diff --git a/.clang-tidy b/.clang-tidy index 428b2f6c..c08efb72 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -22,7 +22,10 @@ Checks: ' -*, - bsl-* + bsl-*, + -bsl-template-generic-param, + -bsl-literals-user-defined, + -bsl-unused-return-value, bugprone-*, -bugprone-branch-clone, cert-*, diff --git a/.doxygen b/.doxygen index 587bee3e..da652504 100644 --- a/.doxygen +++ b/.doxygen @@ -813,7 +813,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # NOTE: If this tag is empty the current directory is searched. -INPUT = kernel loader runtime syscall vmmctl +INPUT = example kernel loader runtime syscall vmmctl # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -913,7 +913,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = */backup/* \ +EXCLUDE_PATTERNS = */test/* \ */cmake/* \ */docs/* \ diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 1a93d41e..067d5252 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -63,7 +63,7 @@ jobs: sudo tar -xzvf hypervisor/utils/linux/llvm-bareflank.tar.gz -C /usr/lib/ export PATH="/usr/lib/llvm-bareflank/bin:$PATH" mkdir build && cd build - cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=CLANG_TIDY -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON ../hypervisor + cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=CLANG_TIDY -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON -DBSL_DEBUG_LEVEL=bsl::VVV ../hypervisor ninja shell: bash @@ -81,7 +81,7 @@ jobs: - name: Validate ASAN run: | mkdir build && cd build - cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=ASAN -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON ../hypervisor + cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=ASAN -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON -DBSL_DEBUG_LEVEL=bsl::VVV ../hypervisor ninja ninja unittest shell: bash @@ -100,7 +100,7 @@ jobs: - name: Validate UBSAN run: | mkdir build && cd build - cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=UBSAN -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON ../hypervisor + cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=UBSAN -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON -DBSL_DEBUG_LEVEL=bsl::VVV ../hypervisor ninja ninja unittest shell: bash @@ -137,34 +137,35 @@ jobs: - name: Validate Debug Build run: | mkdir build && cd build - cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON ../hypervisor + cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_EXAMPLES=ON -DBUILD_TESTS=ON -DBSL_DEBUG_LEVEL=bsl::VVV ../hypervisor ninja ninja unittest shell: bash - # Codecov: - # runs-on: ubuntu-20.04 - # steps: - # - uses: actions/checkout@v2 - # with: - # path: hypervisor - # - name: Setup - # run: | - # sudo apt-get update - # sudo apt-get install -y clang lld cmake ninja-build - # wget https://github.com/mozilla/grcov/releases/download/v0.5.9/grcov-linux-x86_64.tar.bz2 - # tar xvf grcov-linux-x86_64.tar.bz2 - # sudo mv grcov /usr/bin/ - # shell: bash - # - name: Gather Codecov Info - # run: | - # mkdir build && cd build - # cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=CODECOV -DBUILD_TESTS=ON ../hypervisor - # ninja - # ninja codecov-info - # shell: bash - # - name: Upload Codecov Info - # run: | - # cd build - # ninja codecov-upload-ci - # shell: bash + Codecov: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + with: + path: hypervisor + - name: Setup + run: | + sudo apt-get update + sudo apt-get install -y clang cmake ninja-build llvm + wget https://github.com/mozilla/grcov/releases/download/v0.8.0/grcov-linux-x86_64.tar.bz2 + tar xvf grcov-linux-x86_64.tar.bz2 + sudo mv grcov /usr/bin/ + sudo rm /usr/bin/gcov + sudo ln -s /usr/bin/llvm-cov-10 /usr/bin/gcov + shell: bash + - name: Gather Codecov Info + run: | + mkdir build && cd build + cmake -GNinja -DCMAKE_CXX_COMPILER="clang++" -DCMAKE_BUILD_TYPE=CODECOV -DBUILD_TESTS=ON -DBSL_DEBUG_LEVEL=bsl::VVV ../hypervisor + ninja + shell: bash + - name: Upload Codecov Info + run: | + cd build + ninja codecov-upload-ci + shell: bash diff --git a/.gitignore b/.gitignore index 70efc526..a86164fb 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,8 @@ build/ site/ doxygen_output/ +grcov/ +genhtml/ # Linux Loader loader/**/*.symvers diff --git a/CMakeLists.txt b/CMakeLists.txt index 02a90ae1..5232ab03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,26 +20,37 @@ # SOFTWARE. cmake_minimum_required(VERSION 3.13) -project(hypervisor CXX) +project(hypervisor C CXX ASM) include(${CMAKE_CURRENT_LIST_DIR}/cmake/init_build.cmake) -if(HYPERVISOR_BUILD_LOADER) - add_subdirectory(loader) -endif() +if(NOT CMAKE_BUILD_TYPE STREQUAL CODECOV) + if(HYPERVISOR_BUILD_LOADER) + add_subdirectory(loader) + endif() -if(HYPERVISOR_BUILD_VMMCTL) - add_subdirectory(vmmctl) -endif() + if(HYPERVISOR_BUILD_VMMCTL) + add_subdirectory(vmmctl) + endif() -if(HYPERVISOR_BUILD_MICROKERNEL) - hypervisor_add_mk_cross_compile(cmake/mk_cross_compile) -endif() + if(HYPERVISOR_BUILD_MICROKERNEL) + hypervisor_add_mk_cross_compile(cmake/mk_cross_compile) + endif() -if(HYPERVISOR_BUILD_EXAMPLES OR DEFINED HYPERVISOR_EXTENSIONS_DIR) hypervisor_add_ext_cross_compile(cmake/ext_cross_compile) + + if(BUILD_TESTS AND NOT HYPERVISOR_BUILD_TESTS_OVERRIDE) + include(kernel/integration/integration_targets.cmake) + endif() endif() -if(HYPERVISOR_BUILD_EFI) - hypervisor_add_efi_cross_compile(cmake/efi_cross_compile) +if(NOT CMAKE_BUILD_TYPE STREQUAL RELEASE AND NOT CMAKE_BUILD_TYPE STREQUAL MINSIZEREL) + if(BUILD_TESTS AND NOT HYPERVISOR_BUILD_TESTS_OVERRIDE) + add_subdirectory(example/default/test) + add_subdirectory(kernel/test) + # add_subdirectory(loader/test) + add_subdirectory(runtime/test) + add_subdirectory(syscall/test) + add_subdirectory(vmmctl/test) + endif() endif() diff --git a/README.md b/README.md index ab8df9e9..6ddb6b47 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,30 @@ ![Bareflank](https://github.com/Bareflank/hypervisor/raw/master/.github/images/hypervisor_logo.png) ## Description -**Warning:** The master branch is under heavy development as we work to complete Bareflank 3.0. For now, you might want to consider one of our offical releases until Bareflank 3.0 is complete . +The Bareflank Hypervisor is an open source hypervisor Software Development Toolkit (SDK), led by Assured Information Security, Inc. (AIS), that provides the tools needed to rapidly prototype and create your own hypervisor on 64bit versions of Intel, AMD and ARMv8 CPUs (RISC-V and PowerPC also planned). The Bareflank SDK is intended for instructional/research purposes as it only provides enough virtualization support to start/stop a hypervisor. Bareflank can also be used as the foundation to create your own, fully functional hypervisor as it uses the MIT license, includes 100% unit test coverage and compliance for AUTOSAR and ASIL/D. If you are looking for a complete hypervisor (and not an SDK), please see [MicroV](https://github.com/Bareflank/microv). If you are looking for a minimal SDK for education or to perform research, this is the project for you. If you are simply looking for a reference hypervisor, please see [SimpleVisor](https://github.com/ionescu007/SimpleVisor). -The Bareflank Hypervisor is an open source hypervisor Software Development Toolkit (SDK), led by Assured Information Security, Inc. (AIS), that provides the tools needed to rapidly prototype and create your own hypervisor. - -Most people think that hypervisors are meant to virtualize servers and provide a means to run Windows on a Mac, but there is a whole field of research where hypervisors are used without guest virtual machines. Since a hypervisor is capable of controlling the host OS running underneath it (so-called "ring -1"), host-only hypervisors support introspection, reverse engineering, anti-virus, containerization, diversity, and even architectural research like [MoRE](https://github.com/ainfosec/MoRE). All of these use cases start the same way, by spending months standing up the hypervisor itself before you can start working on your actual project. Existing open source hypervisors are burdened with legacy support, only support a single operating system or contain unnecessary complexity that make them painful to work with when conducting hypervisor research. - -Instead, Bareflank uses a layered, modular approach, that lets you pick just how much complexity you need in your project: -- [BSL](https://github.com/Bareflank/bsl): provides a header-only, AUTOSAR compliant implementation of a subset of the C++ Standard Library, used to implement Bareflank's C++ components ensuring Bareflank and projects built using Bareflank can support critical systems applications like Automotive. -- [LLVM](https://github.com/Bareflank/llvm-project): provides our custom implementation of the LLVM Clang compiler and associated tools including additional static analysis checks in Clang Tidy to ensure compliance with AUTOSAR. -- [PAL](https://github.com/Bareflank/pal): provides auto-generated intrinsics APIs for Intel, AMD and ARM on any combination of OS (e.g., Windows and Linux), ABI (e.g., SysV and MS64) and programming language (e.g., C, C++ and Python). -- [hypervisor](https://github.com/Bareflank/hypervisor): provides the base SDK including the loader, the Bareflank microkernel and support applications. If all you need is host-only hypervisor support, this is the project to start with. -- [MicroV](https://github.com/Bareflank/microv): provides support for guest VMs, allowing the user to create and execute additional virtual machines. If you need guest VM support, this is the project to start with. - -To support Bareflank's ecosystem, the hypervisor SDK is licensed under MIT, specifically enabling users of the project to both contribute back to the project, but also create proprietary, closed source products that use the Bareflank SDK as their foundation. Feel free to use Bareflank to create your commercial products. All we ask is that if you find a bug or add a feature to the SDK that you consider contributing your changes back to the project. +Bareflank uses a layered, modular approach, that lets you pick just how much complexity you need in your project when creating your own custom hypervisor: +- [BSL](https://github.com/Bareflank/bsl): provides a header-only, AUTOSAR + compliant implementation of a subset of the C++ Standard Library, used to + implement Bareflank's C++ components ensuring Bareflank and projects built + using Bareflank can support critical systems applications. +- [LLVM](https://github.com/Bareflank/llvm-project): provides our custom + implementation of the LLVM Clang-Tidy static analysis tool to ensure + compliance with AUTOSAR. +- [PAL](https://github.com/Bareflank/pal): provides auto-generated intrinsics + APIs for Intel, AMD and ARM on any combination of OS. +- [hypervisor](https://github.com/Bareflank/hypervisor): provides the base SDK + including the loader, the Bareflank microkernel and support applications. + Although this repo is labeled "hypervisor", this repo only provides the base + scaffolding for creating your own hypervisor. If you are in education or + performing research and do not want to deal with the complexity of a fully + functional hypervisor, this repo would be your starting point. By itself, the + code in this repo only implements enough virtualization to start/stop a + hypervisor. +- [MicroV](https://github.com/Bareflank/microv): This is the project led by + Assured Information Security, Inc. (AIS) the provides a fully functional + hypervisor that uses the Bareflank SDK as it's foundation. If you are looking + for an actual hypervisor, this is the project you are looking for. ## **Quick start** ![GitHub release (latest by date)](https://img.shields.io/github/v/release/bareflank/hypervisor?color=brightgreen) @@ -56,6 +66,41 @@ the following videos at [CppCon](https://www.youtube.com/user/CppCon) below: [![CppCon 2017](https://i.imgur.com/nBFD6uA.png)](https://www.youtube.com/watch?v=KdJhQuycD78) [![CppCon 2016](https://i.imgur.com/fwmlOiJ.png)](https://www.youtube.com/watch?v=uQSQy-7lveQ) +## **Important Tips** +Before attempting to use Bareflank, please review the following tips as they can make a huge difference in your initial experience: +- Make sure you are running on a system with a serial port. Which serial port + Bareflank uses can be configured by setting HYPERVISOR_SERIAL_PORT on x86 + or HYPERVISOR_SERIAL_PORTH and HYPERVISOR_SERIAL_PORTL on ARMv8. Cables like + [these](https://www.amazon.com/USB-Serial-Adapter-Modem-9-pin/dp/B008634VJY/ref=sr_1_1_sspa?crid=P21N96MOCMDS&dchild=1&keywords=usb+null+modem+cable&qid=1622226200&sprefix=usb+null+mo%2Caps%2C201&sr=8-1-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUEzNzBLRUcxVzRNOE8zJmVuY3J5cHRlZElkPUEwMTA1Nzg4U0IyM1RPU0NTRjROJmVuY3J5cHRlZEFkSWQ9QTA3OTM4MjVFMzlNSEQ3T1E2MEwmd2lkZ2V0TmFtZT1zcF9hdGYmYWN0aW9uPWNsaWNrUmVkaXJlY3QmZG9Ob3RMb2dDbGljaz10cnVl) + work great. Bareflank uses the following settings (115200 baud rate, 8 data + bits, no parity bits, one stop bit). +- Using PCI serial addon cards will not work with UEFI. These cards need to be + initialized by the OS, logic that Bareflank does not currently contain. + If you are using Bareflank directly from Windows/Linux, these cards will work + fine, but from UEFI, you need a serial port provided on the motherboard. +- The serial output might contain a lot of ANSI color codes if you are using + a terminal that doesn't support ANSI color. To remove these, configure CMake + with -DENABLE_COLOR=OFF. +- Windows Subsystem For Linux v2 is not supported. When this is turned on, + Windows runs under HyperV, which currently does not support nested + virtualization. Furthermore, if you have ever enabled the WSL2, you must + turn HyperV off using `bcdedit /set hypervisorlaunchtype off` as HyperV will + continue to run even if you are no longer using the WSL2. +- When running under Windows, driver issues can be seen by using + [DbgView](https://docs.microsoft.com/en-us/sysinternals/downloads/debugview). + This tool must be run with Admin rights, and you need to turn on kernel + output. Once this is working, you will see error messages coming from the + Windows driver if needed. +- Nested virtualization (i.e., attempting to run Bareflank inside a VM) is + not officially supported, but does work if you know what you are doing. + Specifically, a headless version of Linux 20.04 or higher in VMWare works + with the proper configuration. VirtualBox does not work due to a lack of + supported features and KVM may or may not work (your milage may vary). In + general, you should be using real hardware. +- If you need to compile Bareflank on older versions of Linux, it is possible, + but you will need to update the build tools manually including LLVM 10+ and + CMake 3.13+. + ## **Build Requirements** Currently, the Bareflank hypervisor only supports the Clang/LLVM 10+ compiler. This, however, ensures that the hypervisor can be natively compiled on Windows including support for cross-compiling. Support for other C++20 compilers can be added if needed, just let us know if that is something you need. @@ -208,13 +253,52 @@ The `HYPERVISOR_EXTENSIONS` variable tells CMake what the name of the resulting The rest of the usage instructions above can be used to start/stop your custom hypervisor. For more information about what ABIs the microkernel provides your extension with, please see the [Microkernel Syscall Specification](https://github.com/Bareflank/hypervisor/blob/master/docs/Microkernel%20Syscall%20Specification.md) in the docs folder. We also provide an example implementation of this ABI as a set of C++ APIs that you can use if you would like. This example set of APIs can be seen in the [syscall/include/cpp/mk_interface.hpp](https://github.com/Bareflank/hypervisor/blob/master/syscall/include/cpp/mk_interface.hpp) file. +## **Raspberry Pi 4** +Yes, ARMv8 is supported by Bareflank. Specifically, Bareflank aims to support +systems that adhere to the [ServerReady](https://developer.arm.com/architectures/platform-design/server-systems) +specification using UEFI. To get the Raspberry Pi 4 to run Bareflank, you will +need the following: +- A [Raspberry Pi 4](https://www.raspberrypi.org/products/raspberry-pi-4-desktop-kit/). + Other kits exist, but it is important that you have most of the things that + come with this kit. +- An SD card loaded with [UEFI](https://github.com/pftf/RPi4). The SD card + will only be used to boot UEFI. +- A USB 3.0 USB stick. Make sure it is low profile as all of the USB devices + that will be plugged in get cramped and wide USB sticks will not fit. +- A compatible keyboard and mouse. Not all keyboards seem to work. Likely a + keyboard and mouse that is well supported by Linux will work fine, which + does not include Corsair devices. Or, just buy the kit above which works + great. +- A [USB serial cable](https://www.amazon.com/ADAFRUIT-Industries-954-Serial-Raspberry/dp/B00DJUHGHI/ref=sr_1_3?dchild=1&keywords=raspberry+pi+4+serial+cable&qid=1622228033&sr=8-3) + Do not use the voltage line (the red cable, meaning only use the black, green + and white cables). If you use the voltage line, the Raspberry Pi 4 will be + powered from this USB cable, which causes all sorts of instability issues + including crashing and certain devices not powering on during reboots. + Instead, use the power cable that comes in the kit above, and only use the + USB cable for serial. +- A [power cable switch](https://www.amazon.com/iUniker-Raspberry-Switch-Supply-Type-C/dp/B07V8G2SYZ/ref=sr_1_5?dchild=1&keywords=raspberry+pi+4+power+cable&qid=1622228153&sr=8-5) + is a nice optional feature. Each time you make a mod to the hypervisor you + will need to reboot, and this will prevent you from having to unplug the + Raspberry Pi 4 all the time as it doesn't have a power or reset switch. +- Ubuntu Server 21.04 or higher. This is important. No other versions of Linux + seem to work. Most versions of Linux for the Raspberry Pi 4 as pre-build + images. These images are not compliant with the ServerReady spec and therefore + do not support UEFI. Ubuntu 21.04 Sever Edition has an ISO version for ARM + that installs fine on the Raspberry Pi 4. Install Ubuntu onto the USB stick. + UEFI will make the USB stick FS0, allowing you to use the commands in the + UEFI section of this readme to compile and test. +- Late Launch is not supported, meaning you must use UEFI. + +It is possible that the microkernel is missing APIs for configuring certain +features on the ARMv8 CPU. If this is the case, please feel free to propose +whatever changes are needed to support your research. + ## **Resources** [![Join the chat](https://img.shields.io/badge/chat-on%20Slack-brightgreen.svg)](https://bareflank.herokuapp.com/) The Bareflank hypervisor provides a ton of useful resources to learn how to use the library including: -- **Documentation**: +- **Documentation**: - **Examples**: -- **Unit Tests**: If you have any questions, bugs, or feature requests, please feel free to ask on any of the following: - **Slack**: @@ -244,6 +328,8 @@ If this is the case, disable the default serial device using the following: reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Serial" /f /v "start" /t REG_DWORD /d "4" ``` +See "Important Tips" above for additional details on how to use serial devices. + ## License The Bareflank Hypervisor is licensed under the MIT License. diff --git a/cmake/config/default.cmake b/cmake/config/default.cmake index e29d5d74..236deead 100644 --- a/cmake/config/default.cmake +++ b/cmake/config/default.cmake @@ -21,13 +21,32 @@ include(${bsl_SOURCE_DIR}/cmake/function/bf_add_config.cmake) -option(HYPERVISOR_BUILD_LOADER "Turns on/off building the loader" ON) -option(HYPERVISOR_BUILD_VMMCTL "Turns on/off building the vmmctl" ON) -option(HYPERVISOR_BUILD_MICROKERNEL "Turns on/off building the microkernel" ON) -option(HYPERVISOR_BUILD_EXAMPLES "Turns on/off building the examples" ON) -option(HYPERVISOR_BUILD_EFI "Turns on/off building the EFI loader" OFF) +if(NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") + bf_add_config( + CONFIG_NAME HYPERVISOR_DEFAULT_BUILD_VMMCTL + CONFIG_TYPE BOOL + DEFAULT_VAL ON + DESCRIPTION "Define the default value for HYPERVISOR_BUILD_VMMCTL" + SKIP_VALIDATION + ) +else() + bf_add_config( + CONFIG_NAME HYPERVISOR_DEFAULT_BUILD_EFI + CONFIG_TYPE BOOL + DEFAULT_VAL ON + DESCRIPTION "Define the default value for HYPERVISOR_BUILD_EFI" + SKIP_VALIDATION + ) -if (NOT DEFINED HYPERVISOR_TARGET_ARCH) + set(HYPERVISOR_TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR}) +endif() + +option(HYPERVISOR_BUILD_LOADER "Turns on/off building the loader" ON) +option(HYPERVISOR_BUILD_VMMCTL "Turns on/off building the vmmctl" ${HYPERVISOR_DEFAULT_BUILD_VMMCTL}) +option(HYPERVISOR_BUILD_MICROKERNEL "Turns on/off building the microkernel" ON) +option(HYPERVISOR_BUILD_EFI "Turns on/off building the EFI loader" ${HYPERVISOR_DEFAULT_BUILD_EFI}) + +if(NOT DEFINED HYPERVISOR_TARGET_ARCH) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") execute_process( COMMAND ${CMAKE_CURRENT_LIST_DIR}/../../utils/linux/get_target_arch @@ -47,7 +66,7 @@ else() set(HYPERVISOR_DEFAULT_TARGET_ARCH ${HYPERVISOR_TARGET_ARCH}) endif() -if (NOT DEFINED HYPERVISOR_CXX_LINKER) +if(NOT DEFINED HYPERVISOR_CXX_LINKER) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") set(HYPERVISOR_DEFAULT_CXX_LINKER "ld.lld") elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") @@ -59,7 +78,7 @@ else() set(HYPERVISOR_DEFAULT_CXX_LINKER ${HYPERVISOR_CXX_LINKER}) endif() -if (NOT DEFINED HYPERVISOR_EFI_LINKER) +if(NOT DEFINED HYPERVISOR_EFI_LINKER) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") set(HYPERVISOR_DEFAULT_EFI_LINKER "lld-link") elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") @@ -71,7 +90,7 @@ else() set(HYPERVISOR_DEFAULT_EFI_LINKER ${HYPERVISOR_EFI_LINKER}) endif() -if (NOT DEFINED HYPERVISOR_EFI_FS0) +if(NOT DEFINED HYPERVISOR_EFI_FS0) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") set(HYPERVISOR_DEFAULT_EFI_FS0 "/boot/efi/") elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") @@ -94,7 +113,7 @@ bf_add_config( bf_add_config( CONFIG_NAME HYPERVISOR_EXTENSIONS_DIR CONFIG_TYPE STRING - DEFAULT_VAL "${CMAKE_SOURCE_DIR}/example" + DEFAULT_VAL "${CMAKE_SOURCE_DIR}/example/default" DESCRIPTION "Defines the extension to use" SKIP_VALIDATION ) @@ -104,7 +123,7 @@ bf_add_config( CONFIG_TYPE STRING DEFAULT_VAL ${HYPERVISOR_DEFAULT_TARGET_ARCH} DESCRIPTION "The target architecture for the build" - OPTIONS AuthenticAMD GenuineIntel + OPTIONS AuthenticAMD GenuineIntel aarch64 ) bf_add_config( @@ -112,7 +131,7 @@ bf_add_config( CONFIG_TYPE STRING DEFAULT_VAL ${HYPERVISOR_DEFAULT_CXX_LINKER} DESCRIPTION "Define the linker to use for cross-compiling" - SKIP_VALIDATION + OPTIONS ld.lld ) bf_add_config( @@ -120,7 +139,7 @@ bf_add_config( CONFIG_TYPE STRING DEFAULT_VAL ${HYPERVISOR_DEFAULT_EFI_LINKER} DESCRIPTION "Define the linker to use for linking EFI applications" - SKIP_VALIDATION + OPTIONS lld-link ) bf_add_config( @@ -134,24 +153,58 @@ bf_add_config( bf_add_config( CONFIG_NAME HYPERVISOR_PAGE_SIZE CONFIG_TYPE STRING - DEFAULT_VAL "BSL_PAGE_SIZE" - DESCRIPTION "Defines the hypervisor's page size" - SKIP_VALIDATION + DEFAULT_VAL ${BSL_PAGE_SIZE} + DESCRIPTION "Defines the hypervisor's page size in bytes" + OPTIONS 0x1000 ) bf_add_config( CONFIG_NAME HYPERVISOR_PAGE_SHIFT CONFIG_TYPE STRING DEFAULT_VAL "12" - DESCRIPTION "Defines the hypervisor's page size (as a shift)" + DESCRIPTION "Defines the hypervisor's page size in bytes (as a shift)" + OPTIONS 12 +) + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + bf_add_config( + CONFIG_NAME HYPERVISOR_SERIAL_PORT + CONFIG_TYPE STRING + DEFAULT_VAL "0x03F8" + DESCRIPTION "Defines the hypervisor's serial port" + SKIP_VALIDATION + ) +else() + bf_add_config( + CONFIG_NAME HYPERVISOR_SERIAL_PORTH + CONFIG_TYPE STRING + DEFAULT_VAL "0xFE20" + DESCRIPTION "Defines the upper 16 bits of the hypervisor's UART0 base address (defaults to RPi4)" + SKIP_VALIDATION + ) + + bf_add_config( + CONFIG_NAME HYPERVISOR_SERIAL_PORTL + CONFIG_TYPE STRING + DEFAULT_VAL "0x1000" + DESCRIPTION "Defines the lower 16 bits of the hypervisor's UART0 base address (defaults to RPi4)" + SKIP_VALIDATION + ) +endif() + +bf_add_config( + CONFIG_NAME HYPERVISOR_DEBUG_RING_SIZE + CONFIG_TYPE STRING + DEFAULT_VAL "0x1FFF0" + DESCRIPTION "Defines the hypervisor's debug ring size in bytes" SKIP_VALIDATION ) bf_add_config( - CONFIG_NAME HYPERVISOR_SERIAL_PORT + CONFIG_NAME HYPERVISOR_VMEXIT_LOG_SIZE CONFIG_TYPE STRING - DEFAULT_VAL "0x03F8" - DESCRIPTION "Defines the hypervisor's serial port" + DEFAULT_VAL "5" + DESCRIPTION "Defines the hypervisor's vmexit log size in # of entries" SKIP_VALIDATION ) @@ -160,7 +213,7 @@ bf_add_config( CONFIG_TYPE STRING DEFAULT_VAL "0x800000" DESCRIPTION "Defines the hypervisor's max ELF file size supported" - SKIP_VALIDATION + OPTIONS 0x800000 ) bf_add_config( @@ -203,44 +256,28 @@ bf_add_config( SKIP_VALIDATION ) -bf_add_config( - CONFIG_NAME HYPERVISOR_MAX_VPS_PER_VM - CONFIG_TYPE STRING - DEFAULT_VAL "HYPERVISOR_MAX_PPS" - DESCRIPTION "Defines the hypervisor's max number of virtual processors per VM supported" - SKIP_VALIDATION -) - -bf_add_config( - CONFIG_NAME HYPERVISOR_MAX_VPSS_PER_VP - CONFIG_TYPE STRING - DEFAULT_VAL "2" - DESCRIPTION "Defines the hypervisor's max number of virtual processor states per VP supported" - SKIP_VALIDATION -) - bf_add_config( CONFIG_NAME HYPERVISOR_MAX_VPSS CONFIG_TYPE STRING - DEFAULT_VAL "HYPERVISOR_MAX_VPS * HYPERVISOR_MAX_VPSS_PER_VP" + DEFAULT_VAL ${HYPERVISOR_MAX_VPS} DESCRIPTION "Defines the hypervisor's max number of virtual processor states" SKIP_VALIDATION ) bf_add_config( - CONFIG_NAME HYPERVISOR_DEBUG_RING_SIZE + CONFIG_NAME HYPERVISOR_MK_DIRECT_MAP_ADDR CONFIG_TYPE STRING - DEFAULT_VAL "0x7FF0" - DESCRIPTION "Defines the hypervisor's debug ring size" - SKIP_VALIDATION + DEFAULT_VAL "0x0000400000000000" + DESCRIPTION "Defines an microkernel's default direct map address" + OPTIONS 0x0000400000000000 ) bf_add_config( - CONFIG_NAME HYPERVISOR_DIRECT_MAP_ADDR + CONFIG_NAME HYPERVISOR_MK_DIRECT_MAP_SIZE CONFIG_TYPE STRING - DEFAULT_VAL "0x0000400000000000" - DESCRIPTION "Defines an hypervisor's default direct map address" - SKIP_VALIDATION + DEFAULT_VAL "0x0000200000000000" + DESCRIPTION "Defines an microkernel's default direct map size in bytes" + OPTIONS 0x0000200000000000 ) bf_add_config( @@ -248,7 +285,7 @@ bf_add_config( CONFIG_TYPE STRING DEFAULT_VAL "0x0000008000000000" DESCRIPTION "Defines the microkernel's default stack address" - SKIP_VALIDATION + OPTIONS 0x0000008000000000 ) bf_add_config( @@ -264,31 +301,63 @@ bf_add_config( CONFIG_TYPE STRING DEFAULT_VAL "0x0000028000000000" DESCRIPTION "Defines the microkernel's default code address" - SKIP_VALIDATION + OPTIONS 0x0000028000000000 ) bf_add_config( CONFIG_NAME HYPERVISOR_MK_CODE_SIZE CONFIG_TYPE STRING - DEFAULT_VAL "HYPERVISOR_MAX_ELF_FILE_SIZE" - DESCRIPTION "Defines the microkernel's default code max size" + DEFAULT_VAL ${HYPERVISOR_MAX_ELF_FILE_SIZE} + DESCRIPTION "Defines the microkernel's default code max size in bytes" + OPTIONS ${HYPERVISOR_MAX_ELF_FILE_SIZE} +) + +bf_add_config( + CONFIG_NAME HYPERVISOR_MK_PAGE_POOL_ADDR + CONFIG_TYPE STRING + DEFAULT_VAL ${HYPERVISOR_MK_DIRECT_MAP_ADDR} + DESCRIPTION "Defines the hypervisor's default page pool address" + OPTIONS ${HYPERVISOR_MK_DIRECT_MAP_ADDR} +) + +bf_add_config( + CONFIG_NAME HYPERVISOR_MK_PAGE_POOL_SIZE + CONFIG_TYPE STRING + DEFAULT_VAL "0x8000000" + DESCRIPTION "Defines the hypervisor's default page pool size in bytes" SKIP_VALIDATION ) bf_add_config( - CONFIG_NAME HYPERVISOR_MK_MAP_ADDR + CONFIG_NAME HYPERVISOR_MK_HUGE_POOL_ADDR CONFIG_TYPE STRING - DEFAULT_VAL "0x0000038000000000" - DESCRIPTION "Defines the microkernel's default map address" + DEFAULT_VAL ${HYPERVISOR_MK_DIRECT_MAP_ADDR} + DESCRIPTION "Defines the microkernel's default huge pool address" + OPTIONS ${HYPERVISOR_MK_DIRECT_MAP_ADDR} +) + +bf_add_config( + CONFIG_NAME HYPERVISOR_MK_HUGE_POOL_SIZE + CONFIG_TYPE STRING + DEFAULT_VAL "0x10000" + DESCRIPTION "Defines the microkernel's default huge pool size in bytes" SKIP_VALIDATION ) bf_add_config( - CONFIG_NAME HYPERVISOR_MK_MAP_SIZE + CONFIG_NAME HYPERVISOR_EXT_DIRECT_MAP_ADDR CONFIG_TYPE STRING - DEFAULT_VAL "0x1000000000" - DESCRIPTION "Defines the microkernel's default map max size" - SKIP_VALIDATION + DEFAULT_VAL "0x0000600000000000" + DESCRIPTION "Defines an extension's default direct map address" + OPTIONS 0x0000600000000000 +) + +bf_add_config( + CONFIG_NAME HYPERVISOR_EXT_DIRECT_MAP_SIZE + CONFIG_TYPE STRING + DEFAULT_VAL "0x0000200000000000" + DESCRIPTION "Defines an extension's default direct map size in bytes" + OPTIONS 0x0000200000000000 ) bf_add_config( @@ -296,7 +365,7 @@ bf_add_config( CONFIG_TYPE STRING DEFAULT_VAL "0x0000308000000000" DESCRIPTION "Defines an extension's default stack address" - SKIP_VALIDATION + OPTIONS 0x0000308000000000 ) bf_add_config( @@ -312,15 +381,15 @@ bf_add_config( CONFIG_TYPE STRING DEFAULT_VAL "0x0000328000000000" DESCRIPTION "Defines an extension's default code address" - SKIP_VALIDATION + OPTIONS 0x0000328000000000 ) bf_add_config( CONFIG_NAME HYPERVISOR_EXT_CODE_SIZE CONFIG_TYPE STRING - DEFAULT_VAL "HYPERVISOR_MAX_ELF_FILE_SIZE" - DESCRIPTION "Defines an extension's default code max size" - SKIP_VALIDATION + DEFAULT_VAL ${HYPERVISOR_MAX_ELF_FILE_SIZE} + DESCRIPTION "Defines an extension's default code max size in bytes" + OPTIONS ${HYPERVISOR_MAX_ELF_FILE_SIZE} ) bf_add_config( @@ -328,61 +397,61 @@ bf_add_config( CONFIG_TYPE STRING DEFAULT_VAL "0x0000338000000000" DESCRIPTION "Defines an extension's default TLS address" - SKIP_VALIDATION + OPTIONS 0x0000338000000000 ) bf_add_config( CONFIG_NAME HYPERVISOR_EXT_TLS_SIZE CONFIG_TYPE STRING DEFAULT_VAL "0x2000" - DESCRIPTION "Defines an extension's default TLS size" - SKIP_VALIDATION + DESCRIPTION "Defines an extension's default TLS size in bytes (not modifiable)" + OPTIONS 0x2000 ) bf_add_config( CONFIG_NAME HYPERVISOR_EXT_PAGE_POOL_ADDR CONFIG_TYPE STRING - DEFAULT_VAL "0x0000358000000000" + DEFAULT_VAL ${HYPERVISOR_EXT_DIRECT_MAP_ADDR} DESCRIPTION "Defines an extension's default page pool address" - SKIP_VALIDATION + OPTIONS ${HYPERVISOR_EXT_DIRECT_MAP_ADDR} ) bf_add_config( CONFIG_NAME HYPERVISOR_EXT_PAGE_POOL_SIZE CONFIG_TYPE STRING - DEFAULT_VAL "0x1000000000" - DESCRIPTION "Defines an extension's default page pool max size" - SKIP_VALIDATION + DEFAULT_VAL ${HYPERVISOR_MK_PAGE_POOL_SIZE} + DESCRIPTION "Defines an extension's default page pool max size in bytes" + OPTIONS ${HYPERVISOR_MK_PAGE_POOL_SIZE} +) + +bf_add_config( + CONFIG_NAME HYPERVISOR_EXT_HUGE_POOL_ADDR + CONFIG_TYPE STRING + DEFAULT_VAL ${HYPERVISOR_EXT_DIRECT_MAP_ADDR} + DESCRIPTION "Defines an extension's default huge pool address" + OPTIONS ${HYPERVISOR_EXT_DIRECT_MAP_ADDR} +) + +bf_add_config( + CONFIG_NAME HYPERVISOR_EXT_HUGE_POOL_SIZE + CONFIG_TYPE STRING + DEFAULT_VAL ${HYPERVISOR_MK_HUGE_POOL_SIZE} + DESCRIPTION "Defines an extension's default huge pool max size in bytes" + OPTIONS ${HYPERVISOR_MK_HUGE_POOL_SIZE} ) bf_add_config( CONFIG_NAME HYPERVISOR_EXT_HEAP_POOL_ADDR CONFIG_TYPE STRING - DEFAULT_VAL "0x0000368000000000" - DESCRIPTION "Defines an extension's default heap pool address" - SKIP_VALIDATION + DEFAULT_VAL "0x0000348000000000" + DESCRIPTION "Defines an extension's default heap pool address in bytes" + OPTIONS 0x0000348000000000 ) bf_add_config( CONFIG_NAME HYPERVISOR_EXT_HEAP_POOL_SIZE CONFIG_TYPE STRING - DEFAULT_VAL "0x1000000000" + DEFAULT_VAL ${HYPERVISOR_MK_PAGE_POOL_SIZE} DESCRIPTION "Defines an extension's default heap pool max size" - SKIP_VALIDATION -) - -bf_add_config( - CONFIG_NAME HYPERVISOR_HUGE_POOL_SIZE - CONFIG_TYPE STRING - DEFAULT_VAL "0x10000" - DESCRIPTION "Defines the hypervisor's default huge pool size in bytes" - SKIP_VALIDATION -) - -bf_add_config( - CONFIG_NAME HYPERVISOR_PAGE_POOL_SIZE - CONFIG_TYPE STRING - DEFAULT_VAL "0x2000000" - DESCRIPTION "Defines the hypervisor's default page pool size in bytes" - SKIP_VALIDATION + OPTIONS ${HYPERVISOR_MK_PAGE_POOL_SIZE} ) diff --git a/cmake/depend/bsl.cmake b/cmake/depend/bsl.cmake index b5329e28..0e09ed42 100644 --- a/cmake/depend/bsl.cmake +++ b/cmake/depend/bsl.cmake @@ -22,7 +22,7 @@ FetchContent_Declare( bsl GIT_REPOSITORY https://github.com/bareflank/bsl.git - GIT_TAG 92dff4d9e701b7ae18c9dbdfe579d9f6f2decbb2 + GIT_TAG 5c3c948d44a0cdeb2477b42c1493d88e3268c40d ) FetchContent_GetProperties(bsl) diff --git a/cmake/ext_cross_compile/CMakeLists.txt b/cmake/ext_cross_compile/CMakeLists.txt index f833076f..1082bce7 100644 --- a/cmake/ext_cross_compile/CMakeLists.txt +++ b/cmake/ext_cross_compile/CMakeLists.txt @@ -27,7 +27,23 @@ include(${CMAKE_CURRENT_LIST_DIR}/../init_cross_compile_build.cmake) add_subdirectory(../../loader loader) add_subdirectory(../../runtime runtime) add_subdirectory(../../syscall syscall) +add_subdirectory(../../kernel/integration integration) -if (DEFINED HYPERVISOR_EXTENSIONS_DIR OR NOT HYPERVISOR_BUILD_EXAMPLES_OVERRIDE) +if(DEFINED HYPERVISOR_EXTENSIONS_DIR) add_subdirectory(${HYPERVISOR_EXTENSIONS_DIR} extension) endif() + +# get_filename_component(HYPERVISOR_EXTENSIONS_REALPATH +# "${HYPERVISOR_EXTENSIONS_DIR}" REALPATH BASE_DIR "${CMAKE_CURRENT_LIST_DIR}") +# get_filename_component(HYPERVISOR_DEFAULT_REALPATH +# "../../example/default" REALPATH BASE_DIR "${CMAKE_CURRENT_LIST_DIR}") +# get_filename_component(HYPERVISOR_NESTED_PAGING_REALPATH +# "../../example/nested_paging" REALPATH BASE_DIR "${CMAKE_CURRENT_LIST_DIR}") + +# if(NOT HYPERVISOR_DEFAULT_REALPATH STREQUAL "${HYPERVISOR_EXTENSIONS_REALPATH}") +# add_subdirectory(../../example/default example_default) +# endif() + +# if(NOT HYPERVISOR_NESTED_PAGING_REALPATH STREQUAL "${HYPERVISOR_EXTENSIONS_REALPATH}") +# add_subdirectory(../../example/nested_paging example_nested_paging) +# endif() diff --git a/cmake/function/hypervisor_add_cmake_args.cmake b/cmake/function/hypervisor_add_cmake_args.cmake index b2ad0288..7b59d9b6 100644 --- a/cmake/function/hypervisor_add_cmake_args.cmake +++ b/cmake/function/hypervisor_add_cmake_args.cmake @@ -47,6 +47,17 @@ macro(hypervisor_add_cmake_args) -DBSL_PAGE_SIZE=${BSL_PAGE_SIZE} ) + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + list(APPEND CMAKE_ARGS + -DHYPERVISOR_SERIAL_PORT=${HYPERVISOR_SERIAL_PORT} + ) + else() + list(APPEND CMAKE_ARGS + -DHYPERVISOR_SERIAL_PORTH=${HYPERVISOR_SERIAL_PORTH} + -DHYPERVISOR_SERIAL_PORTL=${HYPERVISOR_SERIAL_PORTL} + ) + endif() + list(APPEND CMAKE_ARGS -DHYPERVISOR_EXTENSIONS=${HYPERVISOR_EXTENSIONS} -DHYPERVISOR_EXTENSIONS_DIR=${HYPERVISOR_EXTENSIONS_DIR} @@ -56,24 +67,27 @@ macro(hypervisor_add_cmake_args) -DHYPERVISOR_EFI_FS0=${HYPERVISOR_EFI_FS0} -DHYPERVISOR_PAGE_SIZE=${HYPERVISOR_PAGE_SIZE} -DHYPERVISOR_PAGE_SHIFT=${HYPERVISOR_PAGE_SHIFT} - -DHYPERVISOR_SERIAL_PORT=${HYPERVISOR_SERIAL_PORT} + -DHYPERVISOR_DEBUG_RING_SIZE=${HYPERVISOR_DEBUG_RING_SIZE} + -DHYPERVISOR_VMEXIT_LOG_SIZE=${HYPERVISOR_VMEXIT_LOG_SIZE} -DHYPERVISOR_MAX_ELF_FILE_SIZE=${HYPERVISOR_MAX_ELF_FILE_SIZE} -DHYPERVISOR_MAX_SEGMENTS=${HYPERVISOR_MAX_SEGMENTS} -DHYPERVISOR_MAX_EXTENSIONS=${HYPERVISOR_MAX_EXTENSIONS} -DHYPERVISOR_MAX_VMS=${HYPERVISOR_MAX_VMS} -DHYPERVISOR_MAX_PPS=${HYPERVISOR_MAX_PPS} -DHYPERVISOR_MAX_VPS=${HYPERVISOR_MAX_VPS} - -DHYPERVISOR_MAX_VPS_PER_VM=${HYPERVISOR_MAX_VPS_PER_VM} - -DHYPERVISOR_MAX_VPSS_PER_VP=${HYPERVISOR_MAX_VPSS_PER_VP} -DHYPERVISOR_MAX_VPSS=${HYPERVISOR_MAX_VPSS} - -DHYPERVISOR_DEBUG_RING_SIZE=${HYPERVISOR_DEBUG_RING_SIZE} - -DHYPERVISOR_DIRECT_MAP_ADDR=${HYPERVISOR_DIRECT_MAP_ADDR} + -DHYPERVISOR_MK_DIRECT_MAP_ADDR=${HYPERVISOR_MK_DIRECT_MAP_ADDR} + -DHYPERVISOR_MK_DIRECT_MAP_SIZE=${HYPERVISOR_MK_DIRECT_MAP_SIZE} -DHYPERVISOR_MK_STACK_ADDR=${HYPERVISOR_MK_STACK_ADDR} -DHYPERVISOR_MK_STACK_SIZE=${HYPERVISOR_MK_STACK_SIZE} -DHYPERVISOR_MK_CODE_ADDR=${HYPERVISOR_MK_CODE_ADDR} -DHYPERVISOR_MK_CODE_SIZE=${HYPERVISOR_MK_CODE_SIZE} - -DHYPERVISOR_MK_MAP_ADDR=${HYPERVISOR_MK_MAP_ADDR} - -DHYPERVISOR_MK_MAP_SIZE=${HYPERVISOR_MK_MAP_SIZE} + -DHYPERVISOR_MK_PAGE_POOL_ADDR=${HYPERVISOR_MK_PAGE_POOL_ADDR} + -DHYPERVISOR_MK_PAGE_POOL_SIZE=${HYPERVISOR_MK_PAGE_POOL_SIZE} + -DHYPERVISOR_MK_HUGE_POOL_ADDR=${HYPERVISOR_MK_HUGE_POOL_ADDR} + -DHYPERVISOR_MK_HUGE_POOL_SIZE=${HYPERVISOR_MK_HUGE_POOL_SIZE} + -DHYPERVISOR_EXT_DIRECT_MAP_ADDR=${HYPERVISOR_EXT_DIRECT_MAP_ADDR} + -DHYPERVISOR_EXT_DIRECT_MAP_SIZE=${HYPERVISOR_EXT_DIRECT_MAP_SIZE} -DHYPERVISOR_EXT_STACK_ADDR=${HYPERVISOR_EXT_STACK_ADDR} -DHYPERVISOR_EXT_STACK_SIZE=${HYPERVISOR_EXT_STACK_SIZE} -DHYPERVISOR_EXT_CODE_ADDR=${HYPERVISOR_EXT_CODE_ADDR} @@ -82,9 +96,9 @@ macro(hypervisor_add_cmake_args) -DHYPERVISOR_EXT_TLS_SIZE=${HYPERVISOR_EXT_TLS_SIZE} -DHYPERVISOR_EXT_PAGE_POOL_ADDR=${HYPERVISOR_EXT_PAGE_POOL_ADDR} -DHYPERVISOR_EXT_PAGE_POOL_SIZE=${HYPERVISOR_EXT_PAGE_POOL_SIZE} + -DHYPERVISOR_EXT_HUGE_POOL_ADDR=${HYPERVISOR_EXT_HUGE_POOL_ADDR} + -DHYPERVISOR_EXT_HUGE_POOL_SIZE=${HYPERVISOR_EXT_HUGE_POOL_SIZE} -DHYPERVISOR_EXT_HEAP_POOL_ADDR=${HYPERVISOR_EXT_HEAP_POOL_ADDR} -DHYPERVISOR_EXT_HEAP_POOL_SIZE=${HYPERVISOR_EXT_HEAP_POOL_SIZE} - -DHYPERVISOR_HUGE_POOL_SIZE=${HYPERVISOR_HUGE_POOL_SIZE} - -DHYPERVISOR_PAGE_POOL_SIZE=${HYPERVISOR_PAGE_POOL_SIZE} ) endmacro(hypervisor_add_cmake_args) diff --git a/cmake/function/hypervisor_add_efi_cross_compile.cmake b/cmake/function/hypervisor_add_efi_cross_compile.cmake index 78321ec0..c497347c 100644 --- a/cmake/function/hypervisor_add_efi_cross_compile.cmake +++ b/cmake/function/hypervisor_add_efi_cross_compile.cmake @@ -38,9 +38,11 @@ function(hypervisor_add_efi_cross_compile SOURCE_DIR) endif() if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/x64/efi.cmake) + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/../cmake/toolchain/x64/efi.cmake) elseif(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") - set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/x64/efi.cmake) + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/../cmake/toolchain/x64/efi.cmake) + elseif(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/../cmake/toolchain/aarch64/efi.cmake) else() message(FATAL_ERROR "Unsupported HYPERVISOR_TARGET_ARCH: ${HYPERVISOR_TARGET_ARCH}") endif() diff --git a/cmake/function/hypervisor_add_ext_cross_compile.cmake b/cmake/function/hypervisor_add_ext_cross_compile.cmake index 64f9e805..3053684e 100644 --- a/cmake/function/hypervisor_add_ext_cross_compile.cmake +++ b/cmake/function/hypervisor_add_ext_cross_compile.cmake @@ -41,6 +41,8 @@ function(hypervisor_add_ext_cross_compile SOURCE_DIR) set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/x64/ext.cmake) elseif(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/x64/ext.cmake) + elseif(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/aarch64/ext.cmake) else() message(FATAL_ERROR "Unsupported HYPERVISOR_TARGET_ARCH: ${HYPERVISOR_TARGET_ARCH}") endif() diff --git a/cmake/function/hypervisor_add_info.cmake b/cmake/function/hypervisor_add_info.cmake index 335862de..97b521b9 100644 --- a/cmake/function/hypervisor_add_info.cmake +++ b/cmake/function/hypervisor_add_info.cmake @@ -90,18 +90,6 @@ macro(hypervisor_add_info) ) endif() - if(HYPERVISOR_BUILD_EXAMPLES) - add_custom_command(TARGET info - COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_BUILD_EXAMPLES ${BF_COLOR_GRN}enabled${BF_COLOR_RST}" - VERBATIM - ) - else() - add_custom_command(TARGET info - COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_BUILD_EXAMPLES ${BF_COLOR_RED}disabled${BF_COLOR_RST}" - VERBATIM - ) - endif() - if(HYPERVISOR_BUILD_EFI) add_custom_command(TARGET info COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_BUILD_EFI ${BF_COLOR_GRN}enabled${BF_COLOR_RST}" @@ -144,8 +132,29 @@ macro(hypervisor_add_info) VERBATIM ) + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + add_custom_command(TARGET info + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_SERIAL_PORT ${BF_COLOR_CYN}${HYPERVISOR_SERIAL_PORT}${BF_COLOR_RST}" + VERBATIM + ) + else() + add_custom_command(TARGET info + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_SERIAL_PORTH ${BF_COLOR_CYN}${HYPERVISOR_SERIAL_PORTH}${BF_COLOR_RST}" + VERBATIM + ) + add_custom_command(TARGET info + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_SERIAL_PORTL ${BF_COLOR_CYN}${HYPERVISOR_SERIAL_PORTL}${BF_COLOR_RST}" + VERBATIM + ) + endif() + add_custom_command(TARGET info - COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_SERIAL_PORT ${BF_COLOR_CYN}${HYPERVISOR_SERIAL_PORT}${BF_COLOR_RST}" + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_DEBUG_RING_SIZE ${BF_COLOR_CYN}${HYPERVISOR_DEBUG_RING_SIZE}${BF_COLOR_RST}" + VERBATIM + ) + + add_custom_command(TARGET info + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_VMEXIT_LOG_SIZE ${BF_COLOR_CYN}${HYPERVISOR_VMEXIT_LOG_SIZE}${BF_COLOR_RST}" VERBATIM ) @@ -179,28 +188,18 @@ macro(hypervisor_add_info) VERBATIM ) - add_custom_command(TARGET info - COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_MAX_VPS_PER_VM ${BF_COLOR_CYN}${HYPERVISOR_MAX_VPS_PER_VM}${BF_COLOR_RST}" - VERBATIM - ) - - add_custom_command(TARGET info - COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_MAX_VPSS_PER_VP ${BF_COLOR_CYN}${HYPERVISOR_MAX_VPSS_PER_VP}${BF_COLOR_RST}" - VERBATIM - ) - add_custom_command(TARGET info COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_MAX_VPSS ${BF_COLOR_CYN}${HYPERVISOR_MAX_VPSS}${BF_COLOR_RST}" VERBATIM ) add_custom_command(TARGET info - COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_DEBUG_RING_SIZE ${BF_COLOR_CYN}${HYPERVISOR_DEBUG_RING_SIZE}${BF_COLOR_RST}" + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_MK_DIRECT_MAP_ADDR ${BF_COLOR_CYN}${HYPERVISOR_MK_DIRECT_MAP_ADDR}${BF_COLOR_RST}" VERBATIM ) add_custom_command(TARGET info - COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_DIRECT_MAP_ADDR ${BF_COLOR_CYN}${HYPERVISOR_DIRECT_MAP_ADDR}${BF_COLOR_RST}" + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_MK_DIRECT_MAP_SIZE ${BF_COLOR_CYN}${HYPERVISOR_MK_DIRECT_MAP_SIZE}${BF_COLOR_RST}" VERBATIM ) @@ -225,12 +224,32 @@ macro(hypervisor_add_info) ) add_custom_command(TARGET info - COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_MK_MAP_ADDR ${BF_COLOR_CYN}${HYPERVISOR_MK_MAP_ADDR}${BF_COLOR_RST}" + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_MK_PAGE_POOL_ADDR ${BF_COLOR_CYN}${HYPERVISOR_MK_PAGE_POOL_ADDR}${BF_COLOR_RST}" VERBATIM ) add_custom_command(TARGET info - COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_MK_MAP_SIZE ${BF_COLOR_CYN}${HYPERVISOR_MK_MAP_SIZE}${BF_COLOR_RST}" + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_MK_PAGE_POOL_SIZE ${BF_COLOR_CYN}${HYPERVISOR_MK_PAGE_POOL_SIZE}${BF_COLOR_RST}" + VERBATIM + ) + + add_custom_command(TARGET info + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_MK_HUGE_POOL_ADDR ${BF_COLOR_CYN}${HYPERVISOR_MK_HUGE_POOL_ADDR}${BF_COLOR_RST}" + VERBATIM + ) + + add_custom_command(TARGET info + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_MK_HUGE_POOL_SIZE ${BF_COLOR_CYN}${HYPERVISOR_MK_HUGE_POOL_SIZE}${BF_COLOR_RST}" + VERBATIM + ) + + add_custom_command(TARGET info + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_EXT_DIRECT_MAP_ADDR ${BF_COLOR_CYN}${HYPERVISOR_EXT_DIRECT_MAP_ADDR}${BF_COLOR_RST}" + VERBATIM + ) + + add_custom_command(TARGET info + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_EXT_DIRECT_MAP_SIZE ${BF_COLOR_CYN}${HYPERVISOR_EXT_DIRECT_MAP_SIZE}${BF_COLOR_RST}" VERBATIM ) @@ -274,6 +293,16 @@ macro(hypervisor_add_info) VERBATIM ) + add_custom_command(TARGET info + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_EXT_HUGE_POOL_ADDR ${BF_COLOR_CYN}${HYPERVISOR_EXT_HUGE_POOL_ADDR}${BF_COLOR_RST}" + VERBATIM + ) + + add_custom_command(TARGET info + COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_EXT_HUGE_POOL_SIZE ${BF_COLOR_CYN}${HYPERVISOR_EXT_HUGE_POOL_SIZE}${BF_COLOR_RST}" + VERBATIM + ) + add_custom_command(TARGET info COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_EXT_HEAP_POOL_ADDR ${BF_COLOR_CYN}${HYPERVISOR_EXT_HEAP_POOL_ADDR}${BF_COLOR_RST}" VERBATIM @@ -284,16 +313,6 @@ macro(hypervisor_add_info) VERBATIM ) - add_custom_command(TARGET info - COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_HUGE_POOL_SIZE ${BF_COLOR_CYN}${HYPERVISOR_HUGE_POOL_SIZE}${BF_COLOR_RST}" - VERBATIM - ) - - add_custom_command(TARGET info - COMMAND ${CMAKE_COMMAND} -E echo "${BF_COLOR_YLW} HYPERVISOR_PAGE_POOL_SIZE ${BF_COLOR_CYN}${HYPERVISOR_PAGE_POOL_SIZE}${BF_COLOR_RST}" - VERBATIM - ) - add_custom_command(TARGET info COMMAND ${CMAKE_COMMAND} -E echo " " VERBATIM diff --git a/cmake/function/hypervisor_add_integration.cmake b/cmake/function/hypervisor_add_integration.cmake new file mode 100644 index 00000000..ed3288cc --- /dev/null +++ b/cmake/function/hypervisor_add_integration.cmake @@ -0,0 +1,69 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Add's An Integration Test Target +# +macro(hypervisor_add_integration NAME HEADERS) + add_executable(integration_${NAME}) + + target_include_directories(integration_${NAME} PRIVATE + support + ) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") + target_include_directories(integration_${NAME} PRIVATE + support/x64 + support/x64/amd + ) + endif() + + if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + target_include_directories(integration_${NAME} PRIVATE + support/x64 + support/x64/intel + ) + endif() + + if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + target_include_directories(integration_${NAME} PRIVATE + support/arm/aarch64 + ) + endif() + + target_sources(integration_${NAME} PRIVATE + ${NAME}.cpp + ) + + set_property(SOURCE ${NAME} APPEND PROPERTY OBJECT_DEPENDS ${${HEADERS}}) + + target_link_libraries(integration_${NAME} PRIVATE + runtime + bsl + loader + syscall + ) + + if(CMAKE_BUILD_TYPE STREQUAL RELEASE OR CMAKE_BUILD_TYPE STREQUAL MINSIZEREL) + add_custom_command(TARGET integration_${NAME} POST_BUILD COMMAND ${CMAKE_STRIP} integration_${NAME}) + endif() + + install(TARGETS integration_${NAME} DESTINATION bin) +endmacro(hypervisor_add_integration) diff --git a/cmake/function/hypervisor_add_integration_target.cmake b/cmake/function/hypervisor_add_integration_target.cmake new file mode 100644 index 00000000..6c241190 --- /dev/null +++ b/cmake/function/hypervisor_add_integration_target.cmake @@ -0,0 +1,59 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +add_custom_target(integration) + +# Add's An Integration Test Target +# +macro(hypervisor_add_integration_target NAME) + if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + add_custom_target(integration_${NAME} + COMMAND sync + COMMAND sudo vmmctl/vmmctl start ${CMAKE_BINARY_DIR}/mk_cross_compile/bin/kernel ${CMAKE_BINARY_DIR}/ext_cross_compile/bin/integration_${NAME} | true + COMMAND sudo vmmctl/vmmctl dump + VERBATIM + ) + add_custom_target(${NAME} + COMMAND sync + COMMAND sudo vmmctl/vmmctl start ${CMAKE_BINARY_DIR}/mk_cross_compile/bin/kernel ${CMAKE_BINARY_DIR}/ext_cross_compile/bin/integration_${NAME} | true + COMMAND sudo vmmctl/vmmctl dump + VERBATIM + ) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + add_custom_target(integration_${NAME} + COMMAND vmmctl/vmmctl start ${CMAKE_BINARY_DIR}/mk_cross_compile/bin/kernel ${CMAKE_BINARY_DIR}/ext_cross_compile/bin/integration_${NAME} | true + COMMAND vmmctl/vmmctl dump + VERBATIM + ) + add_custom_target(${NAME} + COMMAND vmmctl/vmmctl start ${CMAKE_BINARY_DIR}/mk_cross_compile/bin/kernel ${CMAKE_BINARY_DIR}/ext_cross_compile/bin/integration_${NAME} | true + COMMAND vmmctl/vmmctl dump + VERBATIM + ) + else() + message(FATAL_ERROR "Unsupported CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") + endif() + + add_custom_command(TARGET integration + COMMAND ${CMAKE_COMMAND} --build . --target integration_${NAME} + VERBATIM + ) +endmacro(hypervisor_add_integration_target) diff --git a/cmake/function/hypervisor_add_mk_cross_compile.cmake b/cmake/function/hypervisor_add_mk_cross_compile.cmake index d0046b4e..ef04c0dd 100644 --- a/cmake/function/hypervisor_add_mk_cross_compile.cmake +++ b/cmake/function/hypervisor_add_mk_cross_compile.cmake @@ -41,6 +41,8 @@ function(hypervisor_add_mk_cross_compile SOURCE_DIR) set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/x64/mk.cmake) elseif(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/x64/mk.cmake) + elseif(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/cmake/toolchain/aarch64/mk.cmake) else() message(FATAL_ERROR "Unsupported HYPERVISOR_TARGET_ARCH: ${HYPERVISOR_TARGET_ARCH}") endif() diff --git a/cmake/function/hypervisor_target_source.cmake b/cmake/function/hypervisor_target_source.cmake new file mode 100644 index 00000000..294c4831 --- /dev/null +++ b/cmake/function/hypervisor_target_source.cmake @@ -0,0 +1,29 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Adds a source file to a target, and ensures that dependencies are being +# tracked to deal with a bug with Ninja on Windows where changes to header +# files are not tracked properly. +# +macro(hypervisor_target_source NAME SOURCE_FILE) + target_sources(${NAME} PRIVATE ${SOURCE_FILE}) + set_property(SOURCE ${SOURCE_FILE} APPEND PROPERTY OBJECT_DEPENDS ${ARGN}) +endmacro(hypervisor_target_source) diff --git a/cmake/init_cross_compile_build.cmake b/cmake/init_cross_compile_build.cmake index e689c2c0..9633996b 100644 --- a/cmake/init_cross_compile_build.cmake +++ b/cmake/init_cross_compile_build.cmake @@ -28,7 +28,15 @@ include(${bsl_SOURCE_DIR}/cmake/build_types.cmake) include(${CMAKE_CURRENT_LIST_DIR}/silence.cmake) include(${CMAKE_CURRENT_LIST_DIR}/write_constants.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/write_toolchain_x64_ext_ld.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/write_toolchain_x64_mk_ld.cmake) + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + include(${CMAKE_CURRENT_LIST_DIR}/write_toolchain_x64_ext_ld.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/write_toolchain_x64_mk_ld.cmake) +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + include(${CMAKE_CURRENT_LIST_DIR}/write_toolchain_aarch64_ext_ld.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/write_toolchain_aarch64_mk_ld.cmake) +endif() include(${CMAKE_CURRENT_LIST_DIR}/interface/hypervisor.cmake) diff --git a/cmake/interface/hypervisor.cmake b/cmake/interface/hypervisor.cmake index a6eef94e..981ca8db 100644 --- a/cmake/interface/hypervisor.cmake +++ b/cmake/interface/hypervisor.cmake @@ -21,37 +21,51 @@ add_library(hypervisor INTERFACE) +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + target_compile_definitions(hypervisor INTERFACE + HYPERVISOR_SERIAL_PORT=${HYPERVISOR_SERIAL_PORT} + ) +else() + target_compile_definitions(hypervisor INTERFACE + HYPERVISOR_SERIAL_PORTH=${HYPERVISOR_SERIAL_PORTH} + HYPERVISOR_SERIAL_PORTL=${HYPERVISOR_SERIAL_PORTL} + ) +endif() + target_compile_definitions(hypervisor INTERFACE - HYPERVISOR_PAGE_SIZE=${HYPERVISOR_PAGE_SIZE} - HYPERVISOR_PAGE_SHIFT=${HYPERVISOR_PAGE_SHIFT} - HYPERVISOR_SERIAL_PORT=${HYPERVISOR_SERIAL_PORT} - HYPERVISOR_MAX_ELF_FILE_SIZE=${HYPERVISOR_MAX_ELF_FILE_SIZE} - HYPERVISOR_MAX_SEGMENTS=${HYPERVISOR_MAX_SEGMENTS} - HYPERVISOR_MAX_EXTENSIONS=${HYPERVISOR_MAX_EXTENSIONS} - HYPERVISOR_MAX_VMS=${HYPERVISOR_MAX_VMS} - HYPERVISOR_MAX_PPS=${HYPERVISOR_MAX_PPS} - HYPERVISOR_MAX_VPS=${HYPERVISOR_MAX_VPS} - HYPERVISOR_MAX_VPS_PER_VM=${HYPERVISOR_MAX_VPS_PER_VM} - HYPERVISOR_MAX_VPSS_PER_VP=${HYPERVISOR_MAX_VPSS_PER_VP} - HYPERVISOR_MAX_VPSS=${HYPERVISOR_MAX_VPSS} - HYPERVISOR_DEBUG_RING_SIZE=${HYPERVISOR_DEBUG_RING_SIZE} - HYPERVISOR_DIRECT_MAP_ADDR=${HYPERVISOR_DIRECT_MAP_ADDR} - HYPERVISOR_MK_STACK_ADDR=${HYPERVISOR_MK_STACK_ADDR} - HYPERVISOR_MK_STACK_SIZE=${HYPERVISOR_MK_STACK_SIZE} - HYPERVISOR_MK_CODE_ADDR=${HYPERVISOR_MK_CODE_ADDR} - HYPERVISOR_MK_CODE_SIZE=${HYPERVISOR_MK_CODE_SIZE} - HYPERVISOR_MK_MAP_ADDR=${HYPERVISOR_MK_MAP_ADDR} - HYPERVISOR_MK_MAP_SIZE=${HYPERVISOR_MK_MAP_SIZE} - HYPERVISOR_EXT_STACK_ADDR=${HYPERVISOR_EXT_STACK_ADDR} - HYPERVISOR_EXT_STACK_SIZE=${HYPERVISOR_EXT_STACK_SIZE} - HYPERVISOR_EXT_CODE_ADDR=${HYPERVISOR_EXT_CODE_ADDR} - HYPERVISOR_EXT_CODE_SIZE=${HYPERVISOR_EXT_CODE_SIZE} - HYPERVISOR_EXT_TLS_ADDR=${HYPERVISOR_EXT_TLS_ADDR} - HYPERVISOR_EXT_TLS_SIZE=${HYPERVISOR_EXT_TLS_SIZE} - HYPERVISOR_EXT_PAGE_POOL_ADDR=${HYPERVISOR_EXT_PAGE_POOL_ADDR} - HYPERVISOR_EXT_PAGE_POOL_SIZE=${HYPERVISOR_EXT_PAGE_POOL_SIZE} - HYPERVISOR_EXT_HEAP_POOL_ADDR=${HYPERVISOR_EXT_HEAP_POOL_ADDR} - HYPERVISOR_EXT_HEAP_POOL_SIZE=${HYPERVISOR_EXT_HEAP_POOL_SIZE} - HYPERVISOR_HUGE_POOL_SIZE=${HYPERVISOR_HUGE_POOL_SIZE} - HYPERVISOR_PAGE_POOL_SIZE=${HYPERVISOR_PAGE_POOL_SIZE} + HYPERVISOR_PAGE_SIZE=${HYPERVISOR_PAGE_SIZE}_umax + HYPERVISOR_PAGE_SHIFT=${HYPERVISOR_PAGE_SHIFT}_umax + HYPERVISOR_DEBUG_RING_SIZE=${HYPERVISOR_DEBUG_RING_SIZE}_umax + HYPERVISOR_VMEXIT_LOG_SIZE=${HYPERVISOR_VMEXIT_LOG_SIZE}_umax + HYPERVISOR_MAX_ELF_FILE_SIZE=${HYPERVISOR_MAX_ELF_FILE_SIZE}_umax + HYPERVISOR_MAX_SEGMENTS=${HYPERVISOR_MAX_SEGMENTS}_umax + HYPERVISOR_MAX_EXTENSIONS=${HYPERVISOR_MAX_EXTENSIONS}_umax + HYPERVISOR_MAX_VMS=${HYPERVISOR_MAX_VMS}_umax + HYPERVISOR_MAX_PPS=${HYPERVISOR_MAX_PPS}_umax + HYPERVISOR_MAX_VPS=${HYPERVISOR_MAX_VPS}_umax + HYPERVISOR_MAX_VPSS=${HYPERVISOR_MAX_VPSS}_umax + HYPERVISOR_MK_DIRECT_MAP_ADDR=${HYPERVISOR_MK_DIRECT_MAP_ADDR}_umax + HYPERVISOR_MK_DIRECT_MAP_SIZE=${HYPERVISOR_MK_DIRECT_MAP_SIZE}_umax + HYPERVISOR_MK_STACK_ADDR=${HYPERVISOR_MK_STACK_ADDR}_umax + HYPERVISOR_MK_STACK_SIZE=${HYPERVISOR_MK_STACK_SIZE}_umax + HYPERVISOR_MK_CODE_ADDR=${HYPERVISOR_MK_CODE_ADDR}_umax + HYPERVISOR_MK_CODE_SIZE=${HYPERVISOR_MK_CODE_SIZE}_umax + HYPERVISOR_MK_PAGE_POOL_ADDR=${HYPERVISOR_MK_PAGE_POOL_ADDR}_umax + HYPERVISOR_MK_PAGE_POOL_SIZE=${HYPERVISOR_MK_PAGE_POOL_SIZE}_umax + HYPERVISOR_MK_HUGE_POOL_ADDR=${HYPERVISOR_MK_HUGE_POOL_ADDR}_umax + HYPERVISOR_MK_HUGE_POOL_SIZE=${HYPERVISOR_MK_HUGE_POOL_SIZE}_umax + HYPERVISOR_EXT_DIRECT_MAP_ADDR=${HYPERVISOR_EXT_DIRECT_MAP_ADDR}_umax + HYPERVISOR_EXT_DIRECT_MAP_SIZE=${HYPERVISOR_EXT_DIRECT_MAP_SIZE}_umax + HYPERVISOR_EXT_STACK_ADDR=${HYPERVISOR_EXT_STACK_ADDR}_umax + HYPERVISOR_EXT_STACK_SIZE=${HYPERVISOR_EXT_STACK_SIZE}_umax + HYPERVISOR_EXT_CODE_ADDR=${HYPERVISOR_EXT_CODE_ADDR}_umax + HYPERVISOR_EXT_CODE_SIZE=${HYPERVISOR_EXT_CODE_SIZE}_umax + HYPERVISOR_EXT_TLS_ADDR=${HYPERVISOR_EXT_TLS_ADDR}_umax + HYPERVISOR_EXT_TLS_SIZE=${HYPERVISOR_EXT_TLS_SIZE}_umax + HYPERVISOR_EXT_PAGE_POOL_ADDR=${HYPERVISOR_EXT_PAGE_POOL_ADDR}_umax + HYPERVISOR_EXT_PAGE_POOL_SIZE=${HYPERVISOR_EXT_PAGE_POOL_SIZE}_umax + HYPERVISOR_EXT_HUGE_POOL_ADDR=${HYPERVISOR_EXT_HUGE_POOL_ADDR}_umax + HYPERVISOR_EXT_HUGE_POOL_SIZE=${HYPERVISOR_EXT_HUGE_POOL_SIZE}_umax + HYPERVISOR_EXT_HEAP_POOL_ADDR=${HYPERVISOR_EXT_HEAP_POOL_ADDR}_umax + HYPERVISOR_EXT_HEAP_POOL_SIZE=${HYPERVISOR_EXT_HEAP_POOL_SIZE}_umax ) diff --git a/cmake/silence.cmake b/cmake/silence.cmake index 9a584a0d..a9cb6b5f 100644 --- a/cmake/silence.cmake +++ b/cmake/silence.cmake @@ -48,24 +48,35 @@ hypervisor_silence(HYPERVISOR_EFI_LINKER) hypervisor_silence(HYPERVISOR_EFI_FS0) hypervisor_silence(HYPERVISOR_PAGE_SIZE) hypervisor_silence(HYPERVISOR_PAGE_SHIFT) -hypervisor_silence(HYPERVISOR_SERIAL_PORT) + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + hypervisor_silence(HYPERVISOR_SERIAL_PORT) +else() + hypervisor_silence(HYPERVISOR_SERIAL_PORTH) + hypervisor_silence(HYPERVISOR_SERIAL_PORTL) +endif() + +hypervisor_silence(HYPERVISOR_DEBUG_RING_SIZE) +hypervisor_silence(HYPERVISOR_VMEXIT_LOG_SIZE) hypervisor_silence(HYPERVISOR_MAX_ELF_FILE_SIZE) hypervisor_silence(HYPERVISOR_MAX_SEGMENTS) hypervisor_silence(HYPERVISOR_MAX_EXTENSIONS) hypervisor_silence(HYPERVISOR_MAX_VMS) hypervisor_silence(HYPERVISOR_MAX_PPS) hypervisor_silence(HYPERVISOR_MAX_VPS) -hypervisor_silence(HYPERVISOR_MAX_VPS_PER_VM) -hypervisor_silence(HYPERVISOR_MAX_VPSS_PER_VP) hypervisor_silence(HYPERVISOR_MAX_VPSS) -hypervisor_silence(HYPERVISOR_DEBUG_RING_SIZE) -hypervisor_silence(HYPERVISOR_DIRECT_MAP_ADDR) +hypervisor_silence(HYPERVISOR_MK_DIRECT_MAP_ADDR) +hypervisor_silence(HYPERVISOR_MK_DIRECT_MAP_SIZE) hypervisor_silence(HYPERVISOR_MK_STACK_ADDR) hypervisor_silence(HYPERVISOR_MK_STACK_SIZE) hypervisor_silence(HYPERVISOR_MK_CODE_ADDR) hypervisor_silence(HYPERVISOR_MK_CODE_SIZE) -hypervisor_silence(HYPERVISOR_MK_MAP_ADDR) -hypervisor_silence(HYPERVISOR_MK_MAP_SIZE) +hypervisor_silence(HYPERVISOR_MK_PAGE_POOL_ADDR) +hypervisor_silence(HYPERVISOR_MK_PAGE_POOL_SIZE) +hypervisor_silence(HYPERVISOR_MK_HUGE_POOL_ADDR) +hypervisor_silence(HYPERVISOR_MK_HUGE_POOL_SIZE) +hypervisor_silence(HYPERVISOR_EXT_DIRECT_MAP_ADDR) +hypervisor_silence(HYPERVISOR_EXT_DIRECT_MAP_SIZE) hypervisor_silence(HYPERVISOR_EXT_STACK_ADDR) hypervisor_silence(HYPERVISOR_EXT_STACK_SIZE) hypervisor_silence(HYPERVISOR_EXT_CODE_ADDR) @@ -74,7 +85,7 @@ hypervisor_silence(HYPERVISOR_EXT_TLS_ADDR) hypervisor_silence(HYPERVISOR_EXT_TLS_SIZE) hypervisor_silence(HYPERVISOR_EXT_PAGE_POOL_ADDR) hypervisor_silence(HYPERVISOR_EXT_PAGE_POOL_SIZE) +hypervisor_silence(HYPERVISOR_EXT_HUGE_POOL_ADDR) +hypervisor_silence(HYPERVISOR_EXT_HUGE_POOL_SIZE) hypervisor_silence(HYPERVISOR_EXT_HEAP_POOL_ADDR) hypervisor_silence(HYPERVISOR_EXT_HEAP_POOL_SIZE) -hypervisor_silence(HYPERVISOR_HUGE_POOL_SIZE) -hypervisor_silence(HYPERVISOR_PAGE_POOL_SIZE) diff --git a/cmake/target/dump.cmake b/cmake/target/dump.cmake index 16333527..bfc6b9d4 100644 --- a/cmake/target/dump.cmake +++ b/cmake/target/dump.cmake @@ -19,7 +19,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -if(HYPERVISOR_BUILD_VMMCTL) +if(HYPERVISOR_BUILD_VMMCTL AND NOT HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_custom_target(dump COMMAND sudo vmmctl/vmmctl dump diff --git a/cmake/target/loader_build.cmake b/cmake/target/loader_build.cmake index c14e99f7..6b485abf 100644 --- a/cmake/target/loader_build.cmake +++ b/cmake/target/loader_build.cmake @@ -19,7 +19,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -if(HYPERVISOR_BUILD_LOADER) +if(HYPERVISOR_BUILD_LOADER AND NOT HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_custom_target(loader_build COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_LIST_DIR}/../../loader/linux make CMAKE_BINARY_DIR='${CMAKE_BINARY_DIR}' diff --git a/cmake/target/loader_clean.cmake b/cmake/target/loader_clean.cmake index b4737175..52af5aaf 100644 --- a/cmake/target/loader_clean.cmake +++ b/cmake/target/loader_clean.cmake @@ -19,7 +19,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -if(HYPERVISOR_BUILD_LOADER) +if(HYPERVISOR_BUILD_LOADER AND NOT HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_custom_target(loader_clean COMMAND ${CMAKE_COMMAND} --build . --target loader_unload diff --git a/cmake/target/loader_load.cmake b/cmake/target/loader_load.cmake index 7536c40c..0557bcc3 100644 --- a/cmake/target/loader_load.cmake +++ b/cmake/target/loader_load.cmake @@ -19,7 +19,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -if(HYPERVISOR_BUILD_LOADER) +if(HYPERVISOR_BUILD_LOADER AND NOT HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_custom_target(loader_load COMMAND ${CMAKE_COMMAND} --build . --target loader_build diff --git a/cmake/target/loader_quick.cmake b/cmake/target/loader_quick.cmake index 95959703..fcaa9277 100644 --- a/cmake/target/loader_quick.cmake +++ b/cmake/target/loader_quick.cmake @@ -19,7 +19,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -if(HYPERVISOR_BUILD_LOADER) +if(HYPERVISOR_BUILD_LOADER AND NOT HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") add_custom_target(loader_quick COMMAND ${CMAKE_COMMAND} --build . --target loader_clean COMMAND ${CMAKE_COMMAND} --build . --target loader_load diff --git a/cmake/target/loader_unload.cmake b/cmake/target/loader_unload.cmake index 03d8d31c..71a374f8 100644 --- a/cmake/target/loader_unload.cmake +++ b/cmake/target/loader_unload.cmake @@ -19,7 +19,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -if(HYPERVISOR_BUILD_LOADER) +if(HYPERVISOR_BUILD_LOADER AND NOT HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_custom_target(loader_unload COMMAND sync diff --git a/cmake/target/start.cmake b/cmake/target/start.cmake index 57e01db0..37902d0b 100644 --- a/cmake/target/start.cmake +++ b/cmake/target/start.cmake @@ -19,7 +19,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -if(HYPERVISOR_BUILD_VMMCTL) +if(HYPERVISOR_BUILD_VMMCTL AND NOT HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_custom_target(start COMMAND sync diff --git a/cmake/target/stop.cmake b/cmake/target/stop.cmake index d5ba820a..219b0a58 100644 --- a/cmake/target/stop.cmake +++ b/cmake/target/stop.cmake @@ -19,7 +19,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -if(HYPERVISOR_BUILD_VMMCTL) +if(HYPERVISOR_BUILD_VMMCTL AND NOT HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") add_custom_target(stop COMMAND sync diff --git a/cmake/toolchain/aarch64/efi.cmake b/cmake/toolchain/aarch64/efi.cmake new file mode 100644 index 00000000..4309cbc8 --- /dev/null +++ b/cmake/toolchain/aarch64/efi.cmake @@ -0,0 +1,69 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_C_COMPILER_WORKS 1) + +string(CONCAT HYPERVISOR_EFI_C_FLAGS + "--target=aarch64-unknown-windows " + "-ffreestanding " + "-fshort-wchar " + "-mno-implicit-float " +) + +string(CONCAT HYPERVISOR_EFI_LINK_FLAGS + "--target=aarch64-unknown-windows " + "-nostdlib " + "-Wl,-entry:efi_main " + "-Wl,-subsystem:efi_application " + "-fuse-ld=${HYPERVISOR_EFI_LINKER}" +) + +set(CMAKE_ASM_COMPILE_OBJECT + " ${HYPERVISOR_EFI_C_FLAGS} -o -c ") + +set(CMAKE_C_COMPILE_OBJECT + " ${HYPERVISOR_EFI_C_FLAGS} -o -c ") + +set(CMAKE_C_LINK_EXECUTABLE + " ${HYPERVISOR_EFI_LINK_FLAGS} -o " +) + +################################################################################ +# Hack For Windows +################################################################################ + +# For some reason, CMake on Windows is adding extra stuff to the compiler +# includes and flags. The following fixes this issue by telling CMake not +# to configure the compiler. We need to add C++20 to the command above +# to make this work. +# https://gitlab.kitware.com/cmake/cmake/-/issues/21789 + +set(__COMPILER_CLANG 1) + +macro(__compiler_clang lang) +endmacro() + +macro(__compiler_clang_C_standards lang) +endmacro() + +macro(__compiler_check_default_language_standard lang) +endmacro() diff --git a/cmake/toolchain/aarch64/ext.cmake b/cmake/toolchain/aarch64/ext.cmake new file mode 100644 index 00000000..2dbd9a16 --- /dev/null +++ b/cmake/toolchain/aarch64/ext.cmake @@ -0,0 +1,76 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_CXX_COMPILER_WORKS 1) + +string(CONCAT HYPERVISOR_EXT_CXX_FLAGS + "--target=aarch64-elf " + "-ffreestanding " + "-mno-implicit-float " + "-mcmodel=large " + "-std=c++20 " +) + +if(CMAKE_BUILD_TYPE STREQUAL RELEASE OR CMAKE_BUILD_TYPE STREQUAL MINSIZEREL) + string(CONCAT HYPERVISOR_EXT_CXX_FLAGS + ${HYPERVISOR_EXT_CXX_FLAGS} + "-flto " + ) +endif() + +string(CONCAT HYPERVISOR_EXT_LINK_FLAGS + "-static " + "-nostdlib " + "-z noexecstack " + "-T ${CMAKE_BINARY_DIR}/toolchain/arm/aarch64/ext.ld " +) + +set(CMAKE_ASM_COMPILE_OBJECT + " ${HYPERVISOR_EXT_CXX_FLAGS} -o -c ") + +set(CMAKE_CXX_COMPILE_OBJECT + " ${HYPERVISOR_EXT_CXX_FLAGS} -o -c ") + +set(CMAKE_CXX_LINK_EXECUTABLE + "${HYPERVISOR_CXX_LINKER} ${HYPERVISOR_EXT_LINK_FLAGS} -o " +) + +################################################################################ +# Hack For Windows +################################################################################ + +# For some reason, CMake on Windows is adding extra stuff to the compiler +# includes and flags. The following fixes this issue by telling CMake not +# to configure the compiler. We need to add C++20 to the command above +# to make this work. +# https://gitlab.kitware.com/cmake/cmake/-/issues/21789 + +set(__COMPILER_CLANG 1) + +macro(__compiler_clang lang) +endmacro() + +macro(__compiler_clang_cxx_standards lang) +endmacro() + +macro(__compiler_check_default_language_standard lang) +endmacro() diff --git a/cmake/toolchain/aarch64/mk.cmake b/cmake/toolchain/aarch64/mk.cmake new file mode 100644 index 00000000..a0b066d9 --- /dev/null +++ b/cmake/toolchain/aarch64/mk.cmake @@ -0,0 +1,76 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_CXX_COMPILER_WORKS 1) + +string(CONCAT HYPERVISOR_MK_CXX_FLAGS + "--target=aarch64-elf " + "-ffreestanding " + "-mno-implicit-float " + "-mcmodel=large " + "-std=c++20 " +) + +if(CMAKE_BUILD_TYPE STREQUAL RELEASE OR CMAKE_BUILD_TYPE STREQUAL MINSIZEREL) + string(CONCAT HYPERVISOR_MK_CXX_FLAGS + ${HYPERVISOR_MK_CXX_FLAGS} + "-flto " + ) +endif() + +string(CONCAT HYPERVISOR_MK_LINK_FLAGS + "-static " + "-nostdlib " + "-z noexecstack " + "-T ${CMAKE_BINARY_DIR}/toolchain/arm/aarch64/mk.ld " +) + +set(CMAKE_ASM_COMPILE_OBJECT + " ${HYPERVISOR_MK_CXX_FLAGS} -o -c ") + +set(CMAKE_CXX_COMPILE_OBJECT + " ${HYPERVISOR_MK_CXX_FLAGS} -o -c ") + +set(CMAKE_CXX_LINK_EXECUTABLE + "${HYPERVISOR_CXX_LINKER} ${HYPERVISOR_MK_LINK_FLAGS} -o " +) + +################################################################################ +# Hack For Windows +################################################################################ + +# For some reason, CMake on Windows is adding extra stuff to the compiler +# includes and flags. The following fixes this issue by telling CMake not +# to configure the compiler. We need to add C++20 to the command above +# to make this work. +# https://gitlab.kitware.com/cmake/cmake/-/issues/21789 + +set(__COMPILER_CLANG 1) + +macro(__compiler_clang lang) +endmacro() + +macro(__compiler_clang_cxx_standards lang) +endmacro() + +macro(__compiler_check_default_language_standard lang) +endmacro() diff --git a/cmake/toolchain/x64/ext.cmake b/cmake/toolchain/x64/ext.cmake index 5ae21293..aa19cc1c 100644 --- a/cmake/toolchain/x64/ext.cmake +++ b/cmake/toolchain/x64/ext.cmake @@ -40,6 +40,13 @@ string(CONCAT HYPERVISOR_EXT_CXX_FLAGS "-std=c++20 " ) +if(CMAKE_BUILD_TYPE STREQUAL RELEASE OR CMAKE_BUILD_TYPE STREQUAL MINSIZEREL) + string(CONCAT HYPERVISOR_EXT_CXX_FLAGS + ${HYPERVISOR_EXT_CXX_FLAGS} + "-flto " + ) +endif() + string(CONCAT HYPERVISOR_EXT_LINK_FLAGS "-static " "-nostdlib " diff --git a/cmake/toolchain/x64/mk.cmake b/cmake/toolchain/x64/mk.cmake index cbfe8568..8f212ceb 100644 --- a/cmake/toolchain/x64/mk.cmake +++ b/cmake/toolchain/x64/mk.cmake @@ -40,6 +40,13 @@ string(CONCAT HYPERVISOR_MK_CXX_FLAGS "-std=c++20 " ) +if(CMAKE_BUILD_TYPE STREQUAL RELEASE OR CMAKE_BUILD_TYPE STREQUAL MINSIZEREL) + string(CONCAT HYPERVISOR_MK_CXX_FLAGS + ${HYPERVISOR_MK_CXX_FLAGS} + "-flto " + ) +endif() + string(CONCAT HYPERVISOR_MK_LINK_FLAGS "-static " "-nostdlib " diff --git a/cmake/validate.cmake b/cmake/validate.cmake index a4f56cc9..8d3f9374 100644 --- a/cmake/validate.cmake +++ b/cmake/validate.cmake @@ -19,11 +19,69 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + if(HYPERVISOR_BUILD_VMMCTL) + message(FATAL_ERROR "HYPERVISOR_BUILD_VMMCTL is not supported on ARM") + endif() +endif() + list(LENGTH HYPERVISOR_EXTENSIONS HYPERVISOR_EXTENSIONS_LENGTH) if(NOT HYPERVISOR_EXTENSIONS_LENGTH EQUAL 1) message(FATAL_ERROR "More than one extension is currently not supported") endif() -# TODO: -# - Validate the rest of the configuration -# +if(NOT EXISTS "${HYPERVISOR_EXTENSIONS_DIR}") + message(FATAL_ERROR "HYPERVISOR_EXTENSIONS_DIR does not exist: ${HYPERVISOR_EXTENSIONS_DIR}") +endif() + +if(NOT EXISTS "${HYPERVISOR_EXTENSIONS_DIR}/CMakeLists.txt") + message(FATAL_ERROR "HYPERVISOR_EXTENSIONS_DIR does not contain a CMakeLists.txt") +endif() + +if(HYPERVISOR_DEBUG_RING_SIZE LESS 0x1000) + message(FATAL_ERROR "HYPERVISOR_DEBUG_RING_SIZE must be at least a page") +endif() + +if(HYPERVISOR_VMEXIT_LOG_SIZE LESS 1) + message(FATAL_ERROR "HYPERVISOR_VMEXIT_LOG_SIZE must be at least 1") +endif() + +if(HYPERVISOR_MAX_SEGMENTS LESS 2) + message(FATAL_ERROR "HYPERVISOR_MAX_SEGMENTS must be at least 2") +endif() + +if(HYPERVISOR_MAX_EXTENSIONS LESS 1) + message(FATAL_ERROR "HYPERVISOR_MAX_EXTENSIONS must be at least 1") +endif() + +if(HYPERVISOR_MAX_VMS LESS 1) + message(FATAL_ERROR "HYPERVISOR_MAX_VMS must be at least 1") +endif() + +if(HYPERVISOR_MAX_PPS LESS 1) + message(FATAL_ERROR "HYPERVISOR_MAX_PPS must be at least 1") +endif() + +if(HYPERVISOR_MAX_VPS LESS HYPERVISOR_MAX_PPS) + message(FATAL_ERROR "HYPERVISOR_MAX_VPS the same or greater as HYPERVISOR_MAX_PPS") +endif() + +if(HYPERVISOR_MAX_VPSS LESS HYPERVISOR_MAX_VPS) + message(FATAL_ERROR "HYPERVISOR_MAX_VPSS the same or greater as HYPERVISOR_MAX_VPS") +endif() + +if(HYPERVISOR_MK_STACK_SIZE LESS 0x1000) + message(FATAL_ERROR "HYPERVISOR_MK_STACK_SIZE must be at least a page") +endif() + +if(HYPERVISOR_MK_PAGE_POOL_SIZE LESS 0x1000) + message(FATAL_ERROR "HYPERVISOR_MK_PAGE_POOL_SIZE must be at least a page") +endif() + +if(HYPERVISOR_MK_HUGE_POOL_SIZE LESS 0x1000) + message(FATAL_ERROR "HYPERVISOR_MK_HUGE_POOL_SIZE must be at least a page") +endif() + +if(HYPERVISOR_EXT_STACK_SIZE LESS 0x1000) + message(FATAL_ERROR "HYPERVISOR_EXT_STACK_SIZE must be at least a page") +endif() diff --git a/cmake/write_constants.cmake b/cmake/write_constants.cmake index cf3641f7..cae0e167 100644 --- a/cmake/write_constants.cmake +++ b/cmake/write_constants.cmake @@ -30,6 +30,14 @@ if (NOT EXISTS ${CMAKE_BINARY_DIR}/include/constants.h) file(APPEND ${HYPERVISOR_CONSTANTS} "#define CONSTANTS_H\n") file(APPEND ${HYPERVISOR_CONSTANTS} "\n") + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_SERIAL_PORT ${HYPERVISOR_SERIAL_PORT}\n") + else() + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_SERIAL_PORTH ${HYPERVISOR_SERIAL_PORTH}\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_SERIAL_PORTL ${HYPERVISOR_SERIAL_PORTL}\n") + endif() + + file(APPEND ${HYPERVISOR_CONSTANTS} "#ifndef ASSEMBLY\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#include \n") file(APPEND ${HYPERVISOR_CONSTANTS} "\n") @@ -37,24 +45,27 @@ if (NOT EXISTS ${CMAKE_BINARY_DIR}/include/constants.h) file(APPEND ${HYPERVISOR_CONSTANTS} "#define BSL_PAGE_SIZE ((uint64_t)(${BSL_PAGE_SIZE}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_PAGE_SIZE ((uint64_t)(${HYPERVISOR_PAGE_SIZE}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_PAGE_SHIFT ((uint64_t)(${HYPERVISOR_PAGE_SHIFT}))\n") - file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_SERIAL_PORT ((uint16_t)(${HYPERVISOR_SERIAL_PORT}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_DEBUG_RING_SIZE ((uint64_t)(${HYPERVISOR_DEBUG_RING_SIZE}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_VMEXIT_LOG_SIZE ((uint64_t)(${HYPERVISOR_VMEXIT_LOG_SIZE}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MAX_ELF_FILE_SIZE ((uint64_t)(${HYPERVISOR_MAX_ELF_FILE_SIZE}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MAX_SEGMENTS ((uint64_t)(${HYPERVISOR_MAX_SEGMENTS}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MAX_EXTENSIONS ((uint64_t)(${HYPERVISOR_MAX_EXTENSIONS}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MAX_VMS ((uint64_t)(${HYPERVISOR_MAX_VMS}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MAX_PPS ((uint64_t)(${HYPERVISOR_MAX_PPS}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MAX_VPS ((uint64_t)(${HYPERVISOR_MAX_VPS}))\n") - file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MAX_VPS_PER_VM ((uint64_t)(${HYPERVISOR_MAX_VPS_PER_VM}))\n") - file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MAX_VPSS_PER_VP ((uint64_t)(${HYPERVISOR_MAX_VPSS_PER_VP}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MAX_VPSS ((uint64_t)(${HYPERVISOR_MAX_VPSS}))\n") - file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_DEBUG_RING_SIZE ((uint64_t)(${HYPERVISOR_DEBUG_RING_SIZE}))\n") - file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_DIRECT_MAP_ADDR ((uint64_t)(${HYPERVISOR_DIRECT_MAP_ADDR}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_DIRECT_MAP_ADDR ((uint64_t)(${HYPERVISOR_MK_DIRECT_MAP_ADDR}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_DIRECT_MAP_SIZE ((uint64_t)(${HYPERVISOR_MK_DIRECT_MAP_SIZE}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_STACK_ADDR ((uint64_t)(${HYPERVISOR_MK_STACK_ADDR}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_STACK_SIZE ((uint64_t)(${HYPERVISOR_MK_STACK_SIZE}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_CODE_ADDR ((uint64_t)(${HYPERVISOR_MK_CODE_ADDR}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_CODE_SIZE ((uint64_t)(${HYPERVISOR_MK_CODE_SIZE}))\n") - file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_MAP_ADDR ((uint64_t)(${HYPERVISOR_MK_MAP_ADDR}))\n") - file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_MAP_SIZE ((uint64_t)(${HYPERVISOR_MK_MAP_SIZE}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_PAGE_POOL_ADDR ((uint64_t)(${HYPERVISOR_MK_PAGE_POOL_ADDR}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_PAGE_POOL_SIZE ((uint64_t)(${HYPERVISOR_MK_PAGE_POOL_SIZE}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_HUGE_POOL_ADDR ((uint64_t)(${HYPERVISOR_MK_HUGE_POOL_ADDR}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_MK_HUGE_POOL_SIZE ((uint64_t)(${HYPERVISOR_MK_HUGE_POOL_SIZE}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_DIRECT_MAP_ADDR ((uint64_t)(${HYPERVISOR_EXT_DIRECT_MAP_ADDR}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_DIRECT_MAP_SIZE ((uint64_t)(${HYPERVISOR_EXT_DIRECT_MAP_SIZE}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_STACK_ADDR ((uint64_t)(${HYPERVISOR_EXT_STACK_ADDR}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_STACK_SIZE ((uint64_t)(${HYPERVISOR_EXT_STACK_SIZE}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_CODE_ADDR ((uint64_t)(${HYPERVISOR_EXT_CODE_ADDR}))\n") @@ -63,11 +74,23 @@ if (NOT EXISTS ${CMAKE_BINARY_DIR}/include/constants.h) file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_TLS_SIZE ((uint64_t)(${HYPERVISOR_EXT_TLS_SIZE}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_PAGE_POOL_ADDR ((uint64_t)(${HYPERVISOR_EXT_PAGE_POOL_ADDR}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_PAGE_POOL_SIZE ((uint64_t)(${HYPERVISOR_EXT_PAGE_POOL_SIZE}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_HUGE_POOL_ADDR ((uint64_t)(${HYPERVISOR_EXT_HUGE_POOL_ADDR}))\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_HUGE_POOL_SIZE ((uint64_t)(${HYPERVISOR_EXT_HUGE_POOL_SIZE}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_HEAP_POOL_ADDR ((uint64_t)(${HYPERVISOR_EXT_HEAP_POOL_ADDR}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_EXT_HEAP_POOL_SIZE ((uint64_t)(${HYPERVISOR_EXT_HEAP_POOL_SIZE}))\n") - file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_HUGE_POOL_SIZE ((uint64_t)(${HYPERVISOR_HUGE_POOL_SIZE}))\n") - file(APPEND ${HYPERVISOR_CONSTANTS} "#define HYPERVISOR_PAGE_POOL_SIZE ((uint64_t)(${HYPERVISOR_PAGE_POOL_SIZE}))\n") file(APPEND ${HYPERVISOR_CONSTANTS} "\n") file(APPEND ${HYPERVISOR_CONSTANTS} "#endif\n") + file(APPEND ${HYPERVISOR_CONSTANTS} "#endif\n") +endif() + +if (NOT EXISTS ${CMAKE_BINARY_DIR}/include/constants_masm.h) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/include) + set(HYPERVISOR_CONSTANTS ${CMAKE_BINARY_DIR}/include/constants_masm.h) + + file(WRITE ${HYPERVISOR_CONSTANTS} "; ---- AUTO GENERATED ---- \n") + file(APPEND ${HYPERVISOR_CONSTANTS} "\n") + + string(REPLACE "0x" "" HYPERVISOR_SERIAL_PORT_MASM "${HYPERVISOR_SERIAL_PORT}") + file(APPEND ${HYPERVISOR_CONSTANTS} "HYPERVISOR_SERIAL_PORT EQU ${HYPERVISOR_SERIAL_PORT_MASM}h\n") endif() diff --git a/cmake/write_toolchain_aarch64_ext_ld.cmake b/cmake/write_toolchain_aarch64_ext_ld.cmake new file mode 100644 index 00000000..376a6a6e --- /dev/null +++ b/cmake/write_toolchain_aarch64_ext_ld.cmake @@ -0,0 +1,41 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if (NOT EXISTS ${CMAKE_BINARY_DIR}/toolchain/arm/aarch64/ext.ld) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/toolchain) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/toolchain/arm) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/toolchain/arm/aarch64) + set(HYPERVISOR_TOOLCHAIN_X64_MK_LD ${CMAKE_BINARY_DIR}/toolchain/arm/aarch64/ext.ld) + + file(WRITE ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "/* ---- AUTO GENERATED ---- */\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "\n") + + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "ENTRY(_start)\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "\n") + + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "SECTIONS {\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " . = ${HYPERVISOR_EXT_CODE_ADDR};\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .text : ALIGN(0x1000) { *(.text .text.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .rodata : ALIGN(0x1000) { *(.rodata .rodata.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .data : ALIGN(0x1000) { *(.data .data.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .bss : ALIGN(0x1000) { *(.bss .bss.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "}\n") +endif() diff --git a/cmake/write_toolchain_aarch64_mk_ld.cmake b/cmake/write_toolchain_aarch64_mk_ld.cmake new file mode 100644 index 00000000..7cf0b2ba --- /dev/null +++ b/cmake/write_toolchain_aarch64_mk_ld.cmake @@ -0,0 +1,41 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if (NOT EXISTS ${CMAKE_BINARY_DIR}/toolchain/arm/aarch64/mk.ld) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/toolchain) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/toolchain/arm) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/toolchain/arm/aarch64) + set(HYPERVISOR_TOOLCHAIN_X64_MK_LD ${CMAKE_BINARY_DIR}/toolchain/arm/aarch64/mk.ld) + + file(WRITE ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "/* ---- AUTO GENERATED ---- */\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "\n") + + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "ENTRY(mk_main_entry)\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "\n") + + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "SECTIONS {\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " . = ${HYPERVISOR_MK_CODE_ADDR};\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .text : ALIGN(0x1000) { *(.text .text.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .rodata : ALIGN(0x1000) { *(.rodata .rodata.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .data : ALIGN(0x1000) { *(.data .data.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .bss : ALIGN(0x1000) { *(.bss .bss.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "}\n") +endif() diff --git a/cmake/write_toolchain_x64_ext_ld.cmake b/cmake/write_toolchain_x64_ext_ld.cmake index 270780e0..a4645d2d 100644 --- a/cmake/write_toolchain_x64_ext_ld.cmake +++ b/cmake/write_toolchain_x64_ext_ld.cmake @@ -28,45 +28,13 @@ if (NOT EXISTS ${CMAKE_BINARY_DIR}/toolchain/x64/ext.ld) file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "\n") file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "ENTRY(_start)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "OUTPUT_FORMAT(elf64-x86-64)\n") file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "\n") file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "SECTIONS {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " . = ${HYPERVISOR_EXT_CODE_ADDR};\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .text : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.text)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .init : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.init)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .init_array : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.init_array)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .fini : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.fini)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .fini_array : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.fini_array)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .rodata : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.rodata)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .data : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.data)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .bss : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.bss)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .text : ALIGN(0x1000) { *(.text .text.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .rodata : ALIGN(0x1000) { *(.rodata .rodata.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .data : ALIGN(0x1000) { *(.data .data.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .bss : ALIGN(0x1000) { *(.bss .bss.*); }\n") file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "}\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "\n") endif() diff --git a/cmake/write_toolchain_x64_mk_ld.cmake b/cmake/write_toolchain_x64_mk_ld.cmake index 1bc54be2..24affc46 100644 --- a/cmake/write_toolchain_x64_mk_ld.cmake +++ b/cmake/write_toolchain_x64_mk_ld.cmake @@ -28,45 +28,13 @@ if (NOT EXISTS ${CMAKE_BINARY_DIR}/toolchain/x64/mk.ld) file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "\n") file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "ENTRY(mk_main_entry)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "OUTPUT_FORMAT(elf64-x86-64)\n") file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "\n") file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "SECTIONS {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " . = ${HYPERVISOR_MK_CODE_ADDR};\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .text : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.text)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .init : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.init)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .init_array : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.init_array)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .fini : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.fini)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .fini_array : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.fini_array)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .rodata : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.rodata)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .data : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.data)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .bss : ALIGN(${BSL_PAGE_SIZE}) {\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " *(.bss)\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " }\n") - + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .text : ALIGN(0x1000) { *(.text .text.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .rodata : ALIGN(0x1000) { *(.rodata .rodata.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .data : ALIGN(0x1000) { *(.data .data.*); }\n") + file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} " .bss : ALIGN(0x1000) { *(.bss .bss.*); }\n") file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "}\n") - file(APPEND ${HYPERVISOR_TOOLCHAIN_X64_MK_LD} "\n") endif() diff --git a/docs/Failure Analysis.md b/docs/Failure Analysis.md new file mode 100644 index 00000000..3a1766c2 --- /dev/null +++ b/docs/Failure Analysis.md @@ -0,0 +1,36 @@ +## Table of Contents + +# 1. Introduction + +This document defines how failures are handled by the microkernel and what the expected results are. + +# 2. Starting + +TBD + +# 3. Stopping + +TBD + +# 4. Syscalls + +When a syscall is executed it is possible that the microkernel could generate a hardware exception and fail to execute the syscall. If this occurs, the microkernel is designed to return back to the extension with an error code stating that the call to the microkernel failed. + +If a syscall returns BF_STATUS_FAILURE_UNKNOWN, it should be assumed that either an unexpected error has occurred, or a hardware exception has occurred. In either case, the following are the expectations that an extension can make about any given syscall: + +# 4.1 Resource Creation + +Any syscall that creates a resource like bf_vm_op_create_vm, bf_vm_op_create_vp and bf_vm_op_create_vps will leave the internal state of the microkernel the way it was prior to an error. This includes if a hardware exception occurs while attempting to execute the syscall (excluding exceptions like a Machine Check which are unrecoverable by design). It is up to the extension to determine how to proceed. For example, if the extension is implementing guest support and a creation fails for whatever reason, the extension may choose to stop everything, or it may choose to continue the execution of any existing virtual machines and simply fail to create a new one. + +# 4.2 Resource Destruction + +Resource destruction is way more complicated than resource creation. When we create a resource we are simply taking a clean, unused resource and assigning it so the hardest part about creation is resource starvation. Destruction on the other hand has the following conditions that we need to handle: +- Attempting to destroy resources that were never created or cannot be created. For example, if you attempt to destroy a resource that you never created in the first place, destroying a resource that is above the max allowed, or is invalid. +- Attempting to destroy a resource that is still in use. + +In both cases, we need to ensure the microkernel can continue execution without getting into a corrupt state. Any attempt to destroy a resource that was never created or cannot be created will just output an error and move on as there is no state to reverse. If an extension attempts to destroy a resource that is still in use, the extension would be creating a use-after-free bug. Most kernels would just allow the userspace application to crash, become corrupt, etc, but since this is a hypervisor, we need to try to survive this case. To handle this, the microkernel will mark the resource as a "Zombie". + +A zombie resource is any resource that is still in use that an extension tried to destroy. When this happens, the microkernel will not allow the resource to be used. What this means is that any attempt to make a syscall using the ID of a zombied resource will fail. To understand why, think about free() with a memory address that is still in use. Once an extension makes the decision to free a resource, it should never, ever try to use it. The microkernel's job is not to magically allow a freed resource to still be usable, but instead to ensure that it doesn't crash while an extension is in this state. + +A zombie resource cannot be recovered. For example, if an extension tries to destroy a resource that is still in use, and then realizes it should ensure all other resources are removed first and no longer in use, it cannot then turn around and destroy the zombie resource to get it back. Once a resource is destroyed, it is destroyed. The zombie status is used by the microkernel to say that the resource has been leaked, don't touch it because we don't know how to proceed safely with it. Again, a the zombie status is not about magically providing a means for the extension to do really bad things. It is about providing a means to prevent the hypervisor from crashing which is what would normally happen if a use-after-free bug occurs. + diff --git a/docs/IPI Design Doc.md b/docs/IPI Design Doc.md new file mode 100644 index 00000000..fab65023 --- /dev/null +++ b/docs/IPI Design Doc.md @@ -0,0 +1,69 @@ +# IPI Design Doc + +The microkernel needs a way to IPI itself. For example, if an extension decides free a previously allocated page, the microkernel needs to flush the TLB on all cores to ensure the unmap process doesn't result in a use after free bug. + +The problem is, the microkernel is not actually in charge of how virtualization is implemented. Userspace extensions are responsible for this action. This limits what the microkernel is able to use for performing an IPI. + +## Options + +The following documents the options available to the microkernel WRT to how it implements its own IPI mechanism. + +### External Interrupts + +The microkernel could IPI an external interrupt. This is the safest way to IPI another core. The problem is, the hypervisor doesn't own external interrupts in the type 1 case (it does in the type 2 case like KVM for example). In the type 1 case, the root OS (sometimes called the root partition or Dom0) owns all of the external interrupt vectors. If the hypervisor wants to use one of these vectors, it would either need to ask the OS for a vector, or it would need to steal a vector. + +Asking for a vector has a lot of issues. It means that we must trust the root OS to never use this vector itself. It also doesn't help much while the root OS is booting because we would need a way to ask UEFI to give us a vector, and then from there hope this vector is not used by the OS until we have an opportunity to ask for the vector. This problem is easy to solve with a Linux root OS as we can simply hardcode (which is done today) a vector that we can use. On Windows, or some other random OS that we might want to support, this is a problem. + +Stealing the vector is also problematic because we would need to ensure that no external devices are given the vector we decide to steal. With an IOMMU, we could remap a vector that we steal, but this would require that the microkernel is capable of setting up the IOMMU on its own, which again, the userspace extension should be doing, not the microkernel. This also doesn't help us on systems that either do not have an IOMMU, or devices that are not on the PCI bus that are still capable of firing an external interrupt like the APIC and HPET. In other words, this approach would require an enormous amount of emulation in the microkernel which it is not supposed to be doing. + +### NMIs + +We could use an NMI. On Intel, we cannot mask NMIs, and as a result, we are forced the handle them safely already. What this means is, if an NMI fires while the microkernel is running, it records this and turns on the NMI window, which extensions are required to implement on Intel. One AMD, NMIs are blocked using the global interrupt flag, meaning if an NMI were to fire, it is delivered to the guest on the next VMRun. + +The biggest issue with using the NMI method is trying to determine if the NMI came from the hypervisor. NMIs are owned by the root OS. If more than one NMI fires, the second NMI is ignored. On Linux, this is a problem as NMIs fire all the time, which means that the chances of two NMIs colliding is possible. If this occurs while the hypervisor is in the process of handling an IPI, it would result in the NMI the OS is expecting to be dropped. Since NMIs are used by Linux to handle power management, this event would be a real problem. + +### SMIs + +Another option is to IPI an SMI. The problem with this approach is that on Intel, there is no way to trap SMIs. In fact, on Intel, if an SMI occurs, SMM is executed below the hypervisor. We can trap on SMIs on AMD, but an SMI using an IPI would be considered an external SMI, and on AMD, even after the trap, the SMI is held pending, so once you return back to the guest VM, the SMI will be delivered to the guest with no way to prevent this. + +### INIT + +Unlike all of the other interrupts discussed above, INIT is actually owned by the hypervisor. Meaning, unlike the other interrupts, the ability to reset a CPU is up to the hypervisor, and the hypervisor can decide how INIT is implemented. Rarely would a hypervisor actually wish to deliver an INIT to the guest VM and instead it would normally emulate INIT itself. + +Both Intel and AMD support the ability to trap INIT. On Intel, INIT is trapped as it's own VMExit. From there, it is up to the hypervisor to emulate INIT. On AMD, you can let the guest handle INIT, or you can trap INIT. If you trap INIT, the INIT flag is held pending even after the exit. What this means is that once you enable the global interrupt flag, the CPU would be reset. To prevent this, you need to enable R_INIT in the VM_CR MSR. This tells the CPU to deliver the INIT to the CPU as an SX exception. If the SX exception is intercepted as well, it will result in a VMExit and the hypervisor can emulate INIT from there the same way it would for Intel. + +The problem is when SX is delivered to the hypervisor while it is running, and this is really where the nightmare begins. The global interrupt flag doesn't block SX, so like an NMI on Intel, we have to handle it. There are two ways in which we could implement the SX handler: +- If we use an IST, we would end up with the microkernel state becoming corrupt if more than one INIT lands on the CPU in a short period of time. In other words, unless you want to roll the dice, using the IST is not an option. +- If we don't use an IST, it means that whatever stack the CPU is currently using will be used to handle SX. From the hypervisor point of view, this means the stack given to the microkernel, or the stack given to a userspace extension. Since the microkernel doesn't do much, most of the time will be spent in userspace, which means that we are likely to see a userspace stack more often than not. + +If we take option #2, it means that we have to allow SX to write to the userspace stack. How this is done depends on two different scenarios: +- If SMAP is disabled, the userspace stack would be used without an issue. So long as there is enough stack space (including space for more than one SX exception), we are good. The biggest issue with this approach is anything the microkernel puts on the stack will be leaked to userspace. Bareflank implements the hypervisor in userspace to provide a clean way to support extensions, but one great side effect is we can design the system such that we do not need to trust userspace. Although this is not our primary goal, it is something we would like to achieve in time. What this means is we either need to trust userspace, or we need to ensure we don't use the stack when handling SX. +- If SMAP is enabled, an SX would immediately result in a Double Fault. Specifically, when the CPU would attempt to use the userspace stack, it would generate a page fault due to Ring 0 trying to use Ring 3 memory. The double fault handler however uses the IST, which means that any additional SX would not have a kernel stack to use instead of a userspace stack. What this means is that when SMAP is enabled, the CPU will never be allowed to use the userspace stack, and instead would have to execute from the double fault handler. With a carefully crafted double fault handler this may be possible. + +## Intel Approach + +## AMD Approach + +Currently SMAP is disabled in the microkernel to ensure support on devices that do not support SMAP. This is done in two ways: +- On AMD, the loader disables SMAP in CR4. +- On Intel, this is not as simple as Intel requires certain CR4 bits to be enabled while VT-x is in use. It just so happens that on some CPUs, SMAP must be enabled in both the host and the guest state for VMLaunch to succeed (for example, some Atom processors do this). To mitigate this issue, the microkernel also ensures that whenever the microkernel is executing, the AC bit is set. This allows SMAP to technically be enabled, but not enforced. + +With SMAP disabled, it means that we can use the userspace stack for the SX handler. There are two issues with this that we need to mitigate: +- We would need to trust userspace because kernel specific secrets would be stored on the userspace stack. +- We would need a pretty large userspace stack. Specifically, the stack would have to be large enough to handle normal userspace stuff, plus several SX handler workloads if they happen to pile on. + +To mitigate these two issues, this approach will keep the SX handler as simple as possible. Specifically, it would do the following: + +- inc gs:[sx_pending] +- if gs:[sx_lock] not set, jump to RIP in VMRun handler +- iret + +The code above doesn't use the userspace stack at all. It is also quick, so the chances of SX happening more than once are small, but even if it did, there is no issue here. The only stack modifications using the code above are for the IRET instruction itself. Specifically, when the SX exception fired, microcode will place RIP, RSP, RFLAGS and CS/SS onto the stack. The amount of memory used is so small, it introduces very little risk of the stack running out of space, so issue #2 is addressed above. All we have left to worry about is issue #1. Since we were running in userspace, everything pushed to the stack is userspace specific information, so nothing is leaked. + +Well.... that is not actually true. If two SX exceptions fire before we have an opportunity to execute even a single instruction, the kernel's RIP of the SX handler would be leaked. If we implement KASLR, this would provide userspace with a means to detect the location of the kernel. Do we care... no, and here is why: +- Due to how SWAPGS and NMIs do not play nice, we currently leak GS, so if we are ok with leaking GS for now, we should be ok with leaking RIP of the SX handler as well. +- Need be, we can move the SX handler around independent of where KASLR would have put the microkernel, meaning knowing where the SX handler is wouldn't mean you will know where the rest of the microkernel is. + +Ok, so now that we have a way to handle SX, we still need a way to handle the state that SX is setting. Specifically, there are two things in the TLS block that SX is working with +- tls.sx_pending, like the tls.nmi_pending is used to signal that the SX handler has executed. Unlike tls.nmi_pending, tls.sx_pending is a counter so that we can determine if more than one SX handler has executed. +- tls.sx_lock is used to determine if we need to jump or not in the VMRun logic. Specifically, when this bit is set, the SX handler is only allowed to increment tls.sx_pending. When this bit is not set, it will jump to a different return path of the VMRun handler designed to return from VMRun with an INIT intercept exit. We need this bit to ensure that once we have checked to see if an SX handler was fired that if we get an SX exception between the check and when we actually call VMRun that we don't actually call VMRun and instead continue to process exits. Without this, if an SX exception were to fire between when we checked tls.sx_pending and when we execute VMRun, could result in an IPI that would not be serviced until the next VMExit. Since Bareflank is designed to support hypervisors that result in a VMExit infrequently, this could be a real issue, especially if a core is waiting for all of the other cores to sync up as that could produce deadlock. We also have to deal with the case of when VMRun returns with a real exit and when tls.sx_lock has not been set yet. If this occurs, as soon as the SX exception fires, we would end up with an exception because likely the TLS block has not even been loaded yet. diff --git a/docs/Microkernel Syscall Specification.md b/docs/Microkernel Syscall Specification.md index 045c77fe..c1d2b77d 100644 --- a/docs/Microkernel Syscall Specification.md +++ b/docs/Microkernel Syscall Specification.md @@ -5,17 +5,18 @@ - [1.2. Document Revision](#12-document-revision) - [1.3. Glossary](#13-glossary) - [1.4. Scalar Types](#14-scalar-types) - - [1.5. Memory Address Types](#15-memory-address-types) - - [1.6. ID Types](#16-id-types) - - [1.7. Constants, Structures, Enumerations, and Bit Fields](#17-constants-structures-enumerations-and-bit-fields) - - [1.7.1. Null](#171-null) - - [1.7.2. Handle Type](#172-handle-type) - - [1.7.3. Register Type](#173-register-type) - - [1.7.4. Exit Type](#174-exit-type) - - [1.7.5. Bootstrap Callback Handler Type](#175-bootstrap-callback-handler-type) - - [1.7.6. VMExit Callback Handler Type](#176-vmexit-callback-handler-type) - - [1.7.7. Fast Fail Callback Handler Type](#177-fast-fail-callback-handler-type) - - [1.8. Endianness](#18-endianness) + - [1.5. ID Types](#15-id-types) + - [1.6. Constants, Structures, Enumerations, and Bit Fields](#16-constants-structures-enumerations-and-bit-fields) + - [1.6.1. Null](#161-null) + - [1.6.2. Handle Type](#162-handle-type) + - [1.6.3. Register Type](#163-register-type) + - [1.6.4. Exit Type](#164-exit-type) + - [1.6.5. Bootstrap Callback Handler Type](#165-bootstrap-callback-handler-type) + - [1.6.6. VMExit Callback Handler Type](#166-vmexit-callback-handler-type) + - [1.6.7. Fast Fail Callback Handler Type](#167-fast-fail-callback-handler-type) + - [1.7. Invalid ID](#17-invalid-id) + - [1.8. Host PAT (Intel/AMD Only)](#18-host-pat-intelamd-only) + - [1.9. Endianness](#19-endianness) - [2. Syscall Interface](#2-syscall-interface) - [2.1. Legal Syscall Environments](#21-legal-syscall-environments) - [2.2. Syscall Status Codes](#22-syscall-status-codes) @@ -40,6 +41,7 @@ - [2.6.1. TLS Offsets](#261-tls-offsets) - [2.7. Control Syscalls](#27-control-syscalls) - [2.7.1. bf_control_op_exit, OP=0x0, IDX=0x0](#271-bf_control_op_exit-op0x0-idx0x0) + - [2.10.1. bf_control_op_wait, OP=0x0, IDX=0x1](#2101-bf_control_op_wait-op0x0-idx0x1) - [2.8. Handle Syscalls](#28-handle-syscalls) - [2.8.1. bf_handle_op_open_handle, OP=0x1, IDX=0x0](#281-bf_handle_op_open_handle-op0x1-idx0x0) - [2.8.2. bf_handle_op_close_handle, OP=0x1, IDX=0x1](#282-bf_handle_op_close_handle-op0x1-idx0x1) @@ -51,8 +53,10 @@ - [2.9.5. bf_debug_op_dump_vmexit_log, OP=0x2, IDX=0x4](#295-bf_debug_op_dump_vmexit_log-op0x2-idx0x4) - [2.9.6. bf_debug_op_write_c, OP=0x2, IDX=0x5](#296-bf_debug_op_write_c-op0x2-idx0x5) - [2.9.7. bf_debug_op_write_str, OP=0x2, IDX=0x6](#297-bf_debug_op_write_str-op0x2-idx0x6) + - [2.9.8. bf_debug_op_dump_ext, OP=0x2, IDX=0x7](#298-bf_debug_op_dump_ext-op0x2-idx0x7) + - [2.9.9. bf_debug_op_dump_page_pool, OP=0x2, IDX=0x8](#299-bf_debug_op_dump_page_pool-op0x2-idx0x8) + - [2.9.10. bf_debug_op_dump_huge_pool, OP=0x2, IDX=0x9](#2910-bf_debug_op_dump_huge_pool-op0x2-idx0x9) - [2.10. Callback Syscalls](#210-callback-syscalls) - - [2.10.1. bf_callback_op_wait, OP=0x3, IDX=0x0](#2101-bf_callback_op_wait-op0x3-idx0x0) - [2.10.2. bf_callback_op_register_bootstrap, OP=0x3, IDX=0x2](#2102-bf_callback_op_register_bootstrap-op0x3-idx0x2) - [2.10.3. bf_callback_op_register_vmexit, OP=0x3, IDX=0x3](#2103-bf_callback_op_register_vmexit-op0x3-idx0x3) - [2.10.4. bf_callback_op_register_fail, OP=0x3, IDX=0x4](#2104-bf_callback_op_register_fail-op0x3-idx0x4) @@ -64,6 +68,7 @@ - [2.12.1. Virtual Processor ID (VPID)](#2121-virtual-processor-id-vpid) - [2.12.2. bf_vp_op_create_vp, OP=0x5, IDX=0x0](#2122-bf_vp_op_create_vp-op0x5-idx0x0) - [2.12.3. bf_vp_op_destroy_vp, OP=0x5, IDX=0x1](#2123-bf_vp_op_destroy_vp-op0x5-idx0x1) + - [2.12.3. bf_vp_op_migrate, OP=0x5, IDX=0x2](#2123-bf_vp_op_migrate-op0x5-idx0x2) - [2.12.4. Virtual Processor State Syscalls](#2124-virtual-processor-state-syscalls) - [2.12.5. Virtual Processor State ID (VPSID)](#2125-virtual-processor-state-id-vpsid) - [2.12.6. bf_vps_op_create_vps, OP=0x6, IDX=0x0](#2126-bf_vps_op_create_vps-op0x6-idx0x0) @@ -84,17 +89,19 @@ - [2.12.21. bf_vps_op_advance_ip, OP=0x5, IDX=0xF](#21221-bf_vps_op_advance_ip-op0x5-idx0xf) - [2.12.22. bf_vps_op_advance_ip_and_run_current, OP=0x5, IDX=0x10](#21222-bf_vps_op_advance_ip_and_run_current-op0x5-idx0x10) - [2.12.23. bf_vps_op_promote, OP=0x5, IDX=0x11](#21223-bf_vps_op_promote-op0x5-idx0x11) + - [2.12.24. bf_vps_op_clear_vps, OP=0x5, IDX=0x11](#21224-bf_vps_op_clear_vps-op0x5-idx0x11) - [2.13. Intrinsic Syscalls](#213-intrinsic-syscalls) - - [2.13.1. bf_intrinsic_op_read_msr, OP=0x7, IDX=0x0](#2131-bf_intrinsic_op_read_msr-op0x7-idx0x0) - - [2.13.2. bf_intrinsic_op_write_msr, OP=0x7, IDX=0x1](#2132-bf_intrinsic_op_write_msr-op0x7-idx0x1) + - [2.13.1. bf_intrinsic_op_rdmsr, OP=0x7, IDX=0x0](#2131-bf_intrinsic_op_rdmsr-op0x7-idx0x0) + - [2.13.2. bf_intrinsic_op_wrmsr, OP=0x7, IDX=0x1](#2132-bf_intrinsic_op_wrmsr-op0x7-idx0x1) + - [2.13.3. bf_intrinsic_op_invlpga, OP=0x7, IDX=0x2](#2133-bf_intrinsic_op_invlpga-op0x7-idx0x2) + - [2.13.4. bf_intrinsic_op_invept, OP=0x7, IDX=0x3](#2134-bf_intrinsic_op_invept-op0x7-idx0x3) + - [2.13.5. bf_intrinsic_op_invvpid, OP=0x7, IDX=0x4](#2135-bf_intrinsic_op_invvpid-op0x7-idx0x4) - [2.14. Mem Syscalls](#214-mem-syscalls) - [2.14.1. bf_mem_op_alloc_page, OP=0x7, IDX=0x0](#2141-bf_mem_op_alloc_page-op0x7-idx0x0) - [2.14.2. bf_mem_op_free_page, OP=0x7, IDX=0x1](#2142-bf_mem_op_free_page-op0x7-idx0x1) - [2.14.3. bf_mem_op_alloc_huge, OP=0x7, IDX=0x2](#2143-bf_mem_op_alloc_huge-op0x7-idx0x2) - [2.14.4. bf_mem_op_free_huge, OP=0x7, IDX=0x3](#2144-bf_mem_op_free_huge-op0x7-idx0x3) - [2.14.5. bf_mem_op_alloc_heap, OP=0x7, IDX=0x4](#2145-bf_mem_op_alloc_heap-op0x7-idx0x4) - - [2.14.6. bf_mem_op_free_heap, OP=0x7, IDX=0x5](#2146-bf_mem_op_free_heap-op0x7-idx0x5) - - [2.14.7. bf_mem_op_virt_to_phys, OP=0x7, IDX=0x6](#2147-bf_mem_op_virt_to_phys-op0x7-idx0x6) # 1. Introduction @@ -145,17 +152,10 @@ This specification is specific to 64bit Intel and AMD processors conforming to t | bf_uint16_t | uint16_t | Defines an unsigned 16bit integer | | bf_uint32_t | uint32_t | Defines an unsigned 32bit integer | | bf_uint64_t | uint64_t | Defines an unsigned 64bit integer | -| bf_ptr_t | void const * | Defines a raw pointer type | +| bf_ptr_t | void * | Defines a raw pointer type | +| bf_cptr_t | void const * | Defines a raw const pointer type | -## 1.5. Memory Address Types - -| Name | Type | -| :--- | :--- | -| System Physical Address (SPA) | bf_uint64_t | -| Guest Physical Address (GPA) | bf_uint64_t | -| Guest Virtual Address (GVA) | bf_uint64_t | - -## 1.6. ID Types +## 1.5. ID Types | Name | Type | | :--- | :--- | @@ -164,16 +164,16 @@ This specification is specific to 64bit Intel and AMD processors conforming to t | Virtual Processor State ID (VPSID) | bf_uint64_t | | Physical Processor ID (PPID) | bf_uint64_t | -## 1.7. Constants, Structures, Enumerations, and Bit Fields +## 1.6. Constants, Structures, Enumerations, and Bit Fields -### 1.7.1. Null +### 1.6.1. Null **const, void *: BF_NULL** | Value | Description | | :---- | :---------- | | 0 | Defines the value of a null pointer | -### 1.7.2. Handle Type +### 1.6.2. Handle Type The bf_handle_t structure is an opaque structure containing the handle used by most of the syscalls in this specification. The opaque structure is used internally by the C wrapper interface and should not be accessed directly. The C wrapper is allowed to redefine the internal layout of this structure at any time (e.g., the C wrapper might provide an alternative layout for unit testing). @@ -182,7 +182,7 @@ The bf_handle_t structure is an opaque structure containing the handle used by m | :--- | :--- | :----- | :--- | :---------- | | hndl | bf_uint64_t | 0x0 | 8 bytes | The handle returned by bf_handle_op_open_handle | -### 1.7.3. Register Type +### 1.6.3. Register Type Defines which register a syscall is requesting. @@ -263,7 +263,7 @@ Defines which register a syscall is requesting. | bf_reg_t_ia32_pat | 71 | defines ia32_pat register | | bf_reg_t_ia32_debugctl | 72 | defines ia32_debugctl register | -### 1.7.4. Exit Type +### 1.6.4. Exit Type Defines the exit type used by bf_control_op_exit @@ -273,25 +273,53 @@ Defines the exit type used by bf_control_op_exit | bf_exit_status_t_success | 0 | Exit with a success code | | bf_exit_status_t_failure | 1 | Exit with a failure code | -### 1.7.5. Bootstrap Callback Handler Type +### 1.6.5. Bootstrap Callback Handler Type Defines the signature of the bootstrap callback handler **typedef, void(*bf_callback_handler_bootstrap_t)(bf_uint16_t)** -### 1.7.6. VMExit Callback Handler Type +### 1.6.6. VMExit Callback Handler Type Defines the signature of the VM exit callback handler **typedef, void(*bf_callback_handler_vmexit_t)(bsl::bf_uint16_t, bf_uint64_t)** -### 1.7.7. Fast Fail Callback Handler Type +### 1.6.7. Fast Fail Callback Handler Type Defines the signature of the fast fail callback handler -**typedef, void(*bf_callback_handler_fail_t)()** +**typedef, void(*bf_callback_handler_fail_t)(bf_status_t)** -## 1.8. Endianness +## 1.7. Invalid ID + +The following defines an invalid ID which can be used for all ID types. + +**const, bf_uint16_t: BF_INVALID_ID** +| Value | Description | +| :---- | :---------- | +| 0xFFFF | Defines an invalid ID for an extension, VM, VP and VPS | + +**const, bf_uint16_t: BF_BS_PPID** +| Value | Description | +| :---- | :---------- | +| 0x0 | Defines the bootstrap physical processor ID | + +**const, bf_uint16_t: BF_ROOT_VMID** +| Value | Description | +| :---- | :---------- | +| 0x0 | Defines the root virtual machine ID | + +## 1.8. Host PAT (Intel/AMD Only) + +The host PAT has the following layout. Indexes marked as XX are reserved for future use. + +**const, bf_uint64_t: BF_HOST_PAT** +| Value | Description | +| :---- | :---------- | +| 0xXXXXXXXX00XXXX06 | Defines the host PAT value | + +## 1.9. Endianness This document only applies to 64bit Intel and AMD systems conforming to the amd64 architecture. As such, this document conforms to little-endian. @@ -315,21 +343,6 @@ Every syscall returns a bf_status_t to indicate the success or failure of a sysc BF_STATUS_VALUE defines success or which type of error occurred. BF_STATUS_FLAGS provides additional information about why the error occurred. BF_STATUS_FLAGS is optional and used solely for diagnostics. As such, the microkernel may or may not provide it. -**const, bf_uint64_t: BF_STATUS_SIG_MASK** -| Value | Description | -| :---- | :---------- | -| 0xFFFF000000000000 | Defines a mask for BF_STATUS_SIG | - -**const, bf_uint32_t: BF_STATUS_FLAGS_MASK** -| Value | Description | -| :---- | :---------- | -| 0x0000FFFFFFFF0000 | Defines a mask for BF_STATUS_FLAGS | - -**const, bf_uint32_t: BF_STATUS_VALUE_MASK** -| Value | Description | -| :---- | :---------- | -| 0x000000000000FFFF | Defines a mask for BF_STATUS_VALUE | - ### 2.2.1. BF_STATUS_SUCCESS, VALUE=0 **const, bf_status_t: BF_STATUS_SUCCESS** @@ -625,12 +638,39 @@ The following defines the specification IDs used when opening a handle. These pr The microkernel defines a "thread" the same way both Intel and AMD define a thread (i.e., a logical core). For example, some Intel CPUs have 4 cores and 8 threads when hyper-threading is enabled, or 4 cores and 4 threads when hyper-threading is disabled. Each logical core is given one "thread" and that thread always executes on that logical core. The microkernel defines these logical cores as physical processors (i.e., PP). -Although there is only one thread per PP, a thread's ID changes based on the active extension, VM and VP. If a thread's ID changes, it's TLS block does not, meaning an extension is given one TLS block per PP, regardless of which VM or VP is active. +The layout of the TLS block provided to each extension uses a scheme similar to the ELF TLS specification, but with some modifications. Unlike the ELF TLS specification, each TLS block is limited to two pages. The lower half of the page is dedicated to "thread_local" storage. The upper half is defined by this specification, and provides access to registers shared between the microkernel and the extension to improve performance. For example, access to a VM's general purpose registers is available from the TLS block. Each TLS register defined by this specific is an offset into the upper half of the TLS block (which can be located using the fs segment register on Intel/AMD). -In addition, the layout of the TLS block uses a scheme similar to the ELF TLS specification, but with some modifications. Unlike the ELF TLS specification, each TLS block is limited to two pages. The lower half of the page is dedicated to "thread_local" storage. The upper half is defined by this specification, and provides access to registers shared between the microkernel and the extension to improve performance. For example, access to a VM's general purpose registers is available from the TLS block. +**IMPORTANT:** +The general purpose registers are always accessible to an extension to read and write, but it is up to the extension to ensure the correct VPS state is being modified. Accesses to the TLS block modifies the active VPS only. For example, while an extension is executing its bootstrap handler, there is no active VPS, in which case any reads/writes to the general purpose registers from the TLS block will be lost. When an extension is executing from a VMExit handler, reads/writes to the general purpose registers from the TLS block are made to the VPS that generated the VMExit. If an extension then creates a VPS, the only way to modify the general purpose registers for the newly created VPS is through the read_reg/write_reg ABIs. Attempting to use the TLS block will modify the registers for the active VPS, not the newly created VPS. The only way to set a VPS to "active" is to use the run ABI, which on success does not return, meaning the extension has to wait for a VMExit before the newly create VPS's general purpose registers can be accessed from the TLS block. + +Although this seems overly complicated, this optimization works well for the majority of the VMExits an extension will have to handle, especially the VMExits that execute frequently as most of the time an extension will only be modifying the general purpose registers for the active VPS. ### 2.6.1. TLS Offsets -TBD + +**consts, void *: bf_uint64_t** +| Name | Value | Description | +| :--- | :---- | :---------- | +| TLS_OFFSET_RAX | 0x800U | stores the offset for rax | +| TLS_OFFSET_RBX | 0x808U | stores the offset for rbx | +| TLS_OFFSET_RCX | 0x810U | stores the offset for rcx | +| TLS_OFFSET_RDX | 0x818U | stores the offset for rdx | +| TLS_OFFSET_RBP | 0x820U | stores the offset for rbp | +| TLS_OFFSET_RSI | 0x828U | stores the offset for rsi | +| TLS_OFFSET_RDI | 0x830U | stores the offset for rdi | +| TLS_OFFSET_R8 | 0x838U | stores the offset for r8 | +| TLS_OFFSET_R9 | 0x840U | stores the offset for r9 | +| TLS_OFFSET_R10 | 0x848U | stores the offset for r10 | +| TLS_OFFSET_R11 | 0x850U | stores the offset for r11 | +| TLS_OFFSET_R12 | 0x858U | stores the offset for r12 | +| TLS_OFFSET_R13 | 0x860U | stores the offset for r13 | +| TLS_OFFSET_R14 | 0x868U | stores the offset for r14 | +| TLS_OFFSET_R15 | 0x870U | stores the offset for r15 | +| TLS_OFFSET_ACTIVE_EXTID | 0xFF0U | stores the offset of the active extid | +| TLS_OFFSET_ACTIVE_VMID | 0xFF2U | stores the offset of the active vmid | +| TLS_OFFSET_ACTIVE_VPID | 0xFF4U | stores the offset of the active vpid | +| TLS_OFFSET_ACTIVE_VPSID | 0xFF6U | stores the offset of the active vpsid | +| TLS_OFFSET_ACTIVE_PPID | 0xFF8U | stores the offset of the active ppid | +| TLS_OFFSET_ONLINE_PPS | 0xFFAU | stores the number of PPs that are online | ## 2.7. Control Syscalls @@ -643,6 +683,15 @@ This syscall tells the microkernel to stop the execution of an extension, provid | :---- | :---------- | | 0x0000000000000000 | Defines the syscall index for bf_control_op_exit | +### 2.10.1. bf_control_op_wait, OP=0x0, IDX=0x1 + +This syscall tells the microkernel that the extension would like to wait for a callback. This syscall is a blocking syscall that never returns and should be used to return from the _start function. + +**const, bf_uint64_t: BF_CONTROL_OP_WAIT_IDX_VAL** +| Value | Description | +| :---- | :---------- | +| 0x0000000000000001 | Defines the syscall index for bf_control_op_wait | + ## 2.8. Handle Syscalls ### 2.8.1. bf_handle_op_open_handle, OP=0x1, IDX=0x0 @@ -685,9 +734,6 @@ This syscall closes a previously opened handle. This syscall tells the microkernel to output RDI and RSI to the console device the microkernel is currently using for debugging. -**WARNING:** -In production builds of Bareflank, this syscall is not present. - **Input:** | Register Name | Bits | Description | | :------------ | :--- | :---------- | @@ -703,9 +749,6 @@ In production builds of Bareflank, this syscall is not present. This syscall tells the microkernel to output a VM's state to the console device the microkernel is currently using for debugging. -**WARNING:** -In production builds of Bareflank, this syscall is not present. - **Input:** | Register Name | Bits | Description | | :------------ | :--- | :---------- | @@ -720,9 +763,6 @@ In production builds of Bareflank, this syscall is not present. This syscall tells the microkernel to output a VP's state to the console device the microkernel is currently using for debugging. -**WARNING:** -In production builds of Bareflank, this syscall is not present. - **Input:** | Register Name | Bits | Description | | :------------ | :--- | :---------- | @@ -737,9 +777,6 @@ In production builds of Bareflank, this syscall is not present. This syscall tells the microkernel to output a VPS's state to the console device the microkernel is currently using for debugging. -**WARNING:** -In production builds of Bareflank, this syscall is not present. - **Input:** | Register Name | Bits | Description | | :------------ | :--- | :---------- | @@ -752,15 +789,12 @@ In production builds of Bareflank, this syscall is not present. ### 2.9.5. bf_debug_op_dump_vmexit_log, OP=0x2, IDX=0x4 -This syscall tells the microkernel to output the VMExit log. The VMExit log is a chronological log of the "X" number of exits that have occurred. The total number of "X" logs is implementation-defined and not under the control of software. - -**WARNING:** -In production builds of Bareflank, this syscall is not present. +This syscall tells the microkernel to output the VMExit log. The VMExit log is a chronological log of the "X" number of exits that have occurred on a specific physical processor. **Input:** | Register Name | Bits | Description | | :------------ | :--- | :---------- | -| REG0 | 63:0 | The VPID of the VP to dump the log from | +| REG0 | 63:0 | The PPID of the PP to dump the log from | **const, bf_uint64_t: BF_DEBUG_OP_DUMP_VMEXIT_LOG_IDX_VAL** | Value | Description | @@ -796,16 +830,39 @@ This syscall tells the microkernel to output a provided string to the microkerne | :---- | :---------- | | 0x0000000000000006 | Defines the syscall index for bf_debug_op_write_str | -## 2.10. Callback Syscalls +### 2.9.8. bf_debug_op_dump_ext, OP=0x2, IDX=0x7 -### 2.10.1. bf_callback_op_wait, OP=0x3, IDX=0x0 +This syscall tells the microkernel to output an extension's state to the console device the microkernel is currently using for debugging. -This syscall tells the microkernel that the extension would like to wait for a callback. This syscall is a blocking syscall that never returns and should be used to return from the _start function. +**Input:** +| Register Name | Bits | Description | +| :------------ | :--- | :---------- | +| REG0 | 63:0 | The EXTID of the extensions's state to output | -**const, bf_uint64_t: BF_CALLBACK_OP_WAIT_IDX_VAL** +**const, bf_uint64_t: BF_DEBUG_OP_DUMP_EXT_IDX_VAL** | Value | Description | | :---- | :---------- | -| 0x0000000000000000 | Defines the syscall index for bf_callback_op_wait | +| 0x0000000000000007 | Defines the syscall index for bf_debug_op_dump_ext | + +### 2.9.9. bf_debug_op_dump_page_pool, OP=0x2, IDX=0x8 + +This syscall tells the microkernel to output the page pool's stats to the console device the microkernel is currently using for debugging. + +**const, bf_uint64_t: BF_DEBUG_OP_DUMP_PAGE_POOL_IDX_VAL** +| Value | Description | +| :---- | :---------- | +| 0x0000000000000008 | Defines the syscall index for bf_debug_op_dump_page_pool | + +### 2.9.10. bf_debug_op_dump_huge_pool, OP=0x2, IDX=0x9 + +This syscall tells the microkernel to output the huge pool's stats to the console device the microkernel is currently using for debugging. + +**const, bf_uint64_t: BF_DEBUG_OP_DUMP_HUGE_POOL_IDX_VAL** +| Value | Description | +| :---- | :---------- | +| 0x0000000000000009 | Defines the syscall index for bf_debug_op_dump_huge_pool | + +## 2.10. Callback Syscalls ### 2.10.2. bf_callback_op_register_bootstrap, OP=0x3, IDX=0x2 @@ -856,6 +913,8 @@ This syscall tells the microkernel that the extension would like to receive call A Virtual Machine or VM virtually represents a physical computer. Although the microkernel has an internal representation of a VM, it doesn't understand what a VM is outside of resource management, and it is up to the extension to define what a VM is and how it should operate. +One important resource within the microkernel that changes when a VM changes is the direct map each extension is given. When a VM changes, the direct map an extension uses to access physical memory also changes. + ### 2.11.1. Virtual Machine ID (VMID) The Virtual Machine ID (VMID) is a 16bit number that uniquely identifies a VM. @@ -898,7 +957,9 @@ This syscall tells the microkernel to destroy a VM given an ID. ## 2.12. Virtual Processor Syscalls -TODO +A Virtual Processor or VP virtually represents a logical core. Although the microkernel has an internal representation of a VP, it doesn't understand what a VP is outside of resource management, and it is up to the extension to define what a VM is and how it should operate. + +Once a VP is run, it is assigned to the VM it was run on, and cannot be run on any other VM for the remainder of it's lifetime. A VP is also assigned to a specific PP (physical processor). Unlike the assigned VM, the assigned PP can be changed by migrating the VP to another PP. ### 2.12.1. Virtual Processor ID (VPID) @@ -906,12 +967,16 @@ The Virtual Processor ID (VPID) is a 16bit number that uniquely identifies a VP. ### 2.12.2. bf_vp_op_create_vp, OP=0x5, IDX=0x0 -This syscall tells the microkernel to create a VP and return its ID. +This syscall tells the microkernel to create a VP given the IDs of the VM and PP the VP will be assigned to. Upon success, this syscall returns the ID of the newly created VP. **Input:** | Register Name | Bits | Description | | :------------ | :--- | :---------- | | REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | +| REG1 | 15:0 | The ID of the VM to assign the newly created VP to | +| REG1 | 63:16 | REVI | +| REG2 | 15:0 | The ID of the PP to assign the newly created VP to | +| REG2 | 63:16 | REVI | **Output:** | Register Name | Bits | Description | @@ -940,9 +1005,35 @@ This syscall tells the microkernel to destroy a VP given an ID. | :---- | :---------- | | 0x0000000000000001 | Defines the syscall index for bf_vp_op_destroy_vp | +### 2.12.3. bf_vp_op_migrate, OP=0x5, IDX=0x2 + +This syscall tells the microkernel to migrate a VP from one PP to another PP. This function does not execute the VP (use bf_vps_op_run for that), but instead allows bf_vps_op_run to execute a VP on a PP that it was not originally assigned to. + +When a VP is migrated, all of the VPSs that are assigned to the requested VP are also migrated to this new PP as well. From an AMD/Intel point of view, this clears the VMCS/VMCB for each VPS assigned to the VP. On Intel, it also loads the newly cleared VPS and sets the launched state to false, ensuring the next bf_vps_op_run will use VMLaunch instead of VMResume. + +It should be noted that the migration of a VPS from one PP to another does not happen during the execution of this ABI. This ABI simply tells the microkernel that the requested VP may now execute on the requested PP. This will cause a mismatch between the assigned PP for a VP and the assigned PP for a VPS. The microkernel will detect this mismatch when an extension attempts to execute bf_vps_op_run. When this occurs, the microkernel will ensure the VP is being run on the PP it was assigned to during migration, and then it will check to see if the PP of the VPS matches. If it doesn't, it will then perform a migration of that VPS at that time. This ensures that the microkernel is only migrations VPSs when it needs to, and it ensures the VPS is cleared an loaded (in the case of Intel) on the PP it will be executed on, which is a requirement for VMCS migration. An extension can determine which VPSs have been migrated by looking at the assigned PP of a VPS. If it doesn't match the VP it was assigned to, it has not been migrated. Finally, an extension is free to read/write to the VPSs state, even if it has not been migrated. The only requirement for migration is execution (meaning VMRun/VMLaunch/VMResume). + +Any additional migration responsibilities, like TSC synchronization, must be performed by the extension. + +**Input:** +| Register Name | Bits | Description | +| :------------ | :--- | :---------- | +| REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | +| REG1 | 15:0 | The VPID of the VP to migrate | +| REG1 | 63:16 | REVI | +| REG2 | 15:0 | The ID of the PP to assign the provided VP to | +| REG2 | 63:16 | REVI | + +**const, bf_uint64_t: BF_VP_OP_MIGRATE_IDX_VAL** +| Value | Description | +| :---- | :---------- | +| 0x0000000000000002 | Defines the syscall index for bf_vp_op_migrate | + ### 2.12.4. Virtual Processor State Syscalls -TODO +A Virtual Processor State or VPS encapsulates the state associated with a virtual process. For example, on Intel this would be the VMCS, the registers that must be saved that the VMCS does not manage, and the general purpose registers. + +Once a VPS is run, it is assigned to the VP it was run on, and cannot be run on any other VP for the remainder of it's lifetime. Since a VP is also assigned to a specific PP (physical processor), so is the VPS. When a VP is migrated, all VPSs assigned to that VP are also migrated. ### 2.12.5. Virtual Processor State ID (VPSID) @@ -950,12 +1041,16 @@ The Virtual Processor State ID (VPSID) is a 16bit number that uniquely identifie ### 2.12.6. bf_vps_op_create_vps, OP=0x6, IDX=0x0 -This syscall tells the microkernel to create a VPS and return its ID. +This syscall tells the microkernel to create a VPS given the IDs of the VP and PP the VPS will be assigned to. Upon success, this syscall returns the ID of the newly created VPS. **Input:** | Register Name | Bits | Description | | :------------ | :--- | :---------- | | REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | +| REG1 | 15:0 | The ID of the VP to assign the newly created VPS to | +| REG1 | 63:16 | REVI | +| REG2 | 15:0 | The ID of the PP to assign the newly created VPS to | +| REG2 | 63:16 | REVI | **Output:** | Register Name | Bits | Description | @@ -1002,7 +1097,7 @@ This syscall tells the microkernel to initialize a VPS using the root VP state p ### 2.12.9. bf_vps_op_read8, OP=0x6, IDX=0x3 -bf_vps_op_read8 reads an 8bit field from the VPS and returns the value. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). +Reads an 8bit field from the VPS and returns the value. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). **Input:** | Register Name | Bits | Description | @@ -1025,7 +1120,7 @@ bf_vps_op_read8 reads an 8bit field from the VPS and returns the value. The "ind ### 2.12.10. bf_vps_op_read16, OP=0x6, IDX=0x4 -bf_vps_op_read16 reads a 16bit field from the VPS and returns the value. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). +Reads a 16bit field from the VPS and returns the value. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). **Input:** | Register Name | Bits | Description | @@ -1048,7 +1143,7 @@ bf_vps_op_read16 reads a 16bit field from the VPS and returns the value. The "in ### 2.12.11. bf_vps_op_read32, OP=0x6, IDX=0x5 -bf_vps_op_read32 reads a 32bit field from the VPS and returns the value. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). +Reads a 32bit field from the VPS and returns the value. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). **Input:** | Register Name | Bits | Description | @@ -1071,7 +1166,7 @@ bf_vps_op_read32 reads a 32bit field from the VPS and returns the value. The "in ### 2.12.12. bf_vps_op_read64, OP=0x6, IDX=0x6 -bf_vps_op_read64 reads a 64bit field from the VPS and returns the value. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). +Reads a 64bit field from the VPS and returns the value. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). **Input:** | Register Name | Bits | Description | @@ -1093,7 +1188,7 @@ bf_vps_op_read64 reads a 64bit field from the VPS and returns the value. The "in ### 2.12.13. bf_vps_op_write8, OP=0x6, IDX=0x7 -bf_vps_op_write8 writes to an 8bit field in the VPS. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). +Writes to an 8bit field in the VPS. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). **Input:** | Register Name | Bits | Description | @@ -1112,7 +1207,7 @@ bf_vps_op_write8 writes to an 8bit field in the VPS. The "index" is architecture ### 2.12.14. bf_vps_op_write16, OP=0x6, IDX=0x8 -bf_vps_op_write16 writes to a 16bit field in the VPS. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). +Writes to a 16bit field in the VPS. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). **Input:** | Register Name | Bits | Description | @@ -1131,7 +1226,7 @@ bf_vps_op_write16 writes to a 16bit field in the VPS. The "index" is architectur ### 2.12.15. bf_vps_op_write32, OP=0x6, IDX=0x9 -bf_vps_op_write32 writes to a 32bit field in the VPS. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). +Writes to a 32bit field in the VPS. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). **Input:** | Register Name | Bits | Description | @@ -1150,7 +1245,7 @@ bf_vps_op_write32 writes to a 32bit field in the VPS. The "index" is architectur ### 2.12.16. bf_vps_op_write64, OP=0x6, IDX=0xA -bf_vps_op_write64 writes to a 64bit field in the VPS. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). +Writes to a 64bit field in the VPS. The "index" is architecture-specific. For Intel, Appendix B, "Field Encoding in VMCS," defines the index (or encoding). For AMD, Appendix B, "Layout of VMCB," defines the index (or offset). **Input:** | Register Name | Bits | Description | @@ -1208,17 +1303,25 @@ Writes to a CPU register in the VPS given a bf_reg_t and the value to write. Not ### 2.12.19. bf_vps_op_run, OP=0x5, IDX=0xD -bf_vps_op_run tells the microkernel to execute a given VPS on behalf of a given VP and VM. This system call only returns if an error occurs. On success, this system call will physically execute the requested VP using the requested VPS, and the extension will only execute again on the next VMExit. +bf_vps_op_run tells the microkernel to execute a given VPS on behalf of a given VP and VM. This system call only returns if an error occurs. On success, this system call will physically execute the requested VM and VP using the requested VPS, and the extension will only execute again on the next VMExit. + +Unless an extension needs to change the active VM, VP or VPS, the extension should use bf_vps_op_run_current instead of bf_vps_op_run. bf_vps_op_run is slow as it must perform a series of checks to determine if it has any work to perform before execution of a VM can occur. + +Unlike bf_vps_op_run_current which is really just a return to microkernel execution, bf_vps_op_run must perform the following operations: +- It first verifies that the provided VM, VP and VPS are all created. Meaning, and extension must first use the create ABI to properly create a VM, VP and VPS before it may be used. +- Next, it must ensure VM, VP and VPS assignment is correct. A newly created VP and VPS are unassigned. Once bf_vps_op_run is executed, the VP is assigned to the provided VM and the VPS is assigned to the provided VP. The VP and VPS are also both assigned to the PP bf_vps_op_run is executed on. Once these assignments take place, an extension cannot change them, and any attempt to run a VP or VPS on a VM, VP or PP they are not assigned to will fail. It is impossible to change the assigned of a VM or VP, but an extension can change the assignment of a VP and VPSs PP by using the bf_vp_op_migrate function. +- Next, bf_vps_op_run must determine if it needs to migrate a VPS to the PP the VPS is being executed on by bf_vps_op_run. For more information about how this works, please see bf_vp_op_migrate. +- Finally, bf_vps_op_run must ensure the active VM, VP and VPS are set to the VM, VP and VPS provided to this ABI. Any changes in the active state could cause additional operations to take place. For example, the VPS must transfer the TLS state of the general purpose registers to its internal cache so that the VPS that is about to become active can use the TLS block instead. **Input:** | Register Name | Bits | Description | | :------------ | :--- | :---------- | | REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | -| REG1 | 15:0 | The VPSID of the VPS to run | +| REG1 | 15:0 | The VMID of the VM to run | | REG1 | 63:16 | REVI | | REG2 | 15:0 | The VPID of the VP to run | | REG2 | 63:16 | REVI | -| REG3 | 15:0 | The VMID of the VM to run | +| REG3 | 15:0 | The VPSID of the VPS to run | | REG3 | 63:16 | REVI | **const, bf_uint64_t: BF_VPS_OP_RUN_IDX_VAL** @@ -1258,14 +1361,12 @@ This syscall tells the microkernel to advance the instruction pointer in the req ### 2.12.22. bf_vps_op_advance_ip_and_run_current, OP=0x5, IDX=0x10 -This syscall tells the microkernel to advance the instruction pointer in the requested VPS and run the currently active VPS, VP and VM (i.e., this combines bf_vps_op_advance_ip and bf_vps_op_advance_ip). +This syscall tells the microkernel to advance the instruction pointer in the currently active VPS and run the currently active VPS, VP and VM (i.e., this combines bf_vps_op_advance_ip and bf_vps_op_advance_ip). **Input:** | Register Name | Bits | Description | | :------------ | :--- | :---------- | | REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | -| REG1 | 15:0 | The VPSID of the VPS advance the IP in | -| REG1 | 63:16 | REVI | **const, bf_uint64_t: BF_VPS_OP_ADVANCE_IP_IDX_VAL** | Value | Description | @@ -1288,11 +1389,27 @@ bf_vps_op_promote tells the microkernel to promote the requested VPS. bf_vps_op_ | :---- | :---------- | | 0x0000000000000011 | Defines the syscall index for bf_vps_op_promote | +### 2.12.24. bf_vps_op_clear_vps, OP=0x5, IDX=0x11 + +bf_vps_op_clear_vps tells the microkernel to clear the VPS's hardware cache, if one exists. How this is used depends entirely on the hardware and is associated with AMD's VMCB Clean Bits, and Intel's VMClear instruction. See the associated documentation for more details. On AMD, this ABI clears the entire VMCB. For more fine grained control, use the write ABIs to manually modify the VMCB. + +**Input:** +| Register Name | Bits | Description | +| :------------ | :--- | :---------- | +| REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | +| REG1 | 15:0 | The VPSID of the VPS to clear | +| REG1 | 63:16 | REVI | + +**const, bf_uint64_t: BF_VPS_OP_CLEAR_IDX_VAL** +| Value | Description | +| :---- | :---------- | +| 0x0000000000000012 | Defines the syscall index for bf_vps_op_clear_vps | + ## 2.13. Intrinsic Syscalls -### 2.13.1. bf_intrinsic_op_read_msr, OP=0x7, IDX=0x0 +### 2.13.1. bf_intrinsic_op_rdmsr, OP=0x7, IDX=0x0 -Reads an MSR directly from the CPU given the address of the MSR to read. Note that this is specific to Intel/AMD only. +Reads an MSR directly from the CPU given the address of the MSR to read. Note that this is specific to Intel/AMD only. Also note that not all MSRs can be written to, and which MSRs that can be written to is up to the microkernel's internal policy as well as which architecture the hypervisor is running on. **Input:** | Register Name | Bits | Description | @@ -1306,14 +1423,14 @@ Reads an MSR directly from the CPU given the address of the MSR to read. Note th | :------------ | :--- | :---------- | | REG0 | 63:0 | The resulting value | -**const, bf_uint64_t: BF_INTRINSIC_OP_READ_MSR_IDX_VAL** +**const, bf_uint64_t: BF_INTRINSIC_OP_RDMSR_IDX_VAL** | Value | Description | | :---- | :---------- | -| 0x0000000000000000 | Defines the syscall index for bf_intrinsic_op_read_msr | +| 0x0000000000000000 | Defines the syscall index for bf_intrinsic_op_rdmsr | -### 2.13.2. bf_intrinsic_op_write_msr, OP=0x7, IDX=0x1 +### 2.13.2. bf_intrinsic_op_wrmsr, OP=0x7, IDX=0x1 -Writes to an MSR directly from the CPU given the address of the MSR to write and the value to write. Note that this is specific to Intel/AMD only. +Writes to an MSR directly from the CPU given the address of the MSR to write and the value to write. Note that this is specific to Intel/AMD only. Also note that not all MSRs can be written to, and which MSRs that can be written to is up to the microkernel's internal policy as well as which architecture the hypervisor is running on. **Input:** | Register Name | Bits | Description | @@ -1323,10 +1440,60 @@ Writes to an MSR directly from the CPU given the address of the MSR to write and | REG1 | 63:32 | REVI | | REG2 | 63:0 | The value to write to the requested MSR | -**const, bf_uint64_t: BF_INTRINSIC_OP_WRITE_MSR_IDX_VAL** +**const, bf_uint64_t: BF_INTRINSIC_OP_WRMSR_IDX_VAL** | Value | Description | | :---- | :---------- | -| 0x0000000000000001 | Defines the syscall index for bf_intrinsic_op_write_msr | +| 0x0000000000000001 | Defines the syscall index for bf_intrinsic_op_wrmsr | + +### 2.13.3. bf_intrinsic_op_invlpga, OP=0x7, IDX=0x2 + +Invalidates the TLB mapping for a given virtual page and a given ASID. Note that this is specific to AMD only. + +**Input:** +| Register Name | Bits | Description | +| :------------ | :--- | :---------- | +| REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | +| REG1 | 63:0 | The address to invalidate | +| REG2 | 63:0 | The ASID to invalidate | + +**const, bf_uint64_t: BF_INTRINSIC_OP_INVLPGA_IDX_VAL** +| Value | Description | +| :---- | :---------- | +| 0x0000000000000002 | Defines the syscall index for bf_intrinsic_op_invlpga | + +### 2.13.4. bf_intrinsic_op_invept, OP=0x7, IDX=0x3 + +Invalidates mappings in the translation lookaside buffers (TLBs) and paging-structure caches that were derived from extended page tables (EPT). Note that this is specific to Intel only. + +**Input:** +| Register Name | Bits | Description | +| :------------ | :--- | :---------- | +| REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | +| REG1 | 63:0 | The EPTP to invalidate | +| REG2 | 63:0 | The INVEPT type (see the Intel SDM for details) | + +**const, bf_uint64_t: BF_INTRINSIC_OP_INVEPT_IDX_VAL** +| Value | Description | +| :---- | :---------- | +| 0x0000000000000003 | Defines the syscall index for bf_intrinsic_op_invept | + +### 2.13.5. bf_intrinsic_op_invvpid, OP=0x7, IDX=0x4 + +Invalidates mappings in the translation lookaside buffers (TLBs) and paging-structure caches based on virtual-processor identifier (VPID). Note that this is specific to Intel only. + +**Input:** +| Register Name | Bits | Description | +| :------------ | :--- | :---------- | +| REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | +| REG1 | 63:0 | The address to invalidate | +| REG2 | 15:0 | The VPID to invalidate | +| REG2 | 63:16 | REVI | +| REG3 | 63:0 | The INVVPID type (see the Intel SDM for details) | + +**const, bf_uint64_t: BF_INTRINSIC_OP_INVVPID_IDX_VAL** +| Value | Description | +| :---- | :---------- | +| 0x0000000000000004 | Defines the syscall index for bf_intrinsic_op_invvpid | ## 2.14. Mem Syscalls @@ -1337,26 +1504,20 @@ Each extension has access to several different memory pools: - TLS (used for thread-local storage) - The direct map -The page pool provides a means to allocate a page. Allocated pages are **not** mapped into the microkernel, and therefore are safe for storing secrets if needed (at least as safe as it is going to get). Page allocation (and freeing) is a slow process as several different page walks are involved. +The page pool provides a means to allocate a page. The huge pool provides a method for allocating physically contiguous memory. This pool is small and platform-dependent (as in less than a megabyte total). +It should be noted that some microkernels may choose not to implement bf_mem_op_free_huge which is optional. -The heap pool provides memory that can only be grown or shrunk, meaning the memory must always remain contiguous. An extension is free to use heap memory or the page pool. Both unmap any allocated pages from the microkernel, and both are slow. The only difference between these two pools is the page pool can only allocate a single page at a time and may or may not be fragmented (depends on the implementation). The heap pool can allocate memory of any size (must be a multiple of a page) and never fragments. Freeing memory is also different. An extension can free any page from the page pool (although the virtual address associated with the page may remain allocated, meaning the memory is reusable, but the virtual address is not, leading to potential exhaustion of the virtual memory space). The heap pool can only be grown or shrunk, meaning the free operation reduces the heap pool's size. +The heap pool provides memory that can only be grown, meaning the memory must always remain virtually contiguous. An extension is free to use heap memory or the page pool. The only difference between these two pools is the page pool can only allocate a single page at a time and may or may not be fragmented (depends on the implementation). The heap pool can allocate memory of any size (must be a multiple of a page) and never fragments. -Allocations must all occur during the bootstrap phase of the extension. Once an extension has executed bf_vps_op_run, allocations are no longer allowed. +Thread-Local Storage (TLS) memory (typically allocated using `thread_local`) provides per-physical processor storage. The amount of TLS available to an extension is 1 page per physical processor. -Thread-Local Storage (TLS) memory (typically allocated using `thread_local`) provides per-thread storage. The amount of TLS available to an extension depends on the configuration of the hypervisor. - -The direct map provides an extension with a means to access any physical address by accessing the direct map region of the virtual address space (depends on the hypervisor's configuration). By default, on Intel/AMD with 4-level paging, this region starts at 0x0000400000000000. An extension can access any physical address by simply adding 0x0000400000000000 to the physical address and dereferencing the resulting value. Note that not all extensions can access the direct map (depends on the microkernel's security policy), and not all physical addresses are accessible. For example, any physical address mapped into the microkernel or another extension cannot be mapped (meaning a physical address can only be mapped once by the entire hypervisor). The microkernel also provides a per-VM direct map to provide additional mitigations for transient execution attacks. This feature is seamless to an extension, meaning, so long as an extension has the right to map a physical address, any attempt to access a legal, physical address will successfully map. +The direct map provides an extension with a means to access any physical address by accessing the direct map region of the virtual address space (depends on the hypervisor's configuration). By default, on Intel/AMD with 4-level paging, this region starts at 0x0000600000000000, but it can be changed using CMake. An extension can access any physical address by simply adding 0x0000600000000000 to the physical address and dereferencing the resulting value. When a VM is destroyed, all physical memory maps associated with that VM will be removed. The direct map is also where page and huge page allocations are mapped, providing an extension with a simple means for performing a virtual address to physical address (and vice versa) translations. ### 2.14.1. bf_mem_op_alloc_page, OP=0x7, IDX=0x0 -bf_mem_op_alloc_page allocates a page. When allocating a page, the extension should keep in mind the following: -- The microkernel removes the page from its address space, which requires a page walk, which means that this operation is slow. -- Virtual address to physical address conversions require a page walk, so they are slow. -- The microkernel does not support physical address to virtual address conversions. -- Whether or not bf_mem_op_free_page frees the allocated virtual address is implementation-specific and not known to the extension, which could lead to the virtual address space's exhaustion. -- The execution of bf_mem_op_free_page is also slow, as a page walk is also needed. +bf_mem_op_alloc_page allocates a page, and maps this page into the direct map of the VM. **Input:** | Register Name | Bits | Description | @@ -1376,7 +1537,7 @@ bf_mem_op_alloc_page allocates a page. When allocating a page, the extension sho ### 2.14.2. bf_mem_op_free_page, OP=0x7, IDX=0x1 -Frees a page previously allocated by bf_mem_op_alloc_page. For more information, please see bf_mem_op_alloc_page. +Frees a page previously allocated by bf_mem_op_alloc_page. This operation is optional and not all microkernels may implement it. **Input:** | Register Name | Bits | Description | @@ -1396,36 +1557,67 @@ Frees a page previously allocated by bf_mem_op_alloc_page. For more information, ### 2.14.3. bf_mem_op_alloc_huge, OP=0x7, IDX=0x2 -TBD - -### 2.14.4. bf_mem_op_free_huge, OP=0x7, IDX=0x3 - -TBD - -### 2.14.5. bf_mem_op_alloc_heap, OP=0x7, IDX=0x4 - -TBD - -### 2.14.6. bf_mem_op_free_heap, OP=0x7, IDX=0x5 - -TBD - -### 2.14.7. bf_mem_op_virt_to_phys, OP=0x7, IDX=0x6 - -bf_mem_op_virt_to_phys converts a provided virtual address to a physical address for any virtual address allocated using bf_mem_op_alloc_page, bf_mem_op_alloc_huge, bf_mem_op_alloc_heap or mapped using the direct map. +bf_mem_op_alloc_huge allocates a physically contiguous block of memory. When allocating a page, the extension should keep in mind the following: +- The total memory available to allocate from this pool is extremely limited. This should only be used when absolutely needed, and extensions should not expect more than 1 MB (might be less) of total memory available. +- Memory allocated from the huge pool might be allocated using different schemes. For example, the microkernel might allocate in increments of a page, or it might use a buddy allocator that would allocate in multiples of 2. If the allocation size doesn't match the algorithm, internal fragmentation could occur, further limiting the total number of allocations this pool can support. **Input:** | Register Name | Bits | Description | | :------------ | :--- | :---------- | | REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | -| REG1 | 63:0 | The virtual address of the page to convert | +| REG1 | 63:0 | The total number of bytes to allocate | **Output:** | Register Name | Bits | Description | | :------------ | :--- | :---------- | -| REG0 | 63:0 | The physical address of the provided virtual address | +| REG0 | 63:0 | The virtual address of the resulting memory | +| REG1 | 63:0 | The physical address of the resulting memory | -**const, bf_uint64_t: BF_MEM_OP_VIRT_TO_PHYS_IDX_VAL** +**const, bf_uint64_t: BF_MEM_OP_ALLOC_HUGE_IDX_VAL** | Value | Description | | :---- | :---------- | -| 0x0000000000000006 | Defines the syscall index for bf_mem_op_virt_to_phys | +| 0x0000000000000002 | Defines the syscall index for bf_mem_op_alloc_huge | + +### 2.14.4. bf_mem_op_free_huge, OP=0x7, IDX=0x3 + +Frees memory previously allocated by bf_mem_op_alloc_huge. This operation is optional and not all microkernels may implement it. + +**Input:** +| Register Name | Bits | Description | +| :------------ | :--- | :---------- | +| REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | +| REG1 | 63:0 | The virtual address of the memory to free | + +**Output:** +| Register Name | Bits | Description | +| :------------ | :--- | :---------- | + +**const, bf_uint64_t: BF_MEM_OP_FREE_HUGE_IDX_VAL** +| Value | Description | +| :---- | :---------- | +| 0x0000000000000003 | Defines the syscall index for bf_mem_op_free_huge | + +### 2.14.5. bf_mem_op_alloc_heap, OP=0x7, IDX=0x4 + +bf_mem_op_alloc_heap allocates heap memory. When allocating heap memory, the extension should keep in mind the following: +- This ABI is designed to work similar to sbrk() to support malloc/free implementations common with existing open source libraries. +- Calling this ABI with with a size of 0 will return the current heap location. +- Calling this ABI with a size (in bytes) will result in return the previous heap location. The current heap location will be set to the previous location, plus the provide size, rounded to the nearest page size. +- The heap is not mapped into the direct map, so virtual to physical (and vice versa) translations are not possible. +- There is no ability to free heap memory + +**Input:** +| Register Name | Bits | Description | +| :------------ | :--- | :---------- | +| REG0 | 63:0 | Set to the result of bf_handle_op_open_handle | +| REG1 | 63:0 | The number of bytes to increase the heap by | + +**Output:** +| Register Name | Bits | Description | +| :------------ | :--- | :---------- | +| REG0 | 63:0 | The virtual address of the previous heap location | + +**const, bf_uint64_t: BF_MEM_OP_ALLOC_HEAP_IDX_VAL** +| Value | Description | +| :---- | :---------- | +| 0x0000000000000004 | Defines the syscall index for bf_mem_op_alloc_heap | diff --git a/docs/Optimizations.md b/docs/Optimizations.md new file mode 100644 index 00000000..2e3f232f --- /dev/null +++ b/docs/Optimizations.md @@ -0,0 +1,27 @@ +## Table of Contents + +# 1. Introduction + +This document describes some of the reasoning behind certain optimization, or the lack there of. + +# 2. VM, VP and VPS Pools + +The VM, VP and VPS pools used to use a combination of an array and a linked list. THe ID given to each resource is the resource's position in the array. This allows any API to access the resource using it's ID, which is fast and simple. Allocations, however, used a linked list. Basically, each resource stored a "next" pointer which the pools could use to turn the array into a linked list. This provided a means to allocate using O(1). In otherwords, all operations for each resource, including accesses, allocations and deallocations were all O(1) which is fast. + +This was changed to remove the linked list portion for a couple of reasons. To start, the next pointer adds memory usage. This memory usage is small, so by itself is not enough to remove the linked list. The main reason for removing the linked list is stability. Even if Bareflank is configured to have access to the max of 32767 resources for a VM, VP and VPS, O(N) in this case is not unreasonable. There are other operations that must take place other than just allocations that are O(N). For example, the microkernel must ensure that when a VM is destroyed, it is not active on any PPs, and that no VPs are assigned to it. All of these operations are all O(N), or we would need additional linked lists to reduce the overall time required to perform these checks. Each linked list not only adds additional memory requirements, but most importantly, it adds additional complexity to the microkernel. + +For example, suppose in the process of performing a deallocation, a null dereference occurs in the microkernel. If this happens, the microkernel needs to mark the resource as a zombie as it was not properly deallocated. Now lets say the microkernel needs to allocate a new resource. If the zombie resource is the head (which it will eventually become), the microkernel would fail as it would have allocated a zombie resource. This means that in addition to the added complexity of the linked lists, the microkernel needs added logic for handling when it attempts to allocate a resource that is a zombie. It also needs added logic for handling when the linked list is not properly linked. There are many more examples of these types of issues. Each linked list adds a lot of extra logic that must be compiled into the code (which also adds to the size of the microkernel), unit tested, etc. + +For these reasons, we simply loop through the arrays when attempting to do allocations. The move from O(1) to O(N) does mean that as N increases, allocations will take longer, but in the grand scheme of things, the reduction in overall complexity is worth it, as there are far fewer edge cases that must be considered, and a lot less state that must be properly handled in the event of unexpected errors. + +# 3. Release and MinSizeRel Modes + +The difference between bsl::unlikely and bsl::unlikely_assert (and the bsl::likely and bsl::finally equivalents) is that in Release and MinSizeRel mode, calls to these functions are optimized out, meaning they will not be executed. + +There are a number of debugging checks that code must have to ensure mods to the hypervisor do not break certain assumptions that during runtime will never actually occur. For example, when creating a VP, an extension must provide the VMID that the VP will be assigned to. The ABI specification states that the microkernel will ignore the upper bits of the field that do not contribute to a 16bit ID. What this means is that the ID will never overflow, in which case the error flag in the ID's safe integral will never trigger. The code for allocating a VP however cannot assume this and so it must check for an invalid VMID even through at runtime, this check will never trigger. + +To overcome this, the bsl::unlikely and friends have assert versions of them that are compiled out in a Release and MinSizeRel mode. This optimization provides a massive reduction in the overall size of the microkernel and extensions that use the BSL as most of the error checks that are in the code are there for developers while they are making changes and not for runtime specific errors. Furthermore, this optimization not only removes the check (including the branch), but is also likely removes a bunch of string information that likely adds more to the overall size of the microkernel and extensions than the code itself. + +These assert versions should not be used to validate correctness. Using the same example above, the microkernel needs to verify that the VMID is a valid VMID. Specifically, it needs to be allocated. If we use the assert version of bsl::unlikely, this check will not be included in a Release or MinSizeRel mode. Extensions that are well tested should never trigger this issue in a Release or MinSizeRel build, but the microkernel cannot assume this as this check is part of the ABI and must be enforced at all times. For this reason, use the assert versions of bsl::unlikely and friends only when the check cannot trigger at runtime assuming the microkernel has been properly tested, and never use the assert versions for validating correctness of the ABI, or some other configuration (including hardware) option that could change. + +The assert versions should also not be used when passing an error code onto the callee of a function. Instead, the debugging statement should be programmed to use bsl::V or higher, meaning these extra debug statements will be compiled out, but the branch will remain. So in other words, bsl::unlikely_assert and friends would only ever be paired with a bsl::error() and not a bsl::print(). diff --git a/docs/Security.md b/docs/Security.md new file mode 100644 index 00000000..0a1ac563 --- /dev/null +++ b/docs/Security.md @@ -0,0 +1,66 @@ +## Table of Contents + +# 1. Introduction + +This document defines all of the security features that have been added to the design of the Bareflank Microkernel. + +# 2. Features + +TBD + +# 3. Remaining Todos + +The following documents all of the security related features that the microkernel still has to implement. + +## 3.1. Meltdown +The microkernel currently doesn't protect against Meltdown. This is a problem because one of the goals of being able to support multiple user-space applications is so that we can create a vTPM app that stores vTPM secrets. This would dramatically improve the overall security of a vTPM as it would ensure that only that user-space application and possibly the microkernel can see the secrets in the vTPM, something other hypervisors will struggle with. If other user-space applications can use Meltdown to access these secrets, we have a problem. + +There are basically two different ways to prevent this. We could either unmap all of the memory from the microkernel that we hand out to the user-space application, or we could set up a different CR3 between the kernel and the user-space application. + +There are several issues with the first approach. First, the process of unmapping is slow, and causes issues with shootdowns, something the microkernel cannot really do as it has no way to IPI itself. The other issue is the microkernel doesn't have the ability to walk it's own page tables. It can only walk the page tables that are allocated for user-space. As a result, it cannot unmap. To solve this, we need to modify the loader to direct map all microkernel memory, including the memory used to store the microkernel's page tables. Since this is recursive, there are issues with running out of stack space in the kernel. In general, although this approach would be extremely effective, and generally faster during normal runtime operations, it is not a great solution and would add a lot of extra complexity. + +The second option would be to provide a different CR3 for the microkernel. We already have this CR3, it is the m_system_rpt. We simply need to remove the microkernel aliases from the other RPTs that the extensions use, and then load the m_system_rpt whenever an extension is done executing, which includes the execute() function, the syscall dispatch logic, and the ESR logic (basically anywhere user-space can enter/exit the microkernel from). The problem with this approach is everything is currently marked as global inside the kernel to reduce the overhead of constantly swapping CR3. The global flag would have to be turned off (done in the loader), and we would need something like PCID to prevent the implementation from being insanely slow. + +Adding a PCID requirement would severally limit which CPUs this code supports, especially on AMD which added this feature in Zen 3. + +For now, we leave this security hole unpatched, but once we attempt to implement a vTPM, this issue should be resolved, and we will either have to implement option #1, or implement option #2 and deal with the massive performance hit systems will take that do not have PCID support. + +## 3.2. Transient Execution Attacks +We need to complete any remaining patches for transient execution attacks. Current we have implemented retpoline, and the user-space direct map implementation should mitigate L1TF style attacks. Attacks like MDS are best handled by disabling HyperThreading or purchasing hardware that is not vulnerable to this style of attack. Besides Meltdown which is described above, we might have some others that still need to be completed. + +## 3.3. Extension Physical Memory Mapping +We currently do not prevent user-space from mapping in any physical address. This means that a user-space application can map in memory from the microkernel or some other user-space application. + +This is obviously an issue, and the solution is not simple. The microkernel has no idea what physical addresses are that it controls as it is given random physical memory from the loader. + +There are basically three options to solve this issue. The first option is to walk the page tables of all extensions and the microkernel to see if the physical page that a user-space application is trying to map is owned by the hypervisor. If it is, it should never be mapped by the user-space application. The second approach is to only enable this security feature for the hypervisor when UEFI is used to load the hypervisor. In this case, the loader could be modified to allocate one giant block of memory for everything and then pull from this block of memory as it needs it. The address and size of this block of memory could then be given to the microkernel, and it could determine if a map is valid or not using a simple comparison. The third option is to store a list that contains all of the physical addresses that the hypervisor was provided by the loader. This is essentially how the older version of Bareflank works. This would require some sort of data structure to store this memory, and obviously would use a fair amount of memory itself just to store the physical address list, but would work for any loader. The downside to this approach is determining if a physical address is in the list would likely require the data structure to be a hash table, which we would have to implement from scratch. + +Since the Windows/Linux loaders are only intended for developers, the second approach should work great and solve this problem in a way that is both fast, and simple. The only trick is ensuring that the loader pulls all of it's allocations from a single, contiguous block. For example, it could use the page pool argument in the start_vmm to determine the total number of pages that are allowed to be used by the entire hypervisor, and then all allocations come from that specific page pool. Any memory left is given to the microkernel as it's page pool. This would not only ensure a simple means to implement this feature, but it would also provide a nice way to reason about how much memory the hypervisor is using as the page pool would account for all memory allocated, including by the loader which it currently doesn't. + +For now, this security issue is left unpatched. + +## 3.4. KALSR +We currently do not implement KASLR like we did in the previous version of the hypervisor. To implement this, all addresses should have some random entropy added to them. + +Specifically, all of the hypervisor constants are still needed, but we need to simply add some entropy to these values to ensure they are not fixed. The only constants that do not need entropy are the direct map constants as these are based on the size of 4-level paging and must remain fixed. + +The other requirement that will be needed to make this work is ensuring that the microkernel and all of it's extensions are compiled as static PIE binaries. We still want "static" compilation because adding support for dynamic libraries would cause issues not only with the overall complexity, but also with retpoline as the PLT that is needed would have to run through an out-of-line retpoline which is not good for performance. + +Like the old code, the ELF loader should always perform all relocations when the ELF is loaded (meaning lazy loading should not be implemented). In general, this security feature should be relatively easy to implement since we have already done it once before. The hardest part will be finding a way to generate random numbers. + +## 3.5. Hardware Security Features +There are some additional kernel level security features that both Intel and AMD continue to implement that we have not yet implemented. We really should do a complete analysis of all of these features and make sure they are turned on when they can be. + +It should be noted that some of them might be due to how the loader works. If any of the bits in CR0/CR4 are turned on, it is likely that the microkernel will inherit these features (which could also cause issues with support for future CPUs). Others like clearing the L1 cache that use MSRs need a full review and implementation where it makes sense. + +One exception to this is SMAP. Right now, even if the loader attempts to enable SMAP (which it likely will), we set the RFLAGS to set SMAP disabled at all times. This is done by making sure that FMASK doesn't clear AC, that AC is set in the dispatch and ESR entry points, and that when calling into an extension using call_ext, that AC is disabled as unaligned memory accesses are performed all the time by the compiler which we don't really have control of. This was done to simplify the microkernel's assembly logic, but at some point this will need to be enabled, and we will have to have some way of determining if and when the SMAP instructions should be used depending on what hardware the system is on. Another option would be to simply set RFLAGs manually without using these new instructions. This would allow SMAP to be used on all hardware (as AC is not used in the microkernel, so changing it has no effect). Option #2 is likely the better solution as even the Linux kernel has struggled with this issue since userspace memory access has to occur in areas where performing a feature check is non-trial. + +Finally, non of these features are turned on in the UEFI loader, and they should be. Basically, once we know what all of the security features are, and how to turn them on, we need to add this logic to the UEFI loader so that it can ensure the system is as secure as possible. + +## 3.6 Support For Multiple Extensions +The microkernel already has a bunch of logic for handling more than one extension, but the main feature missing is IPC ABIs and the ability for one extension to signal another (which is the method for getting more than one extension to execute since we don't have a scheduler). Once multiple extensions are supported, downstream projects like MicroV can break their logic into different extensions which provides several security benefits. There is more details about how this would work in the ext_t.hpp file. + +One detail that MicroV will need to pay attention to once it has more than one extension is how much memory the PV and emulation extensions are using. Ideally, these extensions (which has a communication path to a VM and are thus the first line of defense), should limit how much memory it maps in to as little as possible. They should also be prevented from executing syscalls as much as possible (see below). Again, if these extensions that communicate directly with the VM are ever compromised, or used as a path for transient execution attacks, keeping their access to data and syscalls to a minimum might result in the attack failing overall. + +## 3.7 Syscall Policy +Once multiple extensions are supported, a syscall policy should be implemented to determine which extensions should be allowed to execute specific syscalls. This could then be used to prevent an emulation or PV extension (basically any extension that talks to a VM) from being able to perform certain actions that could further improve security. diff --git a/docs/Testing.md b/docs/Testing.md new file mode 100644 index 00000000..586a7a33 --- /dev/null +++ b/docs/Testing.md @@ -0,0 +1,28 @@ +## Table of Contents + +# 1. Introduction + +This document defines the testing methodology for Bareflank, and some notes +when writing tests. + +# 2. Unit Tests + +## 2.1 "constexpr" + +As much of the code as possible is written as a constexpr. This means that the majority of the code can be compiled and executed at compile time from a static assert. This allows us to execute the unit tests while the code is being compiled, which ensures two things: +- When code is modified, the compiler not only checks for the correctness of the code, but also the correctness of the logic itself, making it far more difficult to make mistakes. +- Undefined behavior is mostly impossible as UB is not allowed in constexpr functions. We also use UBSAN to check for this, but in general, this check is not needed as the use of constexpr performs a much better and more reliable check than attempting to verify this at runtime using UBSAN. + +Some of the code (e.g., the assembly logic) cannot be compiled as a constexpr. In these cases we usually provide a mock that is a constexpr, or we check to see if we are executing at compile-time and if we are, we return early, allowing the function to act as a constexpr at compile-time, avoiding the logic that is not constexpr friendly. For this reason, unit tests are always executed at both compile-time and run-time. All of the non-constexpr logic is tested at runtime to ensure that it is also tested. + +## 2.2 Branch Tests + +The unit tests come complete with 100% branch coverage in addition to function and line coverage. Bareflank's version of the Clang Tidy static analysis engine does not allow the use of boolean operators, and if statements are required to be in a specific form to ensure that line coverage should be the same as the branch coverage. When this does not end up being the case is when templates are used. Specifically, each template argument to a function or class creates a new copy of this function or class, and duplicates all of the branches. This means that all of the unit tests need to test every branch for every template type it is provided in the test. Since the test reports are merged across all tests, it is extremely important that template arguments are managed across all of the unit tests. Just providing a new implementation of an object that is passed to a function or class that takes a template is usually a bad idea is it will add requirements for other tests with a cascade style effect. Branch coverage is required to ensure compliance with ASIL/D so it is important that this is done properly. What this means is that the unit tests should have a single mock type, and that type should be capable of supporting all tests that are needed. In some cases, additional seams in the code are needed to support this. + +## 2.3 Std C++ + +The BSL is fully compatible with the standard C++ library, so feel free to use standard C++ in a unit test if needed. Ideally, this is kept to a minimum to support systems that do not have access to a standard C++ library (especially on some RTOS operating systems). In these cases, the unit tests for these systems can be ignored, so keeping the use of the standard C++ library to a minimum is ideal, but when absolutely needed, it is supported. + +# 3. Integration Tests + +All of the ABIs that Bareflank supports have a complete set of integration tests to ensure they operate as expected at runtime. This ensures that all of the assembly code is also tested and works as expected. Note that the use of these integration tests on a specific system can be used to perform system level testing as well, meaning the integration tests can also be used to ensure that all of the code is working on each system tests. The examples also provide an additional level of system level testing as they exercise specific features on the system. diff --git a/example/default/CMakeLists.txt b/example/default/CMakeLists.txt index 1f575f34..3696a59a 100644 --- a/example/default/CMakeLists.txt +++ b/example/default/CMakeLists.txt @@ -19,69 +19,173 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +# ------------------------------------------------------------------------------ +# Notes +# ------------------------------------------------------------------------------ + +# - Extensions must be compiled with the extension toolchain. Bareflank's +# build systems already has support for configuring where your extension +# might be located. Please see the readme for more details. +# +# - If you set up the build system properly, HYPERVISOR_TARGET_ARCH and +# CMAKE_BUILD_TYPE will already be set for you, as well as most of the +# other HYPERVISOR_ variables that the microkernel can use. +# +# - The goal of each example is to prevent the need for any macros that the +# microkernel's build system already provides which is why some macros +# are duplicated here. +# + +# ------------------------------------------------------------------------------ +# Executable +# ------------------------------------------------------------------------------ + add_executable(example_default) -# NOTE: -# - Include your headers and include directories -# - -if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - target_include_directories(example_default PRIVATE - x64 - ) - list(APPEND HEADERS - ${CMAKE_CURRENT_LIST_DIR}/x64/common_arch_support.hpp - ) -endif() - -if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") - target_include_directories(example_default PRIVATE - x64/amd - ) - list(APPEND HEADERS - ${CMAKE_CURRENT_LIST_DIR}/x64/amd/arch_support.hpp - ) -elseif(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - target_include_directories(example_default PRIVATE - x64/intel - ) - list(APPEND HEADERS - ${CMAKE_CURRENT_LIST_DIR}/x64/intel/arch_support.hpp - ) -else() - message(FATAL_ERROR "Unsupported HYPERVISOR_TARGET_ARCH: ${HYPERVISOR_TARGET_ARCH}") -endif() +# ------------------------------------------------------------------------------ +# Macros +# ------------------------------------------------------------------------------ # NOTE: -# - Include your source files and dependencies +# - We use this macro to add source files to an executable because Ninja on +# Windows will not recompile without the dependencies being stated explicitly +# simpilar to how Visual Studio works. This simplifies the process. # -target_sources(example_default PRIVATE - main.cpp +macro(example_target_source NAME SOURCE_FILE) + target_sources(${NAME} PRIVATE ${SOURCE_FILE}) + set_property(SOURCE ${SOURCE_FILE} APPEND PROPERTY OBJECT_DEPENDS ${ARGN}) +endmacro(example_target_source) + +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + +# NOTE: +# - Add each include folder as needed. This is what allows us to handle +# each architecture. Common code simply calls into code that has the same +# name across all architectures, and the build system handles making sure +# the right code is compiled in. This prevents the need for any compile time +# macros in the code. +# + +target_include_directories(example_default PRIVATE + include + src ) -set_property(SOURCE main.cpp APPEND PROPERTY OBJECT_DEPENDS ${HEADERS}) - if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - target_sources(example_default PRIVATE - x64/intrinsic_cpuid.S + target_include_directories(example_default PRIVATE + include/x64 + src/x64 + ) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") + target_include_directories(example_default PRIVATE + include/x64/amd + src/x64/amd + ) + endif() + + if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + target_include_directories(example_default PRIVATE + include/x64/intel + src/x64/intel + ) + endif() +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + target_include_directories(example_default PRIVATE + include/arm/aarch64 + src/arm/aarch64 ) endif() -if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") - # target_sources(example_default PRIVATE - # ) -elseif(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - # target_sources(example_default PRIVATE - # ) -else() - message(FATAL_ERROR "Unsupported HYPERVISOR_TARGET_ARCH: ${HYPERVISOR_TARGET_ARCH}") -endif() +# ------------------------------------------------------------------------------ +# Headers +# ------------------------------------------------------------------------------ # NOTE: -# - Include your libraries. Note that if you use our runtime libary, -# you must include it first, otherwise your extension will try to use -# files from the BSL that the runtime library is meant to replace. +# - We need to explicitly declare each header due to Windows dependency +# issues with header files. +# + +list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/include/dummy_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/bootstrap_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/fail_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/vp_pool_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/vp_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/vps_pool_t.hpp +) + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/src/x64/intrinsic_cpuid_impl.hpp + ) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/include/x64/amd/arch_dummy_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/gs_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/tls_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/intrinsic_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/vmexit_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/vps_t.hpp + ) + endif() + + if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/include/x64/intel/arch_dummy_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/gs_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/tls_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/intrinsic_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/vmexit_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/vps_t.hpp + ) + endif() +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/arch_dummy_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/arm/aarch64/gs_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/arm/aarch64/tls_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/arm/aarch64/intrinsic_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/arm/aarch64/vmexit_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/arm/aarch64/vps_t.hpp + ) +endif() + +# ------------------------------------------------------------------------------ +# Sources +# ------------------------------------------------------------------------------ + +# NOTE: +# - Add the sources to the executable. See the note above about why we +# use the macro for doing this. +# + +example_target_source(example_default src/main.cpp ${HEADERS}) + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + example_target_source(example_default src/x64/intrinsic_cpuid_impl.S ${HEADERS}) +endif() + +# ------------------------------------------------------------------------------ +# Libraries +# ------------------------------------------------------------------------------ + +# NOTE: +# - The only library that is probably needed here is the loader. If you are +# using C, you do not need the BSL, and you can provide your own syscall and +# runtime libraries if you want. We provide our own versions to make things +# easy, but if you prefer to implement your extension another way, you +# can do so. The microkernel's ABI is the only piece of code that the project +# is aiming to keep stable, so if it changes, you can continue to use an +# old implementation, or write your own. # target_link_libraries(example_default PRIVATE @@ -91,8 +195,25 @@ target_link_libraries(example_default PRIVATE syscall ) +# ------------------------------------------------------------------------------ +# Install +# ------------------------------------------------------------------------------ + # NOTE: -# - Install your extension somewhere. +# - If this is a release or minsizerel build, we strip just to make the +# finaly executable as small as possible. Note that this is entirely +# optional and can be removed if you wish. +# + +if(CMAKE_BUILD_TYPE STREQUAL RELEASE OR CMAKE_BUILD_TYPE STREQUAL MINSIZEREL) + add_custom_command(TARGET example_default POST_BUILD COMMAND ${CMAKE_STRIP} example_default) +endif() + +# NOTE: +# - You can install wherever you want. We install into the bin folder, +# which the build system can find for starting/stopping the hypervisor. +# If you provide your own tools, you can install to wherever is easier +# for you. # install(TARGETS example_default DESTINATION bin) diff --git a/example/default/include/arm/aarch64/arch_dummy_t.hpp b/example/default/include/arm/aarch64/arch_dummy_t.hpp new file mode 100644 index 00000000..f461e6f0 --- /dev/null +++ b/example/default/include/arm/aarch64/arch_dummy_t.hpp @@ -0,0 +1,47 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef ARCH_DUMMY_T_HPP +#define ARCH_DUMMY_T_HPP + +#include + +namespace example +{ + /// @class example::arch_dummy_t + /// + /// + /// @brief The only thing that should go in the include folder are + /// type defintions like this one that are not mocked in the unit + /// tests as the include folder is included in the unit tests. All + /// other code should be placed in the src folder. + /// + struct arch_dummy_t final + { + /// @brief dummy data for example purposes only. + bsl::safe_uintmax dummy; + }; +} + +#endif diff --git a/example/default/include/dummy_t.hpp b/example/default/include/dummy_t.hpp new file mode 100644 index 00000000..7d3bbb89 --- /dev/null +++ b/example/default/include/dummy_t.hpp @@ -0,0 +1,47 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DUMMY_T_HPP +#define DUMMY_T_HPP + +#include + +namespace example +{ + /// @class example::dummy_t + /// + /// + /// @brief The only thing that should go in the include folder are + /// type defintions like this one that are not mocked in the unit + /// tests as the include folder is included in the unit tests. All + /// other code should be placed in the src folder. + /// + struct dummy_t final + { + /// @brief dummy data for example purposes only. + bsl::safe_uintmax dummy; + }; +} + +#endif diff --git a/example/default/include/x64/amd/arch_dummy_t.hpp b/example/default/include/x64/amd/arch_dummy_t.hpp new file mode 100644 index 00000000..f461e6f0 --- /dev/null +++ b/example/default/include/x64/amd/arch_dummy_t.hpp @@ -0,0 +1,47 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef ARCH_DUMMY_T_HPP +#define ARCH_DUMMY_T_HPP + +#include + +namespace example +{ + /// @class example::arch_dummy_t + /// + /// + /// @brief The only thing that should go in the include folder are + /// type defintions like this one that are not mocked in the unit + /// tests as the include folder is included in the unit tests. All + /// other code should be placed in the src folder. + /// + struct arch_dummy_t final + { + /// @brief dummy data for example purposes only. + bsl::safe_uintmax dummy; + }; +} + +#endif diff --git a/example/default/include/x64/intel/arch_dummy_t.hpp b/example/default/include/x64/intel/arch_dummy_t.hpp new file mode 100644 index 00000000..f461e6f0 --- /dev/null +++ b/example/default/include/x64/intel/arch_dummy_t.hpp @@ -0,0 +1,47 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef ARCH_DUMMY_T_HPP +#define ARCH_DUMMY_T_HPP + +#include + +namespace example +{ + /// @class example::arch_dummy_t + /// + /// + /// @brief The only thing that should go in the include folder are + /// type defintions like this one that are not mocked in the unit + /// tests as the include folder is included in the unit tests. All + /// other code should be placed in the src folder. + /// + struct arch_dummy_t final + { + /// @brief dummy data for example purposes only. + bsl::safe_uintmax dummy; + }; +} + +#endif diff --git a/example/default/mocks/arm/aarch64/gs_t.hpp b/example/default/mocks/arm/aarch64/gs_t.hpp new file mode 100644 index 00000000..b63689c8 --- /dev/null +++ b/example/default/mocks/arm/aarch64/gs_t.hpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_GS_T_HPP +#define MOCKS_GS_T_HPP + +#include + +namespace example +{ + /// @class example::gs_t + /// + /// + /// @brief Defines the extension's mocked version of gs_t, used for + /// unit testing. + /// + struct gs_t final + {}; +} + +#endif diff --git a/example/default/mocks/arm/aarch64/tls_t.hpp b/example/default/mocks/arm/aarch64/tls_t.hpp new file mode 100644 index 00000000..190f61cd --- /dev/null +++ b/example/default/mocks/arm/aarch64/tls_t.hpp @@ -0,0 +1,45 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_TLS_T_HPP +#define MOCKS_TLS_T_HPP + +#include + +namespace example +{ + /// @class example::tls_t + /// + /// + /// @brief Defines the extension's mocked version of tls_t, used for + /// unit testing. + /// + struct tls_t final + { + /// @brief stores the return value for a test + bsl::errc_type test_ret; + }; +} + +#endif diff --git a/example/default/mocks/bootstrap_t.hpp b/example/default/mocks/bootstrap_t.hpp new file mode 100644 index 00000000..0dc7e7dc --- /dev/null +++ b/example/default/mocks/bootstrap_t.hpp @@ -0,0 +1,182 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_BOOTSTRAP_T_HPP +#define MOCKS_BOOTSTRAP_T_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace example +{ + /// @class example::bootstrap_t + /// + /// + /// @brief Defines the extension's bootstrap handler used for unit + /// testing + /// + class bootstrap_t final + { + /// @brief stores the return value for initialize + bsl::errc_type m_initialize{}; + /// @brief stores the return value for dispatch + bsl::errc_type m_dispatch{}; + + public: + /// + /// @brief Initializes this bootstrap_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + return m_initialize; + } + + /// + /// @brief Sets the return value of initialize. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// initialize + /// + constexpr void + set_initialize(bsl::errc_type const &errc) noexcept + { + m_initialize = errc; + } + + /// + /// @brief Release the bootstrap_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + } + + /// + /// @brief Dispatches the bootstrap process as needed. Note that + /// the bootstrap callback is only called when starting the + /// hypervisor on root VPs. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param ppid the ID of the PP to bootstrap + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + bsl::discard(ppid); + + return m_dispatch; + } + + /// + /// @brief Sets the return value of dispatch. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// dispatch + /// + constexpr void + set_dispatch(bsl::errc_type const &errc) noexcept + { + m_dispatch = errc; + } + }; +} + +#endif diff --git a/example/default/mocks/fail_t.hpp b/example/default/mocks/fail_t.hpp new file mode 100644 index 00000000..46e9a52c --- /dev/null +++ b/example/default/mocks/fail_t.hpp @@ -0,0 +1,183 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_FAIL_T_HPP +#define MOCKS_FAIL_T_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace example +{ + /// @class example::fail_t + /// + /// + /// @brief Defines the extension's fail handler used for unit testing + /// + class fail_t final + { + /// @brief stores the return value for initialize + bsl::errc_type m_initialize{}; + /// @brief stores the return value for dispatch + bsl::errc_type m_dispatch{}; + + public: + /// + /// @brief Initializes this fail_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + return m_initialize; + } + + /// + /// @brief Sets the return value of initialize. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// initialize + /// + constexpr void + set_initialize(bsl::errc_type const &errc) noexcept + { + m_initialize = errc; + } + + /// + /// @brief Release the fail_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + } + + /// + /// @brief Dispatches the fail as needed, or returns an error so + /// that the microkernel can halt the PP. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint64 const &fail_reason) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return m_dispatch; + } + + /// + /// @brief Sets the return value of dispatch. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// dispatch + /// + constexpr void + set_dispatch(bsl::errc_type const &errc) noexcept + { + m_dispatch = errc; + } + }; +} + +#endif diff --git a/example/default/mocks/gs_t.hpp b/example/default/mocks/gs_t.hpp new file mode 100644 index 00000000..20198902 --- /dev/null +++ b/example/default/mocks/gs_t.hpp @@ -0,0 +1,41 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_GS_T_HPP +#define MOCKS_GS_T_HPP + +namespace example +{ + /// @class example::gs_t + /// + /// + /// @brief Defines the extension's mocked version of gs_t, used for + /// unit testing. Specifically, this version only contains portions + /// that are common for all architectures. + /// + struct gs_t final + {}; +} + +#endif diff --git a/example/default/mocks/intrinsic_t.hpp b/example/default/mocks/intrinsic_t.hpp new file mode 100644 index 00000000..33a79cad --- /dev/null +++ b/example/default/mocks/intrinsic_t.hpp @@ -0,0 +1,97 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_INTRINSIC_HPP +#define MOCKS_INTRINSIC_HPP + +#include +#include + +#include +#include + +namespace example +{ + /// @class example::intrinsic_t + /// + /// + /// @brief Provides raw access to intrinsics used for unit testing. + /// Specifically, this version only contains portions that are common + /// for all architectures. + /// + class intrinsic_t final + { + /// @brief stores the return value for initialize + bsl::errc_type m_initialize{}; + + public: + /// + /// @brief Initializes this intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize(gs_t &gs, tls_t &tls) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + + return m_initialize; + } + + /// + /// @brief Sets the return value of initialize. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// initialize + /// + constexpr void + set_initialize(bsl::errc_type const &errc) noexcept + { + m_initialize = errc; + } + + /// + /// @brief Release the intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + } + }; +} + +#endif diff --git a/example/default/mocks/tls_t.hpp b/example/default/mocks/tls_t.hpp new file mode 100644 index 00000000..d49d6486 --- /dev/null +++ b/example/default/mocks/tls_t.hpp @@ -0,0 +1,46 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_TLS_T_HPP +#define MOCKS_TLS_T_HPP + +#include + +namespace example +{ + /// @class example::tls_t + /// + /// + /// @brief Defines the extension's mocked version of tls_t, used for + /// unit testing. Specifically, this version only contains portions + /// that are common for all architectures. + /// + struct tls_t final + { + /// @brief tells certain mocks when to fail + bsl::errc_type test_ret; + }; +} + +#endif diff --git a/example/default/mocks/vmexit_t.hpp b/example/default/mocks/vmexit_t.hpp new file mode 100644 index 00000000..0b0bf8d6 --- /dev/null +++ b/example/default/mocks/vmexit_t.hpp @@ -0,0 +1,183 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_VMEXIT_T_HPP +#define MOCKS_VMEXIT_T_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace example +{ + /// @class example::vmexit_t + /// + /// + /// @brief Defines the extension's VMExit handler + /// + class vmexit_t final + { + /// @brief stores the return value for initialize + bsl::errc_type m_initialize{}; + /// @brief stores the return value for dispatch + bsl::errc_type m_dispatch{}; + + public: + /// + /// @brief Initializes this vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + return m_initialize; + } + + /// + /// @brief Sets the return value of initialize. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// initialize + /// + constexpr void + set_initialize(bsl::errc_type const &errc) noexcept + { + m_initialize = errc; + } + + /// + /// @brief Release the vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + } + + /// + /// @brief Dispatches the VMExit. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint64 const &exit_reason) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + bsl::discard(vpsid); + bsl::discard(exit_reason); + + return m_dispatch; + } + + /// + /// @brief Sets the return value of dispatch. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// dispatch + /// + constexpr void + set_dispatch(bsl::errc_type const &errc) noexcept + { + m_dispatch = errc; + } + }; +} + +#endif diff --git a/example/default/mocks/vp_pool_t.hpp b/example/default/mocks/vp_pool_t.hpp new file mode 100644 index 00000000..41f8a012 --- /dev/null +++ b/example/default/mocks/vp_pool_t.hpp @@ -0,0 +1,156 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_VP_POOL_T_HPP +#define MOCKS_VP_POOL_T_HPP + +#include +#include +#include +#include + +#include +#include +#include + +namespace example +{ + /// @class example::vp_pool_t + /// + /// + /// @brief Defines the extension's VP pool + /// + class vp_pool_t final + { + /// @brief stores the return value for initialize + bsl::errc_type m_initialize{}; + /// @brief stores the return value for allocate + bsl::safe_uint16 m_allocate{}; + + public: + /// + /// @brief Initializes this vp_pool_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + return m_initialize; + } + + /// + /// @brief Sets the return value of initialize. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// initialize + /// + constexpr void + set_initialize(bsl::errc_type const &errc) noexcept + { + m_initialize = errc; + } + + /// + /// @brief Release the vp_pool_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + } + + /// + /// @brief Allocates a VP and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vmid the ID of the VM to assign the newly created VP to + /// @param ppid the ID of the PP to assign the newly created VP to + /// @return Returns the ID of the newly created VP on + /// success, or bsl::safe_uint16::failure() on failure. + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vmid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::safe_uint16 + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vmid); + bsl::discard(ppid); + + return m_allocate; + } + + /// + /// @brief Sets the return value of allocate. + /// (unit testing only) + /// + /// + /// @param val the bsl::safe_uint16 to return when executing + /// allocate + /// + constexpr void + set_allocate(bsl::safe_uint16 const &val) noexcept + { + m_allocate = val; + } + }; +} + +#endif diff --git a/example/default/mocks/vp_t.hpp b/example/default/mocks/vp_t.hpp new file mode 100644 index 00000000..4777a06d --- /dev/null +++ b/example/default/mocks/vp_t.hpp @@ -0,0 +1,126 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_VP_T_HPP +#define MOCKS_VP_T_HPP + +#include +#include +#include +#include + +#include +#include +#include + +namespace example +{ + /// @class example::vp_t + /// + /// + /// @brief Defines the extension's notion of a VP for unit testing. + /// + class vp_t final + { + public: + /// + /// @brief Initializes this vp_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param i the ID for this vp_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(i); + + return tls.test_ret; + } + + /// + /// @brief Release the vp_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + } + + /// + /// @brief Allocates a vp_t and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vmid the ID of the VM to assign the vp_t to + /// @param ppid the ID of the PP to assign the vp_t to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vmid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vmid); + bsl::discard(ppid); + + return tls.test_ret; + } + }; +} + +#endif diff --git a/example/default/mocks/vps_pool_t.hpp b/example/default/mocks/vps_pool_t.hpp new file mode 100644 index 00000000..6ccb5a41 --- /dev/null +++ b/example/default/mocks/vps_pool_t.hpp @@ -0,0 +1,156 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_VPS_POOL_T_HPP +#define MOCKS_VPS_POOL_T_HPP + +#include +#include +#include +#include + +#include +#include +#include + +namespace example +{ + /// @class example::vps_pool_t + /// + /// + /// @brief Defines the extension's VPS pool + /// + class vps_pool_t final + { + /// @brief stores the return value for initialize + bsl::errc_type m_initialize{}; + /// @brief stores the return value for allocate + bsl::safe_uint16 m_allocate{}; + + public: + /// + /// @brief Initializes this vps_pool_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + return m_initialize; + } + + /// + /// @brief Sets the return value of initialize. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// initialize + /// + constexpr void + set_initialize(bsl::errc_type const &errc) noexcept + { + m_initialize = errc; + } + + /// + /// @brief Release the vps_pool_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + } + + /// + /// @brief Allocates a VPS and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vpid the ID of the VP to assign the newly created VPS to + /// @param ppid the ID of the PP to assign the newly created VPS to + /// @return Returns the ID of the newly created VPS on + /// success, or bsl::safe_uint16::failure() on failure. + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::safe_uint16 + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vpid); + bsl::discard(ppid); + + return m_allocate; + } + + /// + /// @brief Sets the return value of allocate. + /// (unit testing only) + /// + /// + /// @param val the bsl::safe_uint16 to return when executing + /// allocate + /// + constexpr void + set_allocate(bsl::safe_uint16 const &val) noexcept + { + m_allocate = val; + } + }; +} + +#endif diff --git a/example/default/mocks/vps_t.hpp b/example/default/mocks/vps_t.hpp new file mode 100644 index 00000000..e265f024 --- /dev/null +++ b/example/default/mocks/vps_t.hpp @@ -0,0 +1,126 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_VPS_T_HPP +#define MOCKS_VPS_T_HPP + +#include +#include +#include +#include + +#include +#include +#include + +namespace example +{ + /// @class example::vps_t + /// + /// + /// @brief Defines the extension's notion of a VPS for unit testing. + /// + class vps_t final + { + public: + /// + /// @brief Initializes this vps_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param i the ID for this vps_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(i); + + return tls.test_ret; + } + + /// + /// @brief Release the vps_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + } + + /// + /// @brief Allocates a vps_t and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vpid the ID of the VP to assign the vps_t to + /// @param ppid the ID of the PP to assign the vps_t to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vpid); + bsl::discard(ppid); + + return tls.test_ret; + } + }; +} + +#endif diff --git a/example/default/mocks/x64/amd/gs_t.hpp b/example/default/mocks/x64/amd/gs_t.hpp new file mode 100644 index 00000000..64010a37 --- /dev/null +++ b/example/default/mocks/x64/amd/gs_t.hpp @@ -0,0 +1,45 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_GS_T_HPP +#define MOCKS_GS_T_HPP + +#include + +namespace example +{ + /// @class example::gs_t + /// + /// + /// @brief Defines the extension's mocked version of gs_t, used for + /// unit testing. Specifically, this version is architecture specific. + /// + struct gs_t final + { + /// @brief stores the cpuid value to return from intrinsic_cpuid_impl + bsl::safe_uint64 cpuid_val{}; + }; +} + +#endif diff --git a/example/default/mocks/x64/amd/intrinsic_t.hpp b/example/default/mocks/x64/amd/intrinsic_t.hpp new file mode 100644 index 00000000..07a9acac --- /dev/null +++ b/example/default/mocks/x64/amd/intrinsic_t.hpp @@ -0,0 +1,161 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_INTRINSIC_HPP +#define MOCKS_INTRINSIC_HPP + +#include +#include + +#include +#include +#include +#include + +namespace example +{ + /// @class example::intrinsic_t + /// + /// + /// @brief Provides raw access to intrinsics used for unit testing. + /// Specifically, this version is architecture specific. + /// + class intrinsic_t final + { + /// @brief stores the return value for initialize + bsl::errc_type m_initialize{}; + /// @brief stores the return value for eax with cpuid + bsl::safe_uint32 m_eax{}; + /// @brief stores the return value for ebx with cpuid + bsl::safe_uint32 m_ebx{}; + /// @brief stores the return value for ecx with cpuid + bsl::safe_uint32 m_ecx{}; + /// @brief stores the return value for edx with cpuid + bsl::safe_uint32 m_edx{}; + + public: + /// + /// @brief Initializes this intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize(gs_t &gs, tls_t &tls) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + + return m_initialize; + } + + /// + /// @brief Sets the return value of initialize. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// initialize + /// + constexpr void + set_initialize(bsl::errc_type const &errc) noexcept + { + m_initialize = errc; + } + + /// + /// @brief Release the intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + } + + /// + /// @brief Executes the CPUID instruction given the provided + /// EAX and ECX and returns the results. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param rax the index used by CPUID, returns resulting rax + /// @param rbx returns resulting rbx + /// @param rcx the subindex used by CPUID, returns the resulting rcx + /// @param rdx returns resulting rdx + /// + constexpr void + cpuid( + gs_t &gs, + tls_t &tls, + bsl::safe_uint64 &rax, + bsl::safe_uint64 &rbx, + bsl::safe_uint64 &rcx, + bsl::safe_uint64 &rdx) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + + constexpr auto mask{0xFFFFFFFF00000000_u64}; + + rax = ((rax & mask) | bsl::to_u64(m_eax)); + rbx = ((rbx & mask) | bsl::to_u64(m_ebx)); + rcx = ((rcx & mask) | bsl::to_u64(m_ecx)); + rdx = ((rdx & mask) | bsl::to_u64(m_edx)); + } + + /// + /// @brief Sets the return value of cpuid. + /// (unit testing only) + /// + /// + /// @param eax the value to return from cpuid for eax + /// @param ebx the value to return from cpuid for ebx + /// @param ecx the value to return from cpuid for ecx + /// @param edx the value to return from cpuid for edx + /// + constexpr void + set_cpuid( + bsl::safe_uint32 const &eax, + bsl::safe_uint32 const &ebx, + bsl::safe_uint32 const &ecx, + bsl::safe_uint32 const &edx) noexcept + { + m_eax = eax; + m_ebx = ebx; + m_ecx = ecx; + m_edx = edx; + } + }; +} + +#endif diff --git a/example/default/mocks/x64/amd/tls_t.hpp b/example/default/mocks/x64/amd/tls_t.hpp new file mode 100644 index 00000000..d49d6486 --- /dev/null +++ b/example/default/mocks/x64/amd/tls_t.hpp @@ -0,0 +1,46 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_TLS_T_HPP +#define MOCKS_TLS_T_HPP + +#include + +namespace example +{ + /// @class example::tls_t + /// + /// + /// @brief Defines the extension's mocked version of tls_t, used for + /// unit testing. Specifically, this version only contains portions + /// that are common for all architectures. + /// + struct tls_t final + { + /// @brief tells certain mocks when to fail + bsl::errc_type test_ret; + }; +} + +#endif diff --git a/example/default/mocks/x64/gs_t.hpp b/example/default/mocks/x64/gs_t.hpp new file mode 100644 index 00000000..64010a37 --- /dev/null +++ b/example/default/mocks/x64/gs_t.hpp @@ -0,0 +1,45 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_GS_T_HPP +#define MOCKS_GS_T_HPP + +#include + +namespace example +{ + /// @class example::gs_t + /// + /// + /// @brief Defines the extension's mocked version of gs_t, used for + /// unit testing. Specifically, this version is architecture specific. + /// + struct gs_t final + { + /// @brief stores the cpuid value to return from intrinsic_cpuid_impl + bsl::safe_uint64 cpuid_val{}; + }; +} + +#endif diff --git a/example/default/mocks/x64/intel/gs_t.hpp b/example/default/mocks/x64/intel/gs_t.hpp new file mode 100644 index 00000000..60144fae --- /dev/null +++ b/example/default/mocks/x64/intel/gs_t.hpp @@ -0,0 +1,49 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_GS_T_HPP +#define MOCKS_GS_T_HPP + +#include + +namespace example +{ + /// @class example::gs_t + /// + /// + /// @brief Defines the extension's mocked version of gs_t, used for + /// unit testing. Specifically, this version is architecture specific. + /// + struct gs_t final + { + /// @brief stores the cpuid value to return from intrinsic_cpuid_impl + bsl::safe_uint64 cpuid_val{}; + /// @brief stores the MSR bitmap used by this vps_t + void *msr_bitmap{}; + /// @brief stores the physical address of the MSR bitmap above + bsl::safe_uintmax msr_bitmap_phys{}; + }; +} + +#endif diff --git a/example/default/mocks/x64/intel/intrinsic_t.hpp b/example/default/mocks/x64/intel/intrinsic_t.hpp new file mode 100644 index 00000000..07a9acac --- /dev/null +++ b/example/default/mocks/x64/intel/intrinsic_t.hpp @@ -0,0 +1,161 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_INTRINSIC_HPP +#define MOCKS_INTRINSIC_HPP + +#include +#include + +#include +#include +#include +#include + +namespace example +{ + /// @class example::intrinsic_t + /// + /// + /// @brief Provides raw access to intrinsics used for unit testing. + /// Specifically, this version is architecture specific. + /// + class intrinsic_t final + { + /// @brief stores the return value for initialize + bsl::errc_type m_initialize{}; + /// @brief stores the return value for eax with cpuid + bsl::safe_uint32 m_eax{}; + /// @brief stores the return value for ebx with cpuid + bsl::safe_uint32 m_ebx{}; + /// @brief stores the return value for ecx with cpuid + bsl::safe_uint32 m_ecx{}; + /// @brief stores the return value for edx with cpuid + bsl::safe_uint32 m_edx{}; + + public: + /// + /// @brief Initializes this intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize(gs_t &gs, tls_t &tls) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + + return m_initialize; + } + + /// + /// @brief Sets the return value of initialize. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// initialize + /// + constexpr void + set_initialize(bsl::errc_type const &errc) noexcept + { + m_initialize = errc; + } + + /// + /// @brief Release the intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + } + + /// + /// @brief Executes the CPUID instruction given the provided + /// EAX and ECX and returns the results. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param rax the index used by CPUID, returns resulting rax + /// @param rbx returns resulting rbx + /// @param rcx the subindex used by CPUID, returns the resulting rcx + /// @param rdx returns resulting rdx + /// + constexpr void + cpuid( + gs_t &gs, + tls_t &tls, + bsl::safe_uint64 &rax, + bsl::safe_uint64 &rbx, + bsl::safe_uint64 &rcx, + bsl::safe_uint64 &rdx) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + + constexpr auto mask{0xFFFFFFFF00000000_u64}; + + rax = ((rax & mask) | bsl::to_u64(m_eax)); + rbx = ((rbx & mask) | bsl::to_u64(m_ebx)); + rcx = ((rcx & mask) | bsl::to_u64(m_ecx)); + rdx = ((rdx & mask) | bsl::to_u64(m_edx)); + } + + /// + /// @brief Sets the return value of cpuid. + /// (unit testing only) + /// + /// + /// @param eax the value to return from cpuid for eax + /// @param ebx the value to return from cpuid for ebx + /// @param ecx the value to return from cpuid for ecx + /// @param edx the value to return from cpuid for edx + /// + constexpr void + set_cpuid( + bsl::safe_uint32 const &eax, + bsl::safe_uint32 const &ebx, + bsl::safe_uint32 const &ecx, + bsl::safe_uint32 const &edx) noexcept + { + m_eax = eax; + m_ebx = ebx; + m_ecx = ecx; + m_edx = edx; + } + }; +} + +#endif diff --git a/example/default/mocks/x64/intel/tls_t.hpp b/example/default/mocks/x64/intel/tls_t.hpp new file mode 100644 index 00000000..d49d6486 --- /dev/null +++ b/example/default/mocks/x64/intel/tls_t.hpp @@ -0,0 +1,46 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_TLS_T_HPP +#define MOCKS_TLS_T_HPP + +#include + +namespace example +{ + /// @class example::tls_t + /// + /// + /// @brief Defines the extension's mocked version of tls_t, used for + /// unit testing. Specifically, this version only contains portions + /// that are common for all architectures. + /// + struct tls_t final + { + /// @brief tells certain mocks when to fail + bsl::errc_type test_ret; + }; +} + +#endif diff --git a/example/default/mocks/x64/intrinsic_cpuid_impl.hpp b/example/default/mocks/x64/intrinsic_cpuid_impl.hpp new file mode 100644 index 00000000..49120e75 --- /dev/null +++ b/example/default/mocks/x64/intrinsic_cpuid_impl.hpp @@ -0,0 +1,89 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_INTRINSIC_IMPL_PROTOTYPES_HPP +#define MOCKS_INTRINSIC_IMPL_PROTOTYPES_HPP + +#include + +#include +#include +#include +#include +#include + +namespace example +{ + /// + /// @brief Executes the CPUID instruction given the provided EAX and ECX + /// and returns the results + /// + /// + /// @param gs a pointer to the global storage to use + /// @param rax the index used by CPUID, returns resulting rax + /// @param rbx returns resulting rbx + /// @param rcx the subindex used by CPUID, returns the resulting rcx + /// @param rdx returns resulting rdx + /// + extern "C" constexpr void + intrinsic_cpuid_impl( + gs_t *const gs, + bsl::uint64 *const rax, + bsl::uint64 *const rbx, + bsl::uint64 *const rcx, + bsl::uint64 *const rdx) noexcept + { + if (bsl::unlikely_assert(nullptr == gs)) { + bsl::alert() << "gs is null\n" << bsl::here(); + return; + } + + if (bsl::unlikely_assert(nullptr == rax)) { + bsl::alert() << "rax is null\n" << bsl::here(); + return; + } + + if (bsl::unlikely_assert(nullptr == rbx)) { + bsl::alert() << "rbx is null\n" << bsl::here(); + return; + } + + if (bsl::unlikely_assert(nullptr == rcx)) { + bsl::alert() << "rcx is null\n" << bsl::here(); + return; + } + + if (bsl::unlikely_assert(nullptr == rdx)) { + bsl::alert() << "rdx is null\n" << bsl::here(); + return; + } + + *rax = gs->cpuid_val.get(); + *rbx = gs->cpuid_val.get(); + *rcx = gs->cpuid_val.get(); + *rdx = gs->cpuid_val.get(); + } +} + +#endif diff --git a/example/default/mocks/x64/tls_t.hpp b/example/default/mocks/x64/tls_t.hpp new file mode 100644 index 00000000..d49d6486 --- /dev/null +++ b/example/default/mocks/x64/tls_t.hpp @@ -0,0 +1,46 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_TLS_T_HPP +#define MOCKS_TLS_T_HPP + +#include + +namespace example +{ + /// @class example::tls_t + /// + /// + /// @brief Defines the extension's mocked version of tls_t, used for + /// unit testing. Specifically, this version only contains portions + /// that are common for all architectures. + /// + struct tls_t final + { + /// @brief tells certain mocks when to fail + bsl::errc_type test_ret; + }; +} + +#endif diff --git a/example/default/src/arm/aarch64/gs_t.hpp b/example/default/src/arm/aarch64/gs_t.hpp new file mode 100644 index 00000000..629f4be1 --- /dev/null +++ b/example/default/src/arm/aarch64/gs_t.hpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef GS_T_HPP +#define GS_T_HPP + +#include + +namespace example +{ + /// @class example::gs_t + /// + /// + /// @brief Defines the extension's Global Storage (GS). + /// Extensions can use this to store global variables as needed. + /// The gs_t can also be used during unit testing to store testing + /// specific logic and data to ensure tests can support constexpr + /// style unit testing. Also note that this is stored in the arch + /// specific folders as it usually needs to store arch specific + /// resources. + /// + struct gs_t final + { + /// @brief dummy data for example purposes only. + bsl::safe_uintmax dummy; + }; +} + +#endif diff --git a/example/default/src/arm/aarch64/intrinsic_t.hpp b/example/default/src/arm/aarch64/intrinsic_t.hpp new file mode 100644 index 00000000..32467e32 --- /dev/null +++ b/example/default/src/arm/aarch64/intrinsic_t.hpp @@ -0,0 +1,91 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INTRINSIC_HPP +#define INTRINSIC_HPP + +#include +#include + +#include +#include +#include + +namespace example +{ + /// @class example::intrinsic_t + /// + /// + /// @brief Provides raw access to intrinsics. Instead of using global + /// functions, the intrinsics class provides a means for the rest of + /// the extension to mock the intrinsics when needed during testing. + /// + class intrinsic_t final + { + public: + /// + /// @brief Initializes this intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize(gs_t &gs, tls_t &tls) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + + /// NOTE: + /// - Add initialization code here if needed. Otherwise, this + /// function can be removed if it is not needed. + /// + + return bsl::errc_success; + } + + /// + /// @brief Release the intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + } + }; +} + +#endif diff --git a/example/default/src/arm/aarch64/tls_t.hpp b/example/default/src/arm/aarch64/tls_t.hpp new file mode 100644 index 00000000..212eac9b --- /dev/null +++ b/example/default/src/arm/aarch64/tls_t.hpp @@ -0,0 +1,66 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TLS_T_HPP +#define TLS_T_HPP + +#include +#include + +namespace example +{ + /// @class example::tls_t + /// + /// + /// @brief Defines the extension's Thread Local Storage (TLS). + /// Extensions can use this to store data specific to a PP as needed. + /// The tls_t can also be used during unit testing to store testing + /// specific logic and data to ensure tests can support constexpr + /// style unit testing. Also note that this is stored in the arch + /// specific folders as it usually needs to store arch specific + /// resources. In this simple example, we leave this empty. + /// + /// + /// @note IMPORTANT: Extensions are limited to a single 4k page for the + /// TLS data. Technically, extensions are given 2 4k pages, but one of + /// the pages is dedicated to TLS data defined by the specification + /// and populated by the microkernel (e.g., the general purpose + /// registers and ID information). For this reason, if more than a + /// page is needed, the TLS block should store pointers to memory that + /// is allocated. + /// + struct tls_t final + { + /// @brief dummy data for example purposes only. + bsl::safe_uintmax dummy; + }; + + /// @brief defines the max size supported for the TLS block + constexpr auto MAX_TLS_SIZE{HYPERVISOR_PAGE_SIZE}; + + /// @brief ensure that the tls_t does not exceed the max supported size + static_assert(!(sizeof(tls_t) > MAX_TLS_SIZE)); +} + +#endif diff --git a/example/default/src/arm/aarch64/vmexit_t.hpp b/example/default/src/arm/aarch64/vmexit_t.hpp new file mode 100644 index 00000000..5fb37f5c --- /dev/null +++ b/example/default/src/arm/aarch64/vmexit_t.hpp @@ -0,0 +1,177 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_T_HPP +#define VMEXIT_T_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::vmexit_t + /// + /// + /// @brief Defines the extension's VMExit handler + /// + class vmexit_t final + { + public: + /// + /// @brief Initializes this vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + /// NOTE: + /// - Add initialization code here if needed. Otherwise, this + /// function can be removed if it is not needed. + /// + + return bsl::errc_success; + } + + /// + /// @brief Release the vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + } + + /// + /// @brief Dispatches the VMExit. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint64 const &exit_reason) noexcept -> bsl::errc_type + { + /// NOTE: + /// - Define the different VMExits that this dispatcher will + /// support. At a minimum, we need to handle CPUID on AMD. + /// + + /// NOTE: + /// - Dispatch and handle each VMExit. + /// + + switch (exit_reason.get()) { + default: { + break; + } + } + + /// NOTE: + /// - If we got this far, it means that we were given a VMExit + /// that we do not handle. + /// + + bsl::error() << "unsupported vmexit " // -- + << bsl::hex(exit_reason) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + }; +} + +#endif diff --git a/example/default/src/arm/aarch64/vps_t.hpp b/example/default/src/arm/aarch64/vps_t.hpp new file mode 100644 index 00000000..66bd3dca --- /dev/null +++ b/example/default/src/arm/aarch64/vps_t.hpp @@ -0,0 +1,308 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VPS_T_HPP +#define VPS_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::vps_t + /// + /// + /// @brief Defines the extension's notion of a VPS + /// + class vps_t final + { + /// @brief stores the ID associated with this vps_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + /// @brief stores the ID of the VP this vps_t is assigned to + bsl::safe_uint16 m_assigned_vpid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vps_t is assigned to + bsl::safe_uint16 m_assigned_ppid{syscall::BF_INVALID_ID}; + + public: + /// + /// @brief Initializes this vps_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param i the ID for this vps_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// not already initialized ourselves. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(m_id)) { + bsl::error() << "vps_t already initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following are some pedantic checks on the input. In + /// larger extensions, this is useful as it helps to weed + /// out hard to find bugs. In a small example like this, it + /// is completely overkill, but is added for completeness. + /// - We check to to make sure that we were given a valid ID, + /// meaning the safe integral is not storing an error, and we + /// also check to make sure the ID itself is not the reserved + /// syscall::BF_INVALID_ID as that is also not allowed. + /// + + if (bsl::unlikely_assert(!i)) { + bsl::error() << "invalid id\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == i)) { + bsl::error() << "id " // -- + << bsl::hex(i) // -- + << " is invalid and cannot be used for initialization" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + /// NOTE: + /// - Finally, store the ID assigned to this vps_t and report + /// success. + /// + + m_id = i; + return bsl::errc_success; + } + + /// + /// @brief Release the vps_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vpid = syscall::BF_INVALID_ID; + m_id = bsl::safe_uint16::failure(); + } + + /// + /// @brief Allocates a vps_t and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vpid the ID of the VP to assign the vps_t to + /// @param ppid the ID of the PP to assign the vps_t to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(intrinsic); + + bsl::errc_type ret{}; + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// been initialized by the vp_pool_t. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// not already allocated this vps_t. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is already allocated and cannot be created" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following are some pedantic checks on the input. In + /// larger extensions, this is useful as it helps to weed + /// out hard to find bugs. In a small example like this, it + /// is completely overkill, but is added for completeness. + /// - We check to to make sure that we were given a valid ID, + /// meaning the safe integral is not storing an error, and we + /// also check to make sure the ID itself is not the reserved + /// syscall::BF_INVALID_ID as that is also not allowed. + /// + + if (bsl::unlikely_assert(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == vpid)) { + bsl::error() << "vm " // -- + << bsl::hex(vpid) // -- + << " is invalid and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == ppid)) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is invalid and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + /// NOTE: + /// - Initialize the VPS as a root VPS. When the microkernel was + /// started, the loader saved the state of the root VP. This + /// syscall tells the microkernel to load the VPS with this saved + /// state so that when we run the VP, it will contain the state + /// just before the microkernel was started. + /// - In other words, this is what allows the microkernel to return + /// back to the loader once the hypervisor is running. + /// - You only want to run this on root VPs. VPs that are being + /// created for guest VPs should not use this, as it would give + /// the guest VP the state associated with the root VP. Also + /// note that once the root VP has executed, this ABI is no + /// longer useful as the state stored in the microkernel would be + /// out-dated. For root VPs, that ID of the PP should always be + /// the same as the IP of the VP, so we added this check for + /// completeness just in case cut/paste is used here. + /// + + if (ppid == m_id) { + ret = sys.bf_vps_op_init_as_root(m_id); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + else { + + /// NOTE: + /// - The call to bsl::touch is only needed if you plan to + /// enforce MC/DC unit testing. Feel free to remove this if + /// you have no plans to support MC/DC unit testing. + /// + + bsl::touch(); + } + + /// NOTE: + /// - Finally, store the IDs of the VP and PP that this vps_t is + /// assigned to and reprot success. + /// + + m_assigned_vpid = vpid; + m_assigned_ppid = ppid; + + return bsl::errc_success; + } + }; +} + +#endif diff --git a/example/default/src/bootstrap_t.hpp b/example/default/src/bootstrap_t.hpp new file mode 100644 index 00000000..f2fd67c1 --- /dev/null +++ b/example/default/src/bootstrap_t.hpp @@ -0,0 +1,193 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef BOOTSTRAP_T_HPP +#define BOOTSTRAP_T_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::bootstrap_t + /// + /// + /// @brief Defines the extension's bootstrap handler + /// + class bootstrap_t final + { + public: + /// + /// @brief Initializes this bootstrap_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + /// NOTE: + /// - Add initialization code here if needed. Otherwise, this + /// function can be removed if it is not needed. + /// + + return bsl::errc_success; + } + + /// + /// @brief Release the bootstrap_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + } + + /// + /// @brief Dispatches the bootstrap process as needed. Note that + /// the bootstrap callback is only called when starting the + /// hypervisor on root VPs. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param ppid the ID of the PP to bootstrap + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + /// NOTE: + /// - In order to execcute bf_vps_op_run, which is what executes + /// the hypervisor, we must have a VM, VP and VPS. + /// - The root VM is already created for us, so we don't need to + /// create this ourselves. You only need to create VM's if you + /// plan to add guest support with your extensions. + /// + + auto const vmid{syscall::BF_ROOT_VMID}; + + /// NOTE: + /// - The VP in this simple example does nothing, but we still need + /// to create one. The VP is used when you have more than one VPS + /// per VP (e.g., if you are implementing HyperV's VSM, or nested + /// virtualization support). Otherwise, you will always have one + /// VPS for each VP, and they will appear as the same thing. + /// - The VPS is what stores the state associated with the VPS. It + /// is the thing that does most of the work, including storing + /// the VMCS/VMCB and other CPU register state that is needed. + /// + + auto const vpid{vp_pool.allocate(gs, tls, sys, intrinsic, vmid, ppid)}; + if (bsl::unlikely_assert(!vpid)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const vpsid{vps_pool.allocate(gs, tls, sys, intrinsic, vpid, ppid)}; + if (bsl::unlikely_assert(!vpsid)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + /// NOTE: + /// - Run the newly created VP on behalf of the root VM using the + /// newly created and initialized VPS. Note that this version of + /// the run function should only be used when starting the + /// hypervisor, or switching the VM, VP or VPS as it is slow. + /// + + return sys.bf_vps_op_run(vmid, vpid, vpsid); + } + }; +} + +#endif diff --git a/example/default/src/fail_t.hpp b/example/default/src/fail_t.hpp new file mode 100644 index 00000000..9d4c62c5 --- /dev/null +++ b/example/default/src/fail_t.hpp @@ -0,0 +1,175 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef FAIL_T_HPP +#define FAIL_T_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace example +{ + /// @class example::fail_t + /// + /// + /// @brief Defines the extension's fail handler + /// + class fail_t final + { + public: + /// + /// @brief Initializes this fail_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + /// NOTE: + /// - Add initialization code here if needed. Otherwise, this + /// function can be removed if it is not needed. + /// + + return bsl::errc_success; + } + + /// + /// @brief Release the fail_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + } + + /// + /// @brief Dispatches the fail as needed, or returns an error so + /// that the microkernel can halt the PP. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint64 const &fail_reason) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + bsl::discard(vpsid); + bsl::discard(fail_reason); + + /// NOTE: + /// - Tells the microkernel that we didn't handle the fast fail. + /// When this occurs, the microkernel will halt this PP. In most + /// cases, there are only two options for how to handle a fail: + /// - Do the following, and report an error and halt. + /// - Return to a parent VPS and continue execution from there, + /// which is typically only possible if you are implementing + /// more than one VP/VPS per PP (e.g., when implementing guest + /// support, VSM support or nested virtualization support). + /// + /// - Another use case is integration testing. We can also use this + /// to generate faults that we can recover from to ensure the + /// fault system works properly during testing. + /// + + return bsl::errc_failure; + } + }; +} + +#endif diff --git a/example/default/src/main.cpp b/example/default/src/main.cpp new file mode 100644 index 00000000..f5cf0904 --- /dev/null +++ b/example/default/src/main.cpp @@ -0,0 +1,341 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace example +{ + /// NOTE: + /// - This is where we store all of our global and thread local variables. + /// All of the variables are marked as static to ensure they are not + /// visable to the rest of the code. + /// - All global and thread local variables must be passed around from + /// function to function as needed. This ensures that constexpr unit + /// tests work properly as the rest of the code never relies on global + /// variables. In addition, it dramatically simplifies unit testing, so + /// enforcing this coding style, although annoying for the function + /// signatures, makes working with the rest of the code a lot easier. + /// - We use constinit here, which works around a specific AUTOSAR rule + /// that does not allow global constructors/destructors. By using + /// constinit, we are sure that runtime global constructors are not used. + /// Bareflank does not attempt to run any init/fini sections of the + /// ELF binary, so if you use accidentally forget constinit, the code + /// will likely not execute and fail as a reminder. Instead, use the + /// initialization/release pattern that this example provides. + /// - From a unit testing point of view, each of these will have dummy + /// versions that are used for testing. When the code is compiled, each + /// source file and head file is compiled in isolation, meaning they are + /// not given include folder access to all of the code. This means that + /// each of these must be mocked, and the unit tests are given include + /// access to the mocks. This prevents the need for templates, and + /// instead, all mock injection is done using the build system, greatly + /// simplifying both the code and branch analysis during unit tests as + /// the removal of templates also removes issues with branches being + /// counted for each instantiaion of a template type. + /// - Finally, some of these are not really needed for this simple example, + /// but we added them for completness so that it is easier to get + /// started with your own extension as more complicated code will likely + /// need most of these if not all. + /// + + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + /// @brief stores the intrinsic_t that this code will use + constinit intrinsic_t g_intrinsic{}; + + /// @brief stores the pool of VPs that we will use + constinit vp_pool_t g_vp_pool{}; + /// @brief stores the pool of VPSs that we will use + constinit vps_pool_t g_vps_pool{}; + + /// @brief stores the bootstrap_t that this code will use + constinit bootstrap_t g_bootstrap{}; + /// @brief stores the fail_t that this code will use + constinit fail_t g_fail{}; + /// @brief stores the vmexit_t that this code will use + constinit vmexit_t g_vmexit{}; + + /// @brief stores the Global Storage for this extension + constinit gs_t g_gs{}; + /// @brief stores the Thread Local Storage for this extension on this PP + thread_local tls_t g_tls{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::errc_type ret{}; + + /// NOTE: + /// - Call into the bootstrap handler. This entry point serves as a + /// trampoline between C and C++. Specifically, the microkernel + /// cannot call a member function directly, and can only call + /// a C style function. + /// + + ret = g_bootstrap.dispatch( // -- + g_gs, // -- + g_tls, // -- + g_sys, // -- + g_intrinsic, // -- + g_vp_pool, // -- + g_vps_pool, // -- + ppid); + + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - This code should never be reached. The bootstrap handler should + /// always call one of the "run" ABIs to return back to the + /// microkernel when a bootstrap is finished. If this is called, it + /// is because the bootstrap handler returned with an error. + /// + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::errc_type ret{}; + + /// NOTE: + /// - Call into the fast fail handler. This entry point serves as a + /// trampoline between C and C++. Specifically, the microkernel + /// cannot call a member function directly, and can only call + /// a C style function. + /// + + ret = g_fail.dispatch( // -- + g_gs, // -- + g_tls, // -- + g_sys, // -- + g_intrinsic, // -- + g_vp_pool, // -- + g_vps_pool, // -- + vpsid, // -- + fail_reason); + + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - This code should never be reached. The fast fail handler should + /// always call one of the "run" ABIs to return back to the + /// microkernel when a fast fail is finished. If this is called, it + /// is because the fast fail handler returned with an error. + /// + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::errc_type ret{}; + + /// NOTE: + /// - Call into the vmexit handler. This entry point serves as a + /// trampoline between C and C++. Specifically, the microkernel + /// cannot call a member function directly, and can only call + /// a C style function. + /// + + ret = g_vmexit.dispatch( // -- + g_gs, // -- + g_tls, // -- + g_sys, // -- + g_intrinsic, // -- + g_vp_pool, // -- + g_vps_pool, // -- + vpsid, // -- + exit_reason); + + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - This code should never be reached. The VMExit handler should + /// always call one of the "run" ABIs to return back to the + /// microkernel when a VMExit is finished. If this is called, it + /// is because the VMExit handler returned with an error. + /// + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + /// NOTE: + /// - Initialize the bf_syscall_t. This will validate the ABI version, + /// open a handle to the microkernel and register the required + /// callbacks. If this fails, we call bf_control_op_exit, which is + /// similar to exit() from POSIX, except that the return value is + /// always the same. + /// + + ret = g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - Initialize the g_intrinsic. This can be used to add any init + /// logic that might be needed, otherwise it can be removed. + /// + + ret = g_intrinsic.initialize(g_gs, g_tls); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - Initialize the vp_pool_t. This will give all of our vp_t's + /// their IDs so that they can be allocated. + /// + + ret = g_vp_pool.initialize(g_gs, g_tls, g_sys, g_intrinsic); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - Initialize the vps_pool_t. This will give all of our vps_t's + /// their IDs so that they can be allocated. + /// + + ret = g_vps_pool.initialize(g_gs, g_tls, g_sys, g_intrinsic); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - Initialize the g_bootstrap. This can be used to add any init + /// logic that might be needed, otherwise it can be removed. + /// + + ret = g_bootstrap.initialize(g_gs, g_tls, g_sys, g_intrinsic, g_vp_pool, g_vps_pool); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - Initialize the g_fail. This can be used to add any init + /// logic that might be needed, otherwise it can be removed. + /// + + ret = g_fail.initialize(g_gs, g_tls, g_sys, g_intrinsic, g_vp_pool, g_vps_pool); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - Initialize the g_vmexit. This can be used to add any init + /// logic that might be needed, otherwise it can be removed. + /// + + ret = g_vmexit.initialize(g_gs, g_tls, g_sys, g_intrinsic, g_vp_pool, g_vps_pool); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - Wait for callbacks. Note that this function does not return. + /// The next time the extension is executed, it will be the + /// bootstrap callback that was just previously registered, which + /// will be called on each PP that is online. Failure to call this + /// function leads to undefined behaviour (likely a page fault). + /// - This is similar to the wait() function from POSIX after having + /// just started some processes, with the difference being that + /// this will never return, so there is no need to pass in status + /// as there is nothing to process after this call. + /// + + return syscall::bf_control_op_wait(); + } +} diff --git a/example/default/src/vp_pool_t.hpp b/example/default/src/vp_pool_t.hpp new file mode 100644 index 00000000..37928df5 --- /dev/null +++ b/example/default/src/vp_pool_t.hpp @@ -0,0 +1,228 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VP_POOL_T_HPP +#define VP_POOL_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::vp_pool_t + /// + /// + /// @brief Defines the extension's VP pool + /// + class vp_pool_t final + { + /// @brief stores the pool of VPs + bsl::array m_pool{}; + + public: + /// + /// @brief Initializes this vp_pool_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + -> bsl::errc_type + { + /// NOTE: + /// - The following is used in the event of an error. Basically, + /// whatever is in the bsl::finally will execute once the + /// function is returned from unless we explicitly call the + /// ignore() function, which we do at the end when all is good. + /// + + bsl::finally_assert release_on_error{ + [this, &gs, &tls, &sys, &intrinsic]() noexcept -> void { + this->release(gs, tls, sys, intrinsic); + }}; + + /// NOTE: + /// - Initialize all of the VPs. This basically gives each one it's + /// ID. We could spare some execution time if we wanted and only + /// initialize VPs equal to the online PPs (there is an ABI to + /// get that), as we are only going to have one VP per PP, so the + /// two totals are the same, but for now, this is just easier, + /// and it allows us to create more if needed. + /// + + bsl::errc_type ret{}; + for (bsl::safe_uintmax i{}; i < m_pool.size(); ++i) { + ret = m_pool.at_if(i)->initialize(gs, tls, sys, intrinsic, bsl::to_u16(i)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - The call to bsl::touch is only needed if you plan to + /// enforce MC/DC unit testing. Feel free to remove this if + /// you have no plans to support MC/DC unit testing. + /// + + bsl::touch(); + } + + release_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Release the vp_pool_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + + for (bsl::safe_uintmax i{}; i < m_pool.size(); ++i) { + m_pool.at_if(i)->release(gs, tls, sys, intrinsic); + } + } + + /// + /// @brief Allocates a VP and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vmid the ID of the VM to assign the newly created VP to + /// @param ppid the ID of the PP to assign the newly created VP to + /// @return Returns the ID of the newly created VP on + /// success, or bsl::safe_uint16::failure() on failure. + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vmid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::safe_uint16 + { + bsl::errc_type ret{}; + bsl::safe_uint16 vpid{}; + + /// NOTE: + /// - Ask the microkernel to create a VP and return the ID of the + /// newly created VP. We do not check in this function if the + /// provided vmid or ppid are valid as this is done by the + /// bf_vp_op_create_vp. We only need to check these types of + /// inputs at the point of use, and not when we are just passing + /// them to another function. + /// + + vpid = sys.bf_vp_op_create_vp(vmid, ppid); + if (bsl::unlikely_assert(!vpid)) { + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); + } + + /// NOTE: + /// - The following is used in the event of an error. Basically, + /// whatever is in the bsl::finally will execute once the + /// function is returned from unless we explicitly call the + /// ignore() function, which we do at the end when all is good. + /// + + bsl::finally destroy_vp_on_error{[&sys, &vpid]() noexcept -> void { + bsl::discard(sys.bf_vp_op_destroy_vp(vpid)); + }}; + + /// NOTE: + /// - We need to check to make sure that the provided ID fits + /// inside of our pool. Even with microkernel that use the same + /// ABI, this would possibly be an issue if the extension and + /// the microkernel did not use the same max limits. + /// + + auto *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() << "vpid " // -- + << bsl::hex(vpid) // -- + << " provided by the microkernel is invalid" // -- + << " or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + /// NOTE: + /// - Finally, we need to allocate the VP in our pool. This will + /// simply tell the VP which VM and PP it is assigned to. We + /// can use this in more complicated extensions, and it also + /// serves to make sure that we have not allocated the same VP + /// more than once. + /// + + ret = vp->allocate(gs, tls, sys, intrinsic, vmid, ppid); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); + } + + destroy_vp_on_error.ignore(); + return vpid; + } + }; +} + +#endif diff --git a/example/default/src/vp_t.hpp b/example/default/src/vp_t.hpp new file mode 100644 index 00000000..5c71da37 --- /dev/null +++ b/example/default/src/vp_t.hpp @@ -0,0 +1,268 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VP_T_HPP +#define VP_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace example +{ + /// @class example::vp_t + /// + /// + /// @brief Defines the extension's notion of a VP + /// + class vp_t final + { + /// @brief stores the ID associated with this vp_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + /// @brief stores the ID of the VM this vp_t is assigned to + bsl::safe_uint16 m_assigned_vmid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vp_t is assigned to + bsl::safe_uint16 m_assigned_ppid{syscall::BF_INVALID_ID}; + + public: + /// + /// @brief Initializes this vp_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param i the ID for this vp_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// not already initialized ourselves. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(m_id)) { + bsl::error() << "vp_t already initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following are some pedantic checks on the input. In + /// larger extensions, this is useful as it helps to weed + /// out hard to find bugs. In a small example like this, it + /// is completely overkill, but is added for completeness. + /// - We check to to make sure that we were given a valid ID, + /// meaning the safe integral is not storing an error, and we + /// also check to make sure the ID itself is not the reserved + /// syscall::BF_INVALID_ID as that is also not allowed. + /// + + if (bsl::unlikely_assert(!i)) { + bsl::error() << "invalid id\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == i)) { + bsl::error() << "id " // -- + << bsl::hex(i) // -- + << " is invalid and cannot be used for initialization" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + /// NOTE: + /// - Finally, store the ID assigned to this vp_t and report + /// success. + /// + + m_id = i; + return bsl::errc_success; + } + + /// + /// @brief Release the vp_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vmid = syscall::BF_INVALID_ID; + m_id = bsl::safe_uint16::failure(); + } + + /// + /// @brief Allocates a vp_t and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vmid the ID of the VM to assign the vp_t to + /// @param ppid the ID of the PP to assign the vp_t to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vmid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// been initialized by the vp_pool_t. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vp_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// not already allocated this vp_t. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is already allocated and cannot be created" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following are some pedantic checks on the input. In + /// larger extensions, this is useful as it helps to weed + /// out hard to find bugs. In a small example like this, it + /// is completely overkill, but is added for completeness. + /// - We check to to make sure that we were given a valid ID, + /// meaning the safe integral is not storing an error, and we + /// also check to make sure the ID itself is not the reserved + /// syscall::BF_INVALID_ID as that is also not allowed. + /// + + if (bsl::unlikely_assert(!vmid)) { + bsl::error() << "invalid vmid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == vmid)) { + bsl::error() << "vm " // -- + << bsl::hex(vmid) // -- + << " is invalid and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == ppid)) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is invalid and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + /// NOTE: + /// - Finally, store the IDs of the VM and PP that this vp_t is + /// assigned to and reprot success. + /// + + m_assigned_vmid = vmid; + m_assigned_ppid = ppid; + + return bsl::errc_success; + } + }; +} + +#endif diff --git a/example/default/src/vps_pool_t.hpp b/example/default/src/vps_pool_t.hpp new file mode 100644 index 00000000..2ec16dfc --- /dev/null +++ b/example/default/src/vps_pool_t.hpp @@ -0,0 +1,228 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VPS_POOL_T_HPP +#define VPS_POOL_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::vps_pool_t + /// + /// + /// @brief Defines the extension's VPS pool + /// + class vps_pool_t final + { + /// @brief stores the pool of VPSs + bsl::array m_pool{}; + + public: + /// + /// @brief Initializes this vps_pool_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + -> bsl::errc_type + { + /// NOTE: + /// - The following is used in the event of an error. Basically, + /// whatever is in the bsl::finally will execute once the + /// function is returned from unless we explicitly call the + /// ignore() function, which we do at the end when all is good. + /// + + bsl::finally_assert release_on_error{ + [this, &gs, &tls, &sys, &intrinsic]() noexcept -> void { + this->release(gs, tls, sys, intrinsic); + }}; + + /// NOTE: + /// - Initialize all of the VPSs. This basically gives each one it's + /// ID. We could spare some execution time if we wanted and only + /// initialize VPSs equal to the online PPs (there is an ABI to + /// get that), as we are only going to have one VPS per PP, so the + /// two totals are the same, but for now, this is just easier, + /// and it allows us to create more if needed. + /// + + bsl::errc_type ret{}; + for (bsl::safe_uintmax i{}; i < m_pool.size(); ++i) { + ret = m_pool.at_if(i)->initialize(gs, tls, sys, intrinsic, bsl::to_u16(i)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - The call to bsl::touch is only needed if you plan to + /// enforce MC/DC unit testing. Feel free to remove this if + /// you have no plans to support MC/DC unit testing. + /// + + bsl::touch(); + } + + release_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Release the vps_pool_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + + for (bsl::safe_uintmax i{}; i < m_pool.size(); ++i) { + m_pool.at_if(i)->release(gs, tls, sys, intrinsic); + } + } + + /// + /// @brief Allocates a VPS and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vpid the ID of the VP to assign the newly created VPS to + /// @param ppid the ID of the PP to assign the newly created VPS to + /// @return Returns the ID of the newly created VPS on + /// success, or bsl::safe_uint16::failure() on failure. + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::safe_uint16 + { + bsl::errc_type ret{}; + bsl::safe_uint16 vpsid{}; + + /// NOTE: + /// - Ask the microkernel to create a VPS and return the ID of the + /// newly created VPS. We do not check in this function if the + /// provided vmid or ppid are valid as this is done by the + /// bf_vp_op_create_vp. We only need to check these types of + /// inputs at the point of use, and not when we are just passing + /// them to another function. + /// + + vpsid = sys.bf_vps_op_create_vps(vpid, ppid); + if (bsl::unlikely_assert(!vpsid)) { + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); + } + + /// NOTE: + /// - The following is used in the event of an error. Basically, + /// whatever is in the bsl::finally will execute once the + /// function is returned from unless we explicitly call the + /// ignore() function, which we do at the end when all is good. + /// + + bsl::finally destroy_vps_on_error{[&sys, &vpsid]() noexcept -> void { + bsl::discard(sys.bf_vps_op_destroy_vps(vpsid)); + }}; + + /// NOTE: + /// - We need to check to make sure that the provided ID fits + /// inside of our pool. Even with microkernel that use the same + /// ABI, this would possibly be an issue if the extension and + /// the microkernel did not use the same max limits. + /// + + auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " provided by the microkernel is invalid" // -- + << " or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + /// NOTE: + /// - Finally, we need to allocate the VPS in our pool. This will + /// simply tell the VPS which VP and PP it is assigned to. We + /// can use this in more complicated extensions, and it also + /// serves to make sure that we have not allocated the same VPS + /// more than once. + /// + + ret = vps->allocate(gs, tls, sys, intrinsic, vpid, ppid); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); + } + + destroy_vps_on_error.ignore(); + return vpsid; + } + }; +} + +#endif diff --git a/example/default/src/x64/amd/gs_t.hpp b/example/default/src/x64/amd/gs_t.hpp new file mode 100644 index 00000000..629f4be1 --- /dev/null +++ b/example/default/src/x64/amd/gs_t.hpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef GS_T_HPP +#define GS_T_HPP + +#include + +namespace example +{ + /// @class example::gs_t + /// + /// + /// @brief Defines the extension's Global Storage (GS). + /// Extensions can use this to store global variables as needed. + /// The gs_t can also be used during unit testing to store testing + /// specific logic and data to ensure tests can support constexpr + /// style unit testing. Also note that this is stored in the arch + /// specific folders as it usually needs to store arch specific + /// resources. + /// + struct gs_t final + { + /// @brief dummy data for example purposes only. + bsl::safe_uintmax dummy; + }; +} + +#endif diff --git a/example/default/src/x64/amd/intrinsic_t.hpp b/example/default/src/x64/amd/intrinsic_t.hpp new file mode 100644 index 00000000..00cf71fb --- /dev/null +++ b/example/default/src/x64/amd/intrinsic_t.hpp @@ -0,0 +1,117 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INTRINSIC_HPP +#define INTRINSIC_HPP + +#include +#include +#include + +#include +#include +#include + +namespace example +{ + /// @class example::intrinsic_t + /// + /// + /// @brief Provides raw access to intrinsics. Instead of using global + /// functions, the intrinsics class provides a means for the rest of + /// the extension to mock the intrinsics when needed during testing. + /// + class intrinsic_t final + { + public: + /// + /// @brief Initializes this intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize(gs_t &gs, tls_t &tls) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + + /// NOTE: + /// - Add initialization code here if needed. Otherwise, this + /// function can be removed if it is not needed. + /// + + return bsl::errc_success; + } + + /// + /// @brief Release the intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + } + + /// + /// @brief Executes the CPUID instruction given the provided + /// EAX and ECX and returns the results. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param rax the index used by CPUID, returns resulting rax + /// @param rbx returns resulting rbx + /// @param rcx the subindex used by CPUID, returns the resulting rcx + /// @param rdx returns resulting rdx + /// + static constexpr void + cpuid( + gs_t &gs, + tls_t &tls, + bsl::safe_uint64 &rax, + bsl::safe_uint64 &rbx, + bsl::safe_uint64 &rcx, + bsl::safe_uint64 &rdx) noexcept + { + bsl::discard(tls); + intrinsic_cpuid_impl(&gs, rax.data(), rbx.data(), rcx.data(), rdx.data()); + } + }; +} + +#endif diff --git a/example/default/src/x64/amd/tls_t.hpp b/example/default/src/x64/amd/tls_t.hpp new file mode 100644 index 00000000..212eac9b --- /dev/null +++ b/example/default/src/x64/amd/tls_t.hpp @@ -0,0 +1,66 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TLS_T_HPP +#define TLS_T_HPP + +#include +#include + +namespace example +{ + /// @class example::tls_t + /// + /// + /// @brief Defines the extension's Thread Local Storage (TLS). + /// Extensions can use this to store data specific to a PP as needed. + /// The tls_t can also be used during unit testing to store testing + /// specific logic and data to ensure tests can support constexpr + /// style unit testing. Also note that this is stored in the arch + /// specific folders as it usually needs to store arch specific + /// resources. In this simple example, we leave this empty. + /// + /// + /// @note IMPORTANT: Extensions are limited to a single 4k page for the + /// TLS data. Technically, extensions are given 2 4k pages, but one of + /// the pages is dedicated to TLS data defined by the specification + /// and populated by the microkernel (e.g., the general purpose + /// registers and ID information). For this reason, if more than a + /// page is needed, the TLS block should store pointers to memory that + /// is allocated. + /// + struct tls_t final + { + /// @brief dummy data for example purposes only. + bsl::safe_uintmax dummy; + }; + + /// @brief defines the max size supported for the TLS block + constexpr auto MAX_TLS_SIZE{HYPERVISOR_PAGE_SIZE}; + + /// @brief ensure that the tls_t does not exceed the max supported size + static_assert(!(sizeof(tls_t) > MAX_TLS_SIZE)); +} + +#endif diff --git a/example/default/src/x64/amd/vmexit_t.hpp b/example/default/src/x64/amd/vmexit_t.hpp new file mode 100644 index 00000000..b51a8ef6 --- /dev/null +++ b/example/default/src/x64/amd/vmexit_t.hpp @@ -0,0 +1,401 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_T_HPP +#define VMEXIT_T_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::vmexit_t + /// + /// + /// @brief Defines the extension's VMExit handler + /// + class vmexit_t final + { + public: + /// + /// @brief Initializes this vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + /// NOTE: + /// - Add initialization code here if needed. Otherwise, this + /// function can be removed if it is not needed. + /// + + return bsl::errc_success; + } + + /// + /// @brief Release the vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + } + + /// + /// @brief Handles the CPUID VMexit + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + handle_cpuid( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + { + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + bsl::errc_type ret{}; + + /// NOTE: + /// - The first thing that we need to do is get the current values + /// of RAX, RBX, RCX and RDX. We use the full 64bit versions to + /// ensure that we leave the upper half of these values intact, + /// otherwise we would not be emulating the execution of CPUID + /// correctly. + /// + + auto rax{sys.bf_tls_rax()}; + auto rbx{sys.bf_tls_rbx()}; + auto rcx{sys.bf_tls_rcx()}; + auto rdx{sys.bf_tls_rdx()}; + + /// NOTE: + /// - Before we execute CPUID, we need to check to see if we have + /// received a CPUID command. If we have, we need to handle this + /// CPUID differently. + /// + + if (loader::CPUID_COMMAND_EAX == bsl::to_u32_unsafe(rax)) { + switch (bsl::to_u32_unsafe(rcx).get()) { + case loader::CPUID_COMMAND_ECX_STOP.get(): { + + /// NOTE: + /// - If this is the first PP to stop (which is the + /// last PP in the list as we stop in reverse order), + /// print out how much memory was used by the + /// hypervisor. This is a debugging feature that can + /// be disabled, but it helps to track if memory is + /// being over used. + /// + + if (sys.bf_tls_ppid() == (sys.bf_tls_online_pps() - 1_u16)) { + bsl::print() << bsl::endl; + syscall::bf_debug_op_dump_page_pool(); + bsl::print() << bsl::endl; + } + else { + bsl::touch(); + } + + /// NOTE: + /// - If the debug level is set to something higher + /// than bsl::V, we can print out a VMExit log. How + /// many entries we print is configurable, and you + /// can control which PP you want to output if you + /// only care about a specific PP. Note that this log + /// will show VMExits for the whole PP, meaning you + /// will see the order in which different VM's are + /// making VMExits. The VMExit log doesn't attempt + /// to decode anything, so that is up to you. + /// + + if constexpr (BSL_DEBUG_LEVEL > bsl::V) { + bsl::print() << bsl::endl; + syscall::bf_debug_op_dump_vmexit_log(sys.bf_tls_ppid()); + } + + /// NOTE: + /// - Report that the root OS is no longer in a VM for + /// this specific PP. Note that you can do whatever + /// you want here, this is just the default behavior. + /// To report success on promotion after promotion + /// takes place would require that the loader reports + /// success, which we do not do as we are not sure + /// what the extension wants, so the message here + /// should state that we are "about to", and not that + /// it is "done", because it might fail. + /// + + bsl::debug() << bsl::rst << "about to" // -- + << bsl::red << " promote " // -- + << bsl::rst << "root OS on pp " // -- + << bsl::cyn << bsl::hex(sys.bf_tls_ppid()) // -- + << bsl::rst << bsl::endl; // -- + + /// NOTE: + /// - Report success + /// + + sys.bf_tls_set_rax(loader::CPUID_COMMAND_RAX_SUCCESS); + + /// NOTE: + /// - Before we can stop, we need to advance RIP. + /// Normally, all of the other commands will advance + /// and return to the VM at the end of this switch + /// statement, but in this case, promote will not + /// exit before then so we need to advance now. + /// + + ret = sys.bf_vps_op_advance_ip(vpsid); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - The promote ABI will load the microkernel by + /// replacing the CPU's state withthe VP state + /// associated with the provided VPSID. If all + /// goes well, bf_vps_op_promote will not return, + /// and the system will continue executing with the + /// hypervisor turned off. + /// + + return sys.bf_vps_op_promote(vpsid); + } + + case loader::CPUID_COMMAND_ECX_REPORT_ON.get(): { + + /// NOTE: + /// - Report that the root OS is now in a VM for this + /// specific PP. Note that you can do whatever you + /// want here, this is just the default behavior. + /// + + bsl::debug() << bsl::rst << "root OS had been" // -- + << bsl::grn << " demoted " // -- + << bsl::rst << "to vm " // -- + << bsl::cyn << bsl::hex(sys.bf_tls_vmid()) // -- + << bsl::rst << " on pp " // -- + << bsl::cyn << bsl::hex(sys.bf_tls_ppid()) // -- + << bsl::rst << bsl::endl; // -- + + break; + } + + case loader::CPUID_COMMAND_ECX_REPORT_OFF.get(): { + + /// NOTE: + /// - There is nothing to do here as we report off + /// right before promotion takes place. Extensions + /// can use this as a means to perform actions if + /// needed right before the loader sends the stop + /// command. Just note that this command does not + /// report success/failure. + /// + + break; + } + + default: { + bsl::error() << "unsupported cpuid command " // -- + << bsl::hex(rcx) // -- + << bsl::endl // -- + << bsl::here(); // -- + + break; + } + } + + /// NOTE: + /// - Complete this command by advancing RIP and running + /// the currently loaded VM, VP and VPS. + /// + + return sys.bf_vps_op_advance_ip_and_run_current(); + } + + /// NOTE: + /// - If we got this far, this is a normal CPUID, which means we + /// simply need to emulate its execution by calling CPUID and + /// returning the results. + /// + + intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx); + + /// NOTE: + /// - Write the results of CPUID to the VP's registers. Note that + /// the above CPUID intrinsic takes in the full 64bit registers + /// but only touches the lower half of each register, which makes + /// sure that we are emulating CPUID properly. + /// + + sys.bf_tls_set_rax(rax); + sys.bf_tls_set_rbx(rbx); + sys.bf_tls_set_rcx(rcx); + sys.bf_tls_set_rdx(rdx); + + /// NOTE: + /// - Complete the emulation of CPUID by advancing RIP and running + /// the currently loaded VM, VP and VPS. + /// + + return sys.bf_vps_op_advance_ip_and_run_current(); + } + + /// + /// @brief Dispatches the VMExit. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint64 const &exit_reason) noexcept -> bsl::errc_type + { + /// NOTE: + /// - Define the different VMExits that this dispatcher will + /// support. At a minimum, we need to handle CPUID on AMD. + /// + + constexpr auto exit_reason_cpuid{0x72_u64}; + + /// NOTE: + /// - Dispatch and handle each VMExit. + /// + + switch (exit_reason.get()) { + case exit_reason_cpuid.get(): { + return handle_cpuid(gs, tls, sys, intrinsic, vp_pool, vps_pool, vpsid); + } + + default: { + break; + } + } + + /// NOTE: + /// - If we got this far, it means that we were given a VMExit + /// that we do not handle. + /// + + bsl::error() << "unsupported vmexit " // -- + << bsl::hex(exit_reason) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + }; +} + +#endif diff --git a/example/default/src/x64/amd/vps_t.hpp b/example/default/src/x64/amd/vps_t.hpp new file mode 100644 index 00000000..9d0d49ea --- /dev/null +++ b/example/default/src/x64/amd/vps_t.hpp @@ -0,0 +1,347 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VPS_T_HPP +#define VPS_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::vps_t + /// + /// + /// @brief Defines the extension's notion of a VPS + /// + class vps_t final + { + /// @brief stores the ID associated with this vps_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + /// @brief stores the ID of the VP this vps_t is assigned to + bsl::safe_uint16 m_assigned_vpid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vps_t is assigned to + bsl::safe_uint16 m_assigned_ppid{syscall::BF_INVALID_ID}; + + public: + /// + /// @brief Initializes this vps_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param i the ID for this vps_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// not already initialized ourselves. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(m_id)) { + bsl::error() << "vps_t already initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following are some pedantic checks on the input. In + /// larger extensions, this is useful as it helps to weed + /// out hard to find bugs. In a small example like this, it + /// is completely overkill, but is added for completeness. + /// - We check to to make sure that we were given a valid ID, + /// meaning the safe integral is not storing an error, and we + /// also check to make sure the ID itself is not the reserved + /// syscall::BF_INVALID_ID as that is also not allowed. + /// + + if (bsl::unlikely_assert(!i)) { + bsl::error() << "invalid id\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == i)) { + bsl::error() << "id " // -- + << bsl::hex(i) // -- + << " is invalid and cannot be used for initialization" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + /// NOTE: + /// - Finally, store the ID assigned to this vps_t and report + /// success. + /// + + m_id = i; + return bsl::errc_success; + } + + /// + /// @brief Release the vps_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vpid = syscall::BF_INVALID_ID; + m_id = bsl::safe_uint16::failure(); + } + + /// + /// @brief Allocates a vps_t and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vpid the ID of the VP to assign the vps_t to + /// @param ppid the ID of the PP to assign the vps_t to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(intrinsic); + + bsl::errc_type ret{}; + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// been initialized by the vp_pool_t. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// not already allocated this vps_t. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is already allocated and cannot be created" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following are some pedantic checks on the input. In + /// larger extensions, this is useful as it helps to weed + /// out hard to find bugs. In a small example like this, it + /// is completely overkill, but is added for completeness. + /// - We check to to make sure that we were given a valid ID, + /// meaning the safe integral is not storing an error, and we + /// also check to make sure the ID itself is not the reserved + /// syscall::BF_INVALID_ID as that is also not allowed. + /// + + if (bsl::unlikely_assert(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == vpid)) { + bsl::error() << "vm " // -- + << bsl::hex(vpid) // -- + << " is invalid and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == ppid)) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is invalid and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + /// NOTE: + /// - Initialize the VPS as a root VPS. When the microkernel was + /// started, the loader saved the state of the root VP. This + /// syscall tells the microkernel to load the VPS with this saved + /// state so that when we run the VP, it will contain the state + /// just before the microkernel was started. + /// - In other words, this is what allows the microkernel to return + /// back to the loader once the hypervisor is running. + /// - You only want to run this on root VPs. VPs that are being + /// created for guest VPs should not use this, as it would give + /// the guest VP the state associated with the root VP. Also + /// note that once the root VP has executed, this ABI is no + /// longer useful as the state stored in the microkernel would be + /// out-dated. For root VPs, that ID of the PP should always be + /// the same as the IP of the VP, so we added this check for + /// completeness just in case cut/paste is used here. + /// + + if (ppid == m_id) { + ret = sys.bf_vps_op_init_as_root(m_id); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + else { + + /// NOTE: + /// - The call to bsl::touch is only needed if you plan to + /// enforce MC/DC unit testing. Feel free to remove this if + /// you have no plans to support MC/DC unit testing. + /// + + bsl::touch(); + } + + /// NOTE: + /// - Set up ASID. For this simple example, we will use "1", but + /// in most cases you will want to use something based on the + /// VMID that this VPS is assigned to (which is based on which + /// VP the VPS is assigned to, as VPs are assigned to VMs and + /// VPSs are assigned to VPs). + /// + + constexpr auto guest_asid_idx{0x0058_u64}; + constexpr auto guest_asid_val{0x1_u32}; + + ret = sys.bf_vps_op_write32(m_id, guest_asid_idx, guest_asid_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Set up intercept controls. On AMD, we need to intercept + /// VMRun, and CPUID if we plan to support reporting and stopping. + /// + + constexpr auto intercept_instr1_idx{0x000C_u64}; + constexpr auto intercept_instr1_val{0x00040000_u32}; + constexpr auto intercept_instr2_idx{0x0010_u64}; + constexpr auto intercept_instr2_val{0x00000001_u32}; + + ret = sys.bf_vps_op_write32(m_id, intercept_instr1_idx, intercept_instr1_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + ret = sys.bf_vps_op_write32(m_id, intercept_instr2_idx, intercept_instr2_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Finally, store the IDs of the VP and PP that this vps_t is + /// assigned to and reprot success. + /// + + m_assigned_vpid = vpid; + m_assigned_ppid = ppid; + + return bsl::errc_success; + } + }; +} + +#endif diff --git a/example/default/src/x64/intel/gs_t.hpp b/example/default/src/x64/intel/gs_t.hpp new file mode 100644 index 00000000..9ac1f1bf --- /dev/null +++ b/example/default/src/x64/intel/gs_t.hpp @@ -0,0 +1,52 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef GS_T_HPP +#define GS_T_HPP + +#include + +namespace example +{ + /// @class example::gs_t + /// + /// + /// @brief Defines the extension's Global Storage (GS). + /// Extensions can use this to store global variables as needed. + /// The gs_t can also be used during unit testing to store testing + /// specific logic and data to ensure tests can support constexpr + /// style unit testing. Also note that this is stored in the arch + /// specific folders as it usually needs to store arch specific + /// resources. + /// + struct gs_t final + { + /// @brief stores the MSR bitmap used by this vps_t + void *msr_bitmap{}; + /// @brief stores the physical address of the MSR bitmap above + bsl::safe_uintmax msr_bitmap_phys{}; + }; +} + +#endif diff --git a/example/default/src/x64/intel/intrinsic_t.hpp b/example/default/src/x64/intel/intrinsic_t.hpp new file mode 100644 index 00000000..00cf71fb --- /dev/null +++ b/example/default/src/x64/intel/intrinsic_t.hpp @@ -0,0 +1,117 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INTRINSIC_HPP +#define INTRINSIC_HPP + +#include +#include +#include + +#include +#include +#include + +namespace example +{ + /// @class example::intrinsic_t + /// + /// + /// @brief Provides raw access to intrinsics. Instead of using global + /// functions, the intrinsics class provides a means for the rest of + /// the extension to mock the intrinsics when needed during testing. + /// + class intrinsic_t final + { + public: + /// + /// @brief Initializes this intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize(gs_t &gs, tls_t &tls) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + + /// NOTE: + /// - Add initialization code here if needed. Otherwise, this + /// function can be removed if it is not needed. + /// + + return bsl::errc_success; + } + + /// + /// @brief Release the intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + } + + /// + /// @brief Executes the CPUID instruction given the provided + /// EAX and ECX and returns the results. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param rax the index used by CPUID, returns resulting rax + /// @param rbx returns resulting rbx + /// @param rcx the subindex used by CPUID, returns the resulting rcx + /// @param rdx returns resulting rdx + /// + static constexpr void + cpuid( + gs_t &gs, + tls_t &tls, + bsl::safe_uint64 &rax, + bsl::safe_uint64 &rbx, + bsl::safe_uint64 &rcx, + bsl::safe_uint64 &rdx) noexcept + { + bsl::discard(tls); + intrinsic_cpuid_impl(&gs, rax.data(), rbx.data(), rcx.data(), rdx.data()); + } + }; +} + +#endif diff --git a/example/default/src/x64/intel/tls_t.hpp b/example/default/src/x64/intel/tls_t.hpp new file mode 100644 index 00000000..212eac9b --- /dev/null +++ b/example/default/src/x64/intel/tls_t.hpp @@ -0,0 +1,66 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TLS_T_HPP +#define TLS_T_HPP + +#include +#include + +namespace example +{ + /// @class example::tls_t + /// + /// + /// @brief Defines the extension's Thread Local Storage (TLS). + /// Extensions can use this to store data specific to a PP as needed. + /// The tls_t can also be used during unit testing to store testing + /// specific logic and data to ensure tests can support constexpr + /// style unit testing. Also note that this is stored in the arch + /// specific folders as it usually needs to store arch specific + /// resources. In this simple example, we leave this empty. + /// + /// + /// @note IMPORTANT: Extensions are limited to a single 4k page for the + /// TLS data. Technically, extensions are given 2 4k pages, but one of + /// the pages is dedicated to TLS data defined by the specification + /// and populated by the microkernel (e.g., the general purpose + /// registers and ID information). For this reason, if more than a + /// page is needed, the TLS block should store pointers to memory that + /// is allocated. + /// + struct tls_t final + { + /// @brief dummy data for example purposes only. + bsl::safe_uintmax dummy; + }; + + /// @brief defines the max size supported for the TLS block + constexpr auto MAX_TLS_SIZE{HYPERVISOR_PAGE_SIZE}; + + /// @brief ensure that the tls_t does not exceed the max supported size + static_assert(!(sizeof(tls_t) > MAX_TLS_SIZE)); +} + +#endif diff --git a/example/default/src/x64/intel/vmexit_t.hpp b/example/default/src/x64/intel/vmexit_t.hpp new file mode 100644 index 00000000..871e7af4 --- /dev/null +++ b/example/default/src/x64/intel/vmexit_t.hpp @@ -0,0 +1,570 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_T_HPP +#define VMEXIT_T_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::vmexit_t + /// + /// + /// @brief Defines the extension's VMExit handler + /// + class vmexit_t final + { + public: + /// + /// @brief Initializes this vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + gs.msr_bitmap = sys.bf_mem_op_alloc_page(gs.msr_bitmap_phys); + if (bsl::unlikely_assert(nullptr == gs.msr_bitmap)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + /// NOTE: + /// - Add initialization code here if needed. Otherwise, this + /// function can be removed if it is not needed. + /// + + return bsl::errc_success; + } + + /// + /// @brief Release the vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::errc_type ret{}; + + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + + ret = sys.bf_mem_op_free_page(gs.msr_bitmap); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + } + else { + bsl::touch(); + } + + gs.msr_bitmap = {}; + gs.msr_bitmap_phys = {}; + } + + /// + /// @brief Handle NMIs. This is required by Intel. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + handle_nmi( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + /// NOTE: + /// - If we caught an NMI, we need to inject it into the VM. To do + /// this, all we do is enable the NMI window, which will tell us + /// when we can safely inject the NMI. + /// - Note that the microkernel will do the same thing. If an NMI + /// fires while the hypevisor is running, it will enable the NMI + /// window, which the extension will see as a VMExit, and must + /// from there, inject the NMI into the appropriate VPS. + /// + + constexpr auto vmcs_procbased_ctls_idx{0x4002_u64}; + constexpr auto vmcs_set_nmi_window_exiting{0x400000_u32}; + + bsl::safe_uint32 val{}; + bsl::errc_type ret{}; + + val = sys.bf_vps_op_read32(vpsid, vmcs_procbased_ctls_idx); + if (bsl::unlikely_assert(!val)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + val |= vmcs_set_nmi_window_exiting; + + ret = sys.bf_vps_op_write32(vpsid, vmcs_procbased_ctls_idx, val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return sys.bf_vps_op_run_current(); + } + + /// + /// @brief Handle NMIs Windows + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + handle_nmi_window( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + /// NOTE: + /// - If we see this exit, it is because an NMI fired. There are two + /// situations where this could occur, either while the hypervisor + /// is running, or the VPS is running. In either case, we need to + /// clear the NMI window and inject the NMI into the appropriate + /// VPS so that it can be handled. Note that Intel requires that + /// we handle NMIs, and they actually happen a lot with Linux based + /// on what hardware you are using (e.g., a laptop). + /// + + constexpr auto vmcs_procbased_ctls_idx{0x4002_u64}; + constexpr auto vmcs_clear_nmi_window_exiting{0xFFBFFFFF_u32}; + + bsl::safe_uint32 val{}; + bsl::errc_type ret{}; + + val = sys.bf_vps_op_read32(vpsid, vmcs_procbased_ctls_idx); + if (bsl::unlikely_assert(!val)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + val &= vmcs_clear_nmi_window_exiting; + + ret = sys.bf_vps_op_write32(vpsid, vmcs_procbased_ctls_idx, val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Inject an NMI. If the NMI window was enabled, it is because we + /// need to inject a NMI. Note that the NMI window can be enabled + /// both by this extension, as well as by the microkernel itself, + /// so we are required to implement it on Intel. + /// + + constexpr auto vmcs_entry_interrupt_info_idx{0x4016_u64}; + constexpr auto vmcs_entry_interrupt_info_val{0x80000202_u32}; + + ret = sys.bf_vps_op_write32( + vpsid, vmcs_entry_interrupt_info_idx, vmcs_entry_interrupt_info_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return sys.bf_vps_op_run_current(); + } + + /// + /// @brief Handles the CPUID VMexit + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + handle_cpuid( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + { + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + bsl::errc_type ret{}; + + /// NOTE: + /// - The first thing that we need to do is get the current values + /// of RAX, RBX, RCX and RDX. We use the full 64bit versions to + /// ensure that we leave the upper half of these values intact, + /// otherwise we would not be emulating the execution of CPUID + /// correctly. + /// + + auto rax{sys.bf_tls_rax()}; + auto rbx{sys.bf_tls_rbx()}; + auto rcx{sys.bf_tls_rcx()}; + auto rdx{sys.bf_tls_rdx()}; + + /// NOTE: + /// - Before we execute CPUID, we need to check to see if we have + /// received a CPUID command. If we have, we need to handle this + /// CPUID differently. + /// + + if (loader::CPUID_COMMAND_EAX == bsl::to_u32_unsafe(rax)) { + switch (bsl::to_u32_unsafe(rcx).get()) { + case loader::CPUID_COMMAND_ECX_STOP.get(): { + + /// NOTE: + /// - If this is the first PP to stop (which is the + /// last PP in the list as we stop in reverse order), + /// print out how much memory was used by the + /// hypervisor. This is a debugging feature that can + /// be disabled, but it helps to track if memory is + /// being over used. + /// + + if (sys.bf_tls_ppid() == (sys.bf_tls_online_pps() - 1_u16)) { + bsl::print() << bsl::endl; + syscall::bf_debug_op_dump_page_pool(); + bsl::print() << bsl::endl; + } + else { + bsl::touch(); + } + + /// NOTE: + /// - If the debug level is set to something higher + /// than bsl::V, we can print out a VMExit log. How + /// many entries we print is configurable, and you + /// can control which PP you want to output if you + /// only care about a specific PP. Note that this log + /// will show VMExits for the whole PP, meaning you + /// will see the order in which different VM's are + /// making VMExits. The VMExit log doesn't attempt + /// to decode anything, so that is up to you. + /// + + if constexpr (BSL_DEBUG_LEVEL > bsl::V) { + bsl::print() << bsl::endl; + syscall::bf_debug_op_dump_vmexit_log(sys.bf_tls_ppid()); + } + + /// NOTE: + /// - Report that the root OS is no longer in a VM for + /// this specific PP. Note that you can do whatever + /// you want here, this is just the default behavior. + /// To report success on promotion after promotion + /// takes place would require that the loader reports + /// success, which we do not do as we are not sure + /// what the extension wants, so the message here + /// should state that we are "about to", and not that + /// it is "done", because it might fail. + /// + + bsl::debug() << bsl::rst << "about to" // -- + << bsl::red << " promote " // -- + << bsl::rst << "root OS on pp " // -- + << bsl::cyn << bsl::hex(sys.bf_tls_ppid()) // -- + << bsl::rst << bsl::endl; // -- + + /// NOTE: + /// - Report success + /// + + sys.bf_tls_set_rax(loader::CPUID_COMMAND_RAX_SUCCESS); + + /// NOTE: + /// - Before we can stop, we need to advance RIP. + /// Normally, all of the other commands will advance + /// and return to the VM at the end of this switch + /// statement, but in this case, promote will not + /// exit before then so we need to advance now. + /// + + ret = sys.bf_vps_op_advance_ip(vpsid); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - The promote ABI will load the microkernel by + /// replacing the CPU's state withthe VP state + /// associated with the provided VPSID. If all + /// goes well, bf_vps_op_promote will not return, + /// and the system will continue executing with the + /// hypervisor turned off. + /// + + return sys.bf_vps_op_promote(vpsid); + } + + case loader::CPUID_COMMAND_ECX_REPORT_ON.get(): { + + /// NOTE: + /// - Report that the root OS is now in a VM for this + /// specific PP. Note that you can do whatever you + /// want here, this is just the default behavior. + /// + + bsl::debug() << bsl::rst << "root OS had been" // -- + << bsl::grn << " demoted " // -- + << bsl::rst << "to vm " // -- + << bsl::cyn << bsl::hex(sys.bf_tls_vmid()) // -- + << bsl::rst << " on pp " // -- + << bsl::cyn << bsl::hex(sys.bf_tls_ppid()) // -- + << bsl::rst << bsl::endl; // -- + + break; + } + + case loader::CPUID_COMMAND_ECX_REPORT_OFF.get(): { + + /// NOTE: + /// - There is nothing to do here as we report off + /// right before promotion takes place. Extensions + /// can use this as a means to perform actions if + /// needed right before the loader sends the stop + /// command. Just note that this command does not + /// report success/failure. + /// + + break; + } + + default: { + bsl::error() << "unsupported cpuid command " // -- + << bsl::hex(rcx) // -- + << bsl::endl // -- + << bsl::here(); // -- + + break; + } + } + + /// NOTE: + /// - Complete this command by advancing RIP and running + /// the currently loaded VM, VP and VPS. + /// + + return sys.bf_vps_op_advance_ip_and_run_current(); + } + + /// NOTE: + /// - If we got this far, this is a normal CPUID, which means we + /// simply need to emulate its execution by calling CPUID and + /// returning the results. + /// + + intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx); + + /// NOTE: + /// - Write the results of CPUID to the VP's registers. Note that + /// the above CPUID intrinsic takes in the full 64bit registers + /// but only touches the lower half of each register, which makes + /// sure that we are emulating CPUID properly. + /// + + sys.bf_tls_set_rax(rax); + sys.bf_tls_set_rbx(rbx); + sys.bf_tls_set_rcx(rcx); + sys.bf_tls_set_rdx(rdx); + + /// NOTE: + /// - Complete the emulation of CPUID by advancing RIP and running + /// the currently loaded VM, VP and VPS. + /// + + return sys.bf_vps_op_advance_ip_and_run_current(); + } + + /// + /// @brief Dispatches the VMExit. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint64 const &exit_reason) noexcept -> bsl::errc_type + { + /// NOTE: + /// - Define the different VMExits that this dispatcher will + /// support. At a minimum, we need to handle CPUID, and NMIs + /// on Intel (as there is no way to disable NMIs on Intel). + /// + + constexpr auto exit_reason_nmi{0x0_u64}; + constexpr auto exit_reason_nmi_window{0x8_u64}; + constexpr auto exit_reason_cpuid{0xA_u64}; + + /// NOTE: + /// - Dispatch and handle each VMExit. + /// + + switch (exit_reason.get()) { + case exit_reason_nmi.get(): { + return handle_nmi(gs, tls, sys, intrinsic, vp_pool, vps_pool, vpsid); + } + + case exit_reason_nmi_window.get(): { + return handle_nmi_window(gs, tls, sys, intrinsic, vp_pool, vps_pool, vpsid); + } + + case exit_reason_cpuid.get(): { + return handle_cpuid(gs, tls, sys, intrinsic, vp_pool, vps_pool, vpsid); + } + + default: { + break; + } + } + + /// NOTE: + /// - If we got this far, it means that we were given a VMExit + /// that we do not handle. + /// + + bsl::error() << "unsupported vmexit " // -- + << bsl::hex(exit_reason) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + }; +} + +#endif diff --git a/example/default/src/x64/intel/vps_t.hpp b/example/default/src/x64/intel/vps_t.hpp new file mode 100644 index 00000000..570f4f4a --- /dev/null +++ b/example/default/src/x64/intel/vps_t.hpp @@ -0,0 +1,500 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VPS_T_HPP +#define VPS_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace example +{ + /// + /// @brief Returns the masked version of the VMCS control fields + /// + /// + /// @param val the value of the control fields read from the MSRs + /// @return The masked version of the control fields. + /// + [[nodiscard]] constexpr auto + ctls_mask(bsl::safe_uint64 const &val) noexcept -> bsl::safe_uint32 + { + constexpr auto mask{0x00000000FFFFFFFF_u64}; + constexpr auto shift{32_u64}; + return bsl::to_u32_unsafe((val & mask) & (val >> shift)); + }; + + /// @class example::vps_t + /// + /// + /// @brief Defines the extension's notion of a VPS + /// + class vps_t final + { + /// @brief stores the ID associated with this vps_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + /// @brief stores the ID of the VP this vps_t is assigned to + bsl::safe_uint16 m_assigned_vpid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vps_t is assigned to + bsl::safe_uint16 m_assigned_ppid{syscall::BF_INVALID_ID}; + + public: + /// + /// @brief Initializes this vps_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param i the ID for this vps_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// not already initialized ourselves. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(m_id)) { + bsl::error() << "vps_t already initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following are some pedantic checks on the input. In + /// larger extensions, this is useful as it helps to weed + /// out hard to find bugs. In a small example like this, it + /// is completely overkill, but is added for completeness. + /// - We check to to make sure that we were given a valid ID, + /// meaning the safe integral is not storing an error, and we + /// also check to make sure the ID itself is not the reserved + /// syscall::BF_INVALID_ID as that is also not allowed. + /// + + if (bsl::unlikely_assert(!i)) { + bsl::error() << "invalid id\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == i)) { + bsl::error() << "id " // -- + << bsl::hex(i) // -- + << " is invalid and cannot be used for initialization" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + /// NOTE: + /// - Finally, store the ID assigned to this vps_t and report + /// success. + /// + + m_id = i; + return bsl::errc_success; + } + + /// + /// @brief Release the vps_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + /// NOTE: + /// - Release functions are usually only needed in the event of + /// an error, or during unit testing. + /// + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vpid = syscall::BF_INVALID_ID; + m_id = bsl::safe_uint16::failure(); + } + + /// + /// @brief Allocates a vps_t and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vpid the ID of the VP to assign the vps_t to + /// @param ppid the ID of the PP to assign the vps_t to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(intrinsic); + + bsl::errc_type ret{}; + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// been initialized by the vp_pool_t. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following is a pedantic check to make sure we have + /// not already allocated this vps_t. In larger extensions, + /// this is useful as it helps to weed out hard to find bugs. + /// In a small example like this, it is completely overkill, + /// but is added for completeness. + /// + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is already allocated and cannot be created" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + /// NOTE: + /// - The following are some pedantic checks on the input. In + /// larger extensions, this is useful as it helps to weed + /// out hard to find bugs. In a small example like this, it + /// is completely overkill, but is added for completeness. + /// - We check to to make sure that we were given a valid ID, + /// meaning the safe integral is not storing an error, and we + /// also check to make sure the ID itself is not the reserved + /// syscall::BF_INVALID_ID as that is also not allowed. + /// + + if (bsl::unlikely_assert(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == vpid)) { + bsl::error() << "vm " // -- + << bsl::hex(vpid) // -- + << " is invalid and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == ppid)) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is invalid and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_invalid_argument; + } + + /// NOTE: + /// - Initialize the VPS as a root VPS. When the microkernel was + /// started, the loader saved the state of the root VP. This + /// syscall tells the microkernel to load the VPS with this saved + /// state so that when we run the VP, it will contain the state + /// just before the microkernel was started. + /// - In other words, this is what allows the microkernel to return + /// back to the loader once the hypervisor is running. + /// - You only want to run this on root VPs. VPs that are being + /// created for guest VPs should not use this, as it would give + /// the guest VP the state associated with the root VP. Also + /// note that once the root VP has executed, this ABI is no + /// longer useful as the state stored in the microkernel would be + /// out-dated. For root VPs, that ID of the PP should always be + /// the same as the IP of the VP, so we added this check for + /// completeness just in case cut/paste is used here. + /// + + if (ppid == m_id) { + ret = sys.bf_vps_op_init_as_root(m_id); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + else { + + /// NOTE: + /// - The call to bsl::touch is only needed if you plan to + /// enforce MC/DC unit testing. Feel free to remove this if + /// you have no plans to support MC/DC unit testing. + /// + + bsl::touch(); + } + + /// NOTE: + /// - Set up VPID + /// + + constexpr auto vmcs_vpid_idx{0x0000_u64}; + constexpr auto vmcs_vpid_val{0x1_u16}; + + ret = sys.bf_vps_op_write16(m_id, vmcs_vpid_idx, vmcs_vpid_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Set up the VMCS link pointer + /// + + constexpr auto vmcs_link_ptr_idx{0x2800_u64}; + constexpr auto vmcs_link_ptr_val{0xFFFFFFFFFFFFFFFF_u64}; + + ret = sys.bf_vps_op_write64(m_id, vmcs_link_ptr_idx, vmcs_link_ptr_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Set up the VMCS pin based, proc based, exit and entry controls + /// - We turn on MSR bitmaps so that we do not trap on MSR reads and + /// writes. If you do not configure this, or you use the bitmap + /// to trap to specific MSR accesses, make sure you keep the VMCS + /// in sync with your MSR mods. Any MSR that is in the VMCS also + /// needs to be written to the VMCS, otherwise, VMEntry/VMExit will + /// replace any values you write. + /// - We also turn on secondary controls so that we can turn on VPID, + /// and turn on instructions that the OS is relying on, like + /// RDTSCP. Failure to do this will cause the invalid opcodes to + /// occur. + /// - The lambda below performs the MSR conversion of the CTLS + /// registers to determine the bits that must always be set to 1, + /// and the bits that must always be set to 0. This allows us to + /// turn on as much as possible, letting the MSRs decide what is + /// allowed and what is not. + /// - Also note that we do not attempt to detect support for the + /// secondary controls. This is because the loader ensures that + /// this support is present as it is a minimum requirement for the + /// project. + /// + + constexpr auto vmcs_pinbased_ctls_idx{0x4000_u64}; + constexpr auto vmcs_procbased_ctls_idx{0x4002_u64}; + constexpr auto vmcs_exit_ctls_idx{0x400C_u64}; + constexpr auto vmcs_entry_ctls_idx{0x4012_u64}; + constexpr auto vmcs_procbased_ctls2_idx{0x401E_u64}; + + constexpr auto ia32_vmx_true_pinbased_ctls{0x48D_u32}; + constexpr auto ia32_vmx_true_procbased_ctls{0x48E_u32}; + constexpr auto ia32_vmx_true_exit_ctls{0x48F_u32}; + constexpr auto ia32_vmx_true_entry_ctls{0x490_u32}; + constexpr auto ia32_vmx_true_procbased_ctls2{0x48B_u32}; + + bsl::safe_uintmax ctls{}; + + /// NOTE: + /// - Configure the pin based controls + /// + + ctls = sys.bf_intrinsic_op_rdmsr(ia32_vmx_true_pinbased_ctls); + if (bsl::unlikely_assert(!ctls)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = sys.bf_vps_op_write32(m_id, vmcs_pinbased_ctls_idx, ctls_mask(ctls)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Configure the proc based controls + /// + + constexpr auto enable_msr_bitmaps{0x10000000_u64}; + constexpr auto enable_procbased_ctls2{0x80000000_u64}; + + ctls = sys.bf_intrinsic_op_rdmsr(ia32_vmx_true_procbased_ctls); + if (bsl::unlikely_assert(!ctls)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ctls |= enable_msr_bitmaps; + ctls |= enable_procbased_ctls2; + + ret = sys.bf_vps_op_write32(m_id, vmcs_procbased_ctls_idx, ctls_mask(ctls)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Configure the exit controls + /// + + ctls = sys.bf_intrinsic_op_rdmsr(ia32_vmx_true_exit_ctls); + if (bsl::unlikely_assert(!ctls)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = sys.bf_vps_op_write32(m_id, vmcs_exit_ctls_idx, ctls_mask(ctls)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Configure the entry controls + /// + + ctls = sys.bf_intrinsic_op_rdmsr(ia32_vmx_true_entry_ctls); + if (bsl::unlikely_assert(!ctls)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = sys.bf_vps_op_write32(m_id, vmcs_entry_ctls_idx, ctls_mask(ctls)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Configure the secondary proc controls. + /// + + constexpr auto enable_vpid{0x00000020_u64}; + constexpr auto enable_rdtscp{0x00000008_u64}; + constexpr auto enable_invpcid{0x00001000_u64}; + constexpr auto enable_xsave{0x00100000_u64}; + constexpr auto enable_uwait{0x04000000_u64}; + + ctls = sys.bf_intrinsic_op_rdmsr(ia32_vmx_true_procbased_ctls2); + if (bsl::unlikely_assert(!ctls)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ctls |= enable_vpid; + ctls |= enable_rdtscp; + ctls |= enable_invpcid; + ctls |= enable_xsave; + ctls |= enable_uwait; + + ret = sys.bf_vps_op_write32(m_id, vmcs_procbased_ctls2_idx, ctls_mask(ctls)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Configure the MSR bitmaps. This ensures that we do not trap + /// on MSR reads and writes. Also note that in most applications, + /// you only need one of these, regardless of the total number of + /// CPUs you are running on. + /// + + constexpr auto vmcs_msr_bitmaps{0x2004_u64}; + + ret = sys.bf_vps_op_write64(m_id, vmcs_msr_bitmaps, gs.msr_bitmap_phys); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Finally, store the IDs of the VP and PP that this vps_t is + /// assigned to and reprot success. + /// + + m_assigned_vpid = vpid; + m_assigned_ppid = ppid; + + return bsl::errc_success; + } + }; +} + +#endif diff --git a/example/default/src/x64/intrinsic_cpuid_impl.S b/example/default/src/x64/intrinsic_cpuid_impl.S new file mode 100644 index 00000000..5c94439d --- /dev/null +++ b/example/default/src/x64/intrinsic_cpuid_impl.S @@ -0,0 +1,52 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl intrinsic_cpuid_impl + .type intrinsic_cpuid_impl, @function +intrinsic_cpuid_impl: + push rbx + + mov r10, rdx + mov r11, rcx + + mov eax, [rsi] + mov ebx, [r10] + mov ecx, [r11] + mov edx, [r8] + cpuid + mov [rsi], eax + mov [r10], ebx + mov [r11], ecx + mov [r8], edx + + pop rbx + ret + int 3 + + .size intrinsic_cpuid_impl, .-intrinsic_cpuid_impl diff --git a/example/default/src/x64/intrinsic_cpuid_impl.hpp b/example/default/src/x64/intrinsic_cpuid_impl.hpp new file mode 100644 index 00000000..2d2c30db --- /dev/null +++ b/example/default/src/x64/intrinsic_cpuid_impl.hpp @@ -0,0 +1,53 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INTRINSIC_IMPL_PROTOTYPES_HPP +#define INTRINSIC_IMPL_PROTOTYPES_HPP + +#include + +#include + +namespace example +{ + /// + /// @brief Executes the CPUID instruction given the provided EAX and ECX + /// and returns the results + /// + /// + /// @param gs ignored + /// @param rax the index used by CPUID, returns resulting rax + /// @param rbx returns resulting rbx + /// @param rcx the subindex used by CPUID, returns the resulting rcx + /// @param rdx returns resulting rdx + /// + extern "C" void intrinsic_cpuid_impl( + gs_t *const gs, + bsl::uint64 *const rax, + bsl::uint64 *const rbx, + bsl::uint64 *const rcx, + bsl::uint64 *const rdx) noexcept; +} + +#endif diff --git a/example/default/test/.clang-tidy b/example/default/test/.clang-tidy new file mode 100644 index 00000000..623b66c9 --- /dev/null +++ b/example/default/test/.clang-tidy @@ -0,0 +1,56 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +Checks: + ' + -*, + bsl-*, + -bsl-template-generic-param, + -bsl-literals-user-defined, + -bsl-lambda-implicit-capture, + bugprone-*, + -bugprone-branch-clone, + cert-*, + -cert-dcl21-cpp, + -cert-oop54-cpp, + clang-analyzer-*, + -clang-analyzer-core.CallAndMessage, + cppcoreguidelines-*, + -cppcoreguidelines-avoid-non-const-global-variables, + hicpp-*, + -hicpp-function-size, + misc-*, + -misc-misplaced-const, + -misc-non-private-member-variables-in-classes, + modernize-*, + -modernize-use-default-member-init, + performance-*, + readability-*, + -readability-redundant-member-init, + -readability-avoid-const-params-in-decls, + -readability-static-accessed-through-instance, + -readability-function-size + ' +WarningsAsErrors: '*' +HeaderFilterRegex: '.*' +AnalyzeTemporaryDtors: false +FormatStyle: none +UseColor: true diff --git a/example/default/test/CMakeLists.txt b/example/default/test/CMakeLists.txt new file mode 100644 index 00000000..85c6d581 --- /dev/null +++ b/example/default/test/CMakeLists.txt @@ -0,0 +1,227 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - We include the bf_add_test function from the BSL as it greatly simplifies +# creating unit tests for us. If you do not want to use this, feel free to +# handle unit tests however you wish (or not at all) +# + +include(${bsl_SOURCE_DIR}/cmake/function/bf_add_test.cmake) + +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + +# NOTE: +# - It is really, really important that we do not add any include directories +# from the source folder. Anything that is needed by code from the source +# folder must be mocked. The include folder itself is fine as this should +# only ever include type definitions. Things that should not be in the +# include folder are: +# - Any code that can excute. Anything that can execute must be in the src +# folder and have a set of tests associated with it. +# - C function prototypes. These should also be in the source folder, and +# any code that needs them should get to this code through a C++ class +# wrapper. See the intrinsic_t as an example. C function prototypes are not +# constexpr, so they cannot be called from the rest of the C++ code. +# - Obiviously, any actual source files like .cpp and .S. These should all +# be in the source folder as well. Unit test the assembly files where it +# is possible (like a memcpy/memset). For extensions, most assembly files +# likely can be unit tested as they can only execute userspace specific +# instructions. The microkernel is a different story as it executes system +# instructions which likely need an emulator to properly unit test. +# - In the default example, we include the mock folder for bf_syscall_t and +# it's related headers. This is a generic mock of bf_syscall_t which can be +# used for most unit testing, but if you need soemthing more specific, you +# are free to remove the includes for this and provide your own. The sycall +# library stores bf_syscall_t in the source folder for this reason as the +# include folder contains type defintions and constants that can be used in +# any unit test as they do not change, while the src folder specific logic +# should only be included when you plan to use the actual implementation of +# bf_syscall_t and not a mock. +# + +list(APPEND INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include + ${CMAKE_CURRENT_LIST_DIR}/../mocks +) + +list(APPEND SYSTEM_INCLUDES + ${CMAKE_SOURCE_DIR}/syscall/include/cpp + ${CMAKE_SOURCE_DIR}/syscall/mocks/cpp + ${CMAKE_SOURCE_DIR}/loader/include/interface/cpp +) + +list(APPEND COMMON_INCLUDES + ${INCLUDES} +) + +list(APPEND COMMON_SYSTEM_INCLUDES + ${SYSTEM_INCLUDES} +) + +list(APPEND X64_INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include/x64 + ${CMAKE_CURRENT_LIST_DIR}/../mocks/x64 + ${INCLUDES} +) + +list(APPEND X64_SYSTEM_INCLUDES + ${CMAKE_SOURCE_DIR}/syscall/include/cpp/x64 + ${CMAKE_SOURCE_DIR}/syscall/mocks/cpp/x64 + ${CMAKE_SOURCE_DIR}/loader/include/interface/cpp/x64 + ${SYSTEM_INCLUDES} +) + +list(APPEND AMD_INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/amd + ${CMAKE_CURRENT_LIST_DIR}/../mocks/x64/amd + ${X64_INCLUDES} +) + +list(APPEND AMD_SYSTEM_INCLUDES + ${CMAKE_SOURCE_DIR}/syscall/include/cpp/x64/amd + ${CMAKE_SOURCE_DIR}/syscall/mocks/cpp/x64/amd + ${CMAKE_SOURCE_DIR}/loader/include/interface/cpp/x64/amd + ${X64_SYSTEM_INCLUDES} +) + +list(APPEND INTEL_INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intel + ${CMAKE_CURRENT_LIST_DIR}/../mocks/x64/intel + ${X64_INCLUDES} +) + +list(APPEND INTEL_SYSTEM_INCLUDES + ${CMAKE_SOURCE_DIR}/syscall/include/cpp/x64/intel + ${CMAKE_SOURCE_DIR}/syscall/mocks/cpp/x64/intel + ${CMAKE_SOURCE_DIR}/loader/include/interface/cpp/x64/intel + ${X64_SYSTEM_INCLUDES} +) + +list(APPEND AARCH64_INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64 + ${CMAKE_CURRENT_LIST_DIR}/../mocks/arm/aarch64 + ${INCLUDES} +) + +list(APPEND AARCH64_SYSTEM_INCLUDES + ${CMAKE_SOURCE_DIR}/syscall/include/cpp/arm/aarch64 + ${CMAKE_SOURCE_DIR}/syscall/mocks/cpp/arm/aarch64 + ${CMAKE_SOURCE_DIR}/loader/include/interface/cpp/arm/aarch64 + ${SYSTEM_INCLUDES} +) + +# ------------------------------------------------------------------------------ +# Definitions +# ------------------------------------------------------------------------------ + +# NOTE: +# - Any defintions that the extension uses should be defined here. You can +# also define them on a per unit test basis if needed. Bareflank makes the +# definitions available to the extension when it is compiling the actual +# code, but it does not make them available to any tests, so they must be +# manually defined here, or where you define the unit test itself. +# - DO NOT define these in the unit test code. Either define them here, or +# to define them on a per unit test bases, add them to a test specific +# CMake variable that is passed to bf_add_test. If a unit test needs these +# defined different for each test, make a different unit test for each one. +# +# - See the individual CMakeLists.txt for each test for more information. +# + +list(APPEND DEFINES + HYPERVISOR_PAGE_SIZE=0x1000_umax + HYPERVISOR_MAX_VPS=2_umax + HYPERVISOR_MAX_VPSS=2_umax + HYPERVISOR_EXT_DIRECT_MAP_ADDR=0x0000600000000000_umax +) + +list(APPEND COMMON_DEFINES + ${DEFINES} +) + +list(APPEND X64_DEFINES + ${DEFINES} +) + +list(APPEND AMD_DEFINES + ${X64_DEFINES} +) + +list(APPEND INTEL_DEFINES + ${X64_DEFINES} +) + +list(APPEND AARCH64_DEFINES + ${DEFINES} +) + +# ------------------------------------------------------------------------------ +# Tests +# ------------------------------------------------------------------------------ + +# NOTE: +# - The following is just a template that you can use as a starting point for +# each test. Remove it from your extension as needed. +# + +add_subdirectory(template) + +# NOTE: +# - Add the directories for each unit test here. Note that you should add all +# archiectures here. Unit tests mock all dependencies, including the arch +# specific dependencies, so all of the arch specific unit tests can compile +# and run on any other arch. This ensures, for example, that your ARM logic +# is unit tested during CI which might be running on an Intel based system. +# + +add_subdirectory(mocks/bootstrap_t) +add_subdirectory(mocks/fail_t) +add_subdirectory(mocks/intrinsic_t) +add_subdirectory(mocks/vmexit_t) +add_subdirectory(mocks/vp_pool_t) +add_subdirectory(mocks/vp_t) +add_subdirectory(mocks/vps_pool_t) +add_subdirectory(mocks/vps_t) +add_subdirectory(mocks/x64/intrinsic_cpuid_impl) +add_subdirectory(mocks/x64/amd/intrinsic_t) +add_subdirectory(mocks/x64/intel/intrinsic_t) + +add_subdirectory(src/bootstrap_t) +add_subdirectory(src/fail_t) +add_subdirectory(src/main) +add_subdirectory(src/vp_pool_t) +add_subdirectory(src/vp_t) +add_subdirectory(src/vps_pool_t) +add_subdirectory(src/x64/amd/intrinsic_t) +add_subdirectory(src/x64/amd/vmexit_t) +add_subdirectory(src/x64/amd/vps_t) +add_subdirectory(src/x64/intel/intrinsic_t) +add_subdirectory(src/x64/intel/vmexit_t) +add_subdirectory(src/x64/intel/vps_t) + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + add_subdirectory(src/x64/intrinsic_cpuid_impl) + endif() +endif() diff --git a/example/default/test/mocks/bootstrap_t/CMakeLists.txt b/example/default/test/mocks/bootstrap_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/mocks/bootstrap_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/mocks/bootstrap_t/behavior.cpp b/example/default/test/mocks/bootstrap_t/behavior.cpp new file mode 100644 index 00000000..58ee62bf --- /dev/null +++ b/example/default/test/mocks/bootstrap_t/behavior.cpp @@ -0,0 +1,146 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/bootstrap_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bootstrap_t bootstrap{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + bootstrap.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !bootstrap.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bootstrap_t bootstrap{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(bootstrap.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + }; + }; + }; + + bsl::ut_scenario{"release executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bootstrap_t bootstrap{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bootstrap.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bootstrap_t bootstrap{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + bootstrap.set_dispatch(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !bootstrap.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bootstrap_t bootstrap{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + bootstrap.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {})); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/mocks/bootstrap_t/requirements.cpp b/example/default/test/mocks/bootstrap_t/requirements.cpp new file mode 100644 index 00000000..360b50e5 --- /dev/null +++ b/example/default/test/mocks/bootstrap_t/requirements.cpp @@ -0,0 +1,119 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/bootstrap_t.hpp" + +#include +#include + +namespace +{ + constinit example::bootstrap_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::bootstrap_t m_boostrap{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - bootstrap_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + + bsl::discard(example::bootstrap_t{}); + bsl::discard(m_boostrap.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + m_boostrap.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + bsl::discard(m_boostrap.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::bootstrap_t boostrap{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::bootstrap_t{})); + static_assert( + noexcept(boostrap.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert( + noexcept(boostrap.release(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert( + noexcept(boostrap.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/mocks/fail_t/CMakeLists.txt b/example/default/test/mocks/fail_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/mocks/fail_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/mocks/fail_t/behavior.cpp b/example/default/test/mocks/fail_t/behavior.cpp new file mode 100644 index 00000000..795d42b3 --- /dev/null +++ b/example/default/test/mocks/fail_t/behavior.cpp @@ -0,0 +1,145 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/fail_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fail_t fail{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + fail.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!fail.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fail_t fail{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(fail.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + }; + }; + }; + + bsl::ut_scenario{"release executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fail_t fail{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + fail.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fail_t fail{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + fail.set_dispatch(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !fail.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fail_t fail{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + fail.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {})); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/mocks/fail_t/requirements.cpp b/example/default/test/mocks/fail_t/requirements.cpp new file mode 100644 index 00000000..de0d5269 --- /dev/null +++ b/example/default/test/mocks/fail_t/requirements.cpp @@ -0,0 +1,118 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/fail_t.hpp" + +#include +#include + +namespace +{ + constinit example::fail_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::fail_t m_fail{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - fail_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + + bsl::discard(example::fail_t{}); + bsl::discard(m_fail.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + m_fail.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + bsl::discard(m_fail.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::fail_t fail{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::fail_t{})); + static_assert( + noexcept(fail.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert(noexcept(fail.release(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert( + noexcept(fail.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/mocks/intrinsic_t/CMakeLists.txt b/example/default/test/mocks/intrinsic_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/mocks/intrinsic_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/mocks/intrinsic_t/behavior.cpp b/example/default/test/mocks/intrinsic_t/behavior.cpp new file mode 100644 index 00000000..512091f6 --- /dev/null +++ b/example/default/test/mocks/intrinsic_t/behavior.cpp @@ -0,0 +1,98 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/intrinsic_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + intrinsic.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!intrinsic.initialize(gs, tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(intrinsic.initialize(gs, tls)); + }; + }; + }; + + bsl::ut_scenario{"release executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_then{} = [&]() noexcept { + intrinsic.release(gs, tls); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/mocks/intrinsic_t/requirements.cpp b/example/default/test/mocks/intrinsic_t/requirements.cpp new file mode 100644 index 00000000..a02b5659 --- /dev/null +++ b/example/default/test/mocks/intrinsic_t/requirements.cpp @@ -0,0 +1,106 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/intrinsic_t.hpp" + +#include +#include + +namespace +{ + constinit example::intrinsic_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::intrinsic_t m_intrinsic{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - intrinsic_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + + bsl::discard(example::intrinsic_t{}); + bsl::discard(m_intrinsic.initialize(gs, tls)); + m_intrinsic.release(gs, tls); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::intrinsic_t intrinsic{}; + example::gs_t gs{}; + example::tls_t tls{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::intrinsic_t{})); + static_assert(noexcept(intrinsic.initialize(gs, tls))); + static_assert(noexcept(intrinsic.release(gs, tls))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/mocks/vmexit_t/CMakeLists.txt b/example/default/test/mocks/vmexit_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/mocks/vmexit_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/mocks/vmexit_t/behavior.cpp b/example/default/test/mocks/vmexit_t/behavior.cpp new file mode 100644 index 00000000..04c26ab0 --- /dev/null +++ b/example/default/test/mocks/vmexit_t/behavior.cpp @@ -0,0 +1,146 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/vmexit_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + vmexit.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + }; + }; + }; + + bsl::ut_scenario{"release executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + vmexit.set_dispatch(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vmexit.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + vmexit.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {})); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/mocks/vmexit_t/requirements.cpp b/example/default/test/mocks/vmexit_t/requirements.cpp new file mode 100644 index 00000000..b4404442 --- /dev/null +++ b/example/default/test/mocks/vmexit_t/requirements.cpp @@ -0,0 +1,118 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/vmexit_t.hpp" + +#include +#include + +namespace +{ + constinit example::vmexit_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vmexit_t m_vmexit{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vmexit_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + + bsl::discard(example::vmexit_t{}); + bsl::discard(m_vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + m_vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + bsl::discard(m_vmexit.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vmexit_t vmexit{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vmexit_t{})); + static_assert( + noexcept(vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert(noexcept(vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert( + noexcept(vmexit.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/mocks/vp_pool_t/CMakeLists.txt b/example/default/test/mocks/vp_pool_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/mocks/vp_pool_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/mocks/vp_pool_t/behavior.cpp b/example/default/test/mocks/vp_pool_t/behavior.cpp new file mode 100644 index 00000000..329a858f --- /dev/null +++ b/example/default/test/mocks/vp_pool_t/behavior.cpp @@ -0,0 +1,133 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/vp_pool_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + vp_pool.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vp_pool.initialize(gs, tls, sys, intrinsic)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vp_pool.initialize(gs, tls, sys, intrinsic)); + }; + }; + }; + + bsl::ut_scenario{"release executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + vp_pool.release(gs, tls, sys, intrinsic); + }; + }; + }; + + bsl::ut_scenario{"allocate fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + vp_pool.set_allocate(bsl::safe_uint16::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vp_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vp_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/mocks/vp_pool_t/requirements.cpp b/example/default/test/mocks/vp_pool_t/requirements.cpp new file mode 100644 index 00000000..d5f93095 --- /dev/null +++ b/example/default/test/mocks/vp_pool_t/requirements.cpp @@ -0,0 +1,112 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/vp_pool_t.hpp" + +#include +#include + +namespace +{ + constinit example::vp_pool_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vp_pool_t m_vp_pool{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vp_pool_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + + bsl::discard(example::vp_pool_t{}); + bsl::discard(m_vp_pool.initialize(gs, tls, sys, intrinsic)); + m_vp_pool.release(gs, tls, sys, intrinsic); + bsl::discard(m_vp_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vp_pool_t vp_pool{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vp_pool_t{})); + static_assert(noexcept(vp_pool.initialize(gs, tls, sys, intrinsic))); + static_assert(noexcept(vp_pool.release(gs, tls, sys, intrinsic))); + static_assert(noexcept(vp_pool.allocate(gs, tls, sys, intrinsic, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/mocks/vp_t/CMakeLists.txt b/example/default/test/mocks/vp_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/mocks/vp_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/mocks/vp_t/behavior.cpp b/example/default/test/mocks/vp_t/behavior.cpp new file mode 100644 index 00000000..7f665b9e --- /dev/null +++ b/example/default/test/mocks/vp_t/behavior.cpp @@ -0,0 +1,133 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/vp_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vp.initialize(gs, tls, sys, intrinsic, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vp.initialize(gs, tls, sys, intrinsic, {})); + }; + }; + }; + + bsl::ut_scenario{"release executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + vp.release(gs, tls, sys, intrinsic); + }; + }; + }; + + bsl::ut_scenario{"allocate fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vp.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vp.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/mocks/vp_t/requirements.cpp b/example/default/test/mocks/vp_t/requirements.cpp new file mode 100644 index 00000000..2599cceb --- /dev/null +++ b/example/default/test/mocks/vp_t/requirements.cpp @@ -0,0 +1,112 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/vp_t.hpp" + +#include +#include + +namespace +{ + constinit example::vp_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vp_t m_vp{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vp_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + + bsl::discard(example::vp_t{}); + bsl::discard(m_vp.initialize(gs, tls, sys, intrinsic, {})); + m_vp.release(gs, tls, sys, intrinsic); + bsl::discard(m_vp.allocate(gs, tls, sys, intrinsic, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vp_t vp{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vp_t{})); + static_assert(noexcept(vp.initialize(gs, tls, sys, intrinsic, {}))); + static_assert(noexcept(vp.release(gs, tls, sys, intrinsic))); + static_assert(noexcept(vp.allocate(gs, tls, sys, intrinsic, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/mocks/vps_pool_t/CMakeLists.txt b/example/default/test/mocks/vps_pool_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/mocks/vps_pool_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/mocks/vps_pool_t/behavior.cpp b/example/default/test/mocks/vps_pool_t/behavior.cpp new file mode 100644 index 00000000..8d483ffe --- /dev/null +++ b/example/default/test/mocks/vps_pool_t/behavior.cpp @@ -0,0 +1,133 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/vps_pool_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + vps_pool.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps_pool.initialize(gs, tls, sys, intrinsic)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vps_pool.initialize(gs, tls, sys, intrinsic)); + }; + }; + }; + + bsl::ut_scenario{"release executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + vps_pool.release(gs, tls, sys, intrinsic); + }; + }; + }; + + bsl::ut_scenario{"allocate fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + vps_pool.set_allocate(bsl::safe_uint16::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vps_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/mocks/vps_pool_t/requirements.cpp b/example/default/test/mocks/vps_pool_t/requirements.cpp new file mode 100644 index 00000000..358039b4 --- /dev/null +++ b/example/default/test/mocks/vps_pool_t/requirements.cpp @@ -0,0 +1,112 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/vps_pool_t.hpp" + +#include +#include + +namespace +{ + constinit example::vps_pool_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vps_pool_t m_vps_pool{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vps_pool_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + + bsl::discard(example::vps_pool_t{}); + bsl::discard(m_vps_pool.initialize(gs, tls, sys, intrinsic)); + m_vps_pool.release(gs, tls, sys, intrinsic); + bsl::discard(m_vps_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vps_pool_t vps_pool{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vps_pool_t{})); + static_assert(noexcept(vps_pool.initialize(gs, tls, sys, intrinsic))); + static_assert(noexcept(vps_pool.release(gs, tls, sys, intrinsic))); + static_assert(noexcept(vps_pool.allocate(gs, tls, sys, intrinsic, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/mocks/vps_t/CMakeLists.txt b/example/default/test/mocks/vps_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/mocks/vps_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/mocks/vps_t/behavior.cpp b/example/default/test/mocks/vps_t/behavior.cpp new file mode 100644 index 00000000..909a1311 --- /dev/null +++ b/example/default/test/mocks/vps_t/behavior.cpp @@ -0,0 +1,133 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/vps_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.initialize(gs, tls, sys, intrinsic, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vps.initialize(gs, tls, sys, intrinsic, {})); + }; + }; + }; + + bsl::ut_scenario{"release executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + vps.release(gs, tls, sys, intrinsic); + }; + }; + }; + + bsl::ut_scenario{"allocate fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/mocks/vps_t/requirements.cpp b/example/default/test/mocks/vps_t/requirements.cpp new file mode 100644 index 00000000..d194a521 --- /dev/null +++ b/example/default/test/mocks/vps_t/requirements.cpp @@ -0,0 +1,112 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../mocks/vps_t.hpp" + +#include +#include + +namespace +{ + constinit example::vps_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vps_t m_vps{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vps_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + + bsl::discard(example::vps_t{}); + bsl::discard(m_vps.initialize(gs, tls, sys, intrinsic, {})); + m_vps.release(gs, tls, sys, intrinsic); + bsl::discard(m_vps.allocate(gs, tls, sys, intrinsic, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vps_t vps{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vps_t{})); + static_assert(noexcept(vps.initialize(gs, tls, sys, intrinsic, {}))); + static_assert(noexcept(vps.release(gs, tls, sys, intrinsic))); + static_assert(noexcept(vps.allocate(gs, tls, sys, intrinsic, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/mocks/x64/amd/intrinsic_t/CMakeLists.txt b/example/default/test/mocks/x64/amd/intrinsic_t/CMakeLists.txt new file mode 100644 index 00000000..22dd32fb --- /dev/null +++ b/example/default/test/mocks/x64/amd/intrinsic_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) +bf_add_test(behavior INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) diff --git a/example/default/test/mocks/x64/amd/intrinsic_t/behavior.cpp b/example/default/test/mocks/x64/amd/intrinsic_t/behavior.cpp new file mode 100644 index 00000000..d9c806c7 --- /dev/null +++ b/example/default/test/mocks/x64/amd/intrinsic_t/behavior.cpp @@ -0,0 +1,125 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../mocks/x64/amd/intrinsic_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + intrinsic.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!intrinsic.initialize(gs, tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(intrinsic.initialize(gs, tls)); + }; + }; + }; + + bsl::ut_scenario{"release executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_then{} = [&]() noexcept { + intrinsic.release(gs, tls); + }; + }; + }; + + bsl::ut_scenario{"cpuid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + constexpr auto expected_result{0x1234567800000042_u64}; + constexpr auto eax{0x42_u32}; + constexpr auto ebx{0x42_u32}; + constexpr auto ecx{0x42_u32}; + constexpr auto edx{0x42_u32}; + auto rax{0x1234567800000000_u64}; + auto rbx{0x1234567800000000_u64}; + auto rcx{0x1234567800000000_u64}; + auto rdx{0x1234567800000000_u64}; + bsl::ut_when{} = [&]() noexcept { + intrinsic.set_cpuid(eax, ebx, ecx, edx); + intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(rax == expected_result); + bsl::ut_check(rbx == expected_result); + bsl::ut_check(rcx == expected_result); + bsl::ut_check(rdx == expected_result); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/mocks/x64/amd/intrinsic_t/requirements.cpp b/example/default/test/mocks/x64/amd/intrinsic_t/requirements.cpp new file mode 100644 index 00000000..38c05c9a --- /dev/null +++ b/example/default/test/mocks/x64/amd/intrinsic_t/requirements.cpp @@ -0,0 +1,116 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../mocks/x64/amd/intrinsic_t.hpp" + +#include +#include + +namespace +{ + constinit example::intrinsic_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::intrinsic_t m_intrinsic{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - intrinsic_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + + bsl::discard(example::intrinsic_t{}); + bsl::discard(m_intrinsic.initialize(gs, tls)); + m_intrinsic.release(gs, tls); + m_intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::intrinsic_t intrinsic{}; + example::gs_t gs{}; + example::tls_t tls{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::intrinsic_t{})); + static_assert(noexcept(intrinsic.initialize(gs, tls))); + static_assert(noexcept(intrinsic.release(gs, tls))); + static_assert(noexcept(intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/mocks/x64/intel/intrinsic_t/CMakeLists.txt b/example/default/test/mocks/x64/intel/intrinsic_t/CMakeLists.txt new file mode 100644 index 00000000..bdb65470 --- /dev/null +++ b/example/default/test/mocks/x64/intel/intrinsic_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) +bf_add_test(behavior INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) diff --git a/example/default/test/mocks/x64/intel/intrinsic_t/behavior.cpp b/example/default/test/mocks/x64/intel/intrinsic_t/behavior.cpp new file mode 100644 index 00000000..176a03d0 --- /dev/null +++ b/example/default/test/mocks/x64/intel/intrinsic_t/behavior.cpp @@ -0,0 +1,125 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../mocks/x64/intel/intrinsic_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + intrinsic.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!intrinsic.initialize(gs, tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(intrinsic.initialize(gs, tls)); + }; + }; + }; + + bsl::ut_scenario{"release executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_then{} = [&]() noexcept { + intrinsic.release(gs, tls); + }; + }; + }; + + bsl::ut_scenario{"cpuid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + constexpr auto expected_result{0x1234567800000042_u64}; + constexpr auto eax{0x42_u32}; + constexpr auto ebx{0x42_u32}; + constexpr auto ecx{0x42_u32}; + constexpr auto edx{0x42_u32}; + auto rax{0x1234567800000000_u64}; + auto rbx{0x1234567800000000_u64}; + auto rcx{0x1234567800000000_u64}; + auto rdx{0x1234567800000000_u64}; + bsl::ut_when{} = [&]() noexcept { + intrinsic.set_cpuid(eax, ebx, ecx, edx); + intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(rax == expected_result); + bsl::ut_check(rbx == expected_result); + bsl::ut_check(rcx == expected_result); + bsl::ut_check(rdx == expected_result); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/mocks/x64/intel/intrinsic_t/requirements.cpp b/example/default/test/mocks/x64/intel/intrinsic_t/requirements.cpp new file mode 100644 index 00000000..50dd1112 --- /dev/null +++ b/example/default/test/mocks/x64/intel/intrinsic_t/requirements.cpp @@ -0,0 +1,116 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../mocks/x64/intel/intrinsic_t.hpp" + +#include +#include + +namespace +{ + constinit example::intrinsic_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::intrinsic_t m_intrinsic{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - intrinsic_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + + bsl::discard(example::intrinsic_t{}); + bsl::discard(m_intrinsic.initialize(gs, tls)); + m_intrinsic.release(gs, tls); + m_intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::intrinsic_t intrinsic{}; + example::gs_t gs{}; + example::tls_t tls{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::intrinsic_t{})); + static_assert(noexcept(intrinsic.initialize(gs, tls))); + static_assert(noexcept(intrinsic.release(gs, tls))); + static_assert(noexcept(intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/mocks/x64/intrinsic_cpuid_impl/CMakeLists.txt b/example/default/test/mocks/x64/intrinsic_cpuid_impl/CMakeLists.txt new file mode 100644 index 00000000..28a8f305 --- /dev/null +++ b/example/default/test/mocks/x64/intrinsic_cpuid_impl/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${X64_INCLUDES} SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} DEFINES ${X64_DEFINES}) +bf_add_test(behavior INCLUDES ${X64_INCLUDES} SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} DEFINES ${X64_DEFINES}) diff --git a/example/default/test/mocks/x64/intrinsic_cpuid_impl/behavior.cpp b/example/default/test/mocks/x64/intrinsic_cpuid_impl/behavior.cpp new file mode 100644 index 00000000..8a73dd1f --- /dev/null +++ b/example/default/test/mocks/x64/intrinsic_cpuid_impl/behavior.cpp @@ -0,0 +1,101 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../mocks/x64/intrinsic_cpuid_impl.hpp" + +#include +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"intrinsic_cpuid_impl invalid inputs doesn't crash"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + gs_t gs{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + bsl::ut_when{} = [&]() noexcept { + intrinsic_cpuid_impl(nullptr, rax.data(), rbx.data(), rcx.data(), rdx.data()); + intrinsic_cpuid_impl(&gs, nullptr, rbx.data(), rcx.data(), rdx.data()); + intrinsic_cpuid_impl(&gs, rax.data(), nullptr, rcx.data(), rdx.data()); + intrinsic_cpuid_impl(&gs, rax.data(), rbx.data(), nullptr, rdx.data()); + intrinsic_cpuid_impl(&gs, rax.data(), rbx.data(), rcx.data(), nullptr); + }; + }; + }; + + bsl::ut_scenario{"intrinsic_cpuid_impl"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + gs_t gs{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + constexpr auto expected_result{42_u64}; + bsl::ut_when{} = [&]() noexcept { + gs.cpuid_val = expected_result; + intrinsic_cpuid_impl(&gs, rax.data(), rbx.data(), rcx.data(), rdx.data()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(rax == expected_result); + bsl::ut_check(rbx == expected_result); + bsl::ut_check(rcx == expected_result); + bsl::ut_check(rdx == expected_result); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/mocks/x64/intrinsic_cpuid_impl/requirements.cpp b/example/default/test/mocks/x64/intrinsic_cpuid_impl/requirements.cpp new file mode 100644 index 00000000..36ffccc1 --- /dev/null +++ b/example/default/test/mocks/x64/intrinsic_cpuid_impl/requirements.cpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../mocks/x64/intrinsic_cpuid_impl.hpp" + +#include +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::intrinsic_cpuid_impl({}, {}, {}, {}, {}))); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/bootstrap_t/CMakeLists.txt b/example/default/test/src/bootstrap_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/src/bootstrap_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/src/bootstrap_t/behavior.cpp b/example/default/test/src/bootstrap_t/behavior.cpp new file mode 100644 index 00000000..a559baef --- /dev/null +++ b/example/default/test/src/bootstrap_t/behavior.cpp @@ -0,0 +1,173 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/bootstrap_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bootstrap_t bootstrap{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(bootstrap.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + }; + }; + }; + + bsl::ut_scenario{"release executes without initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bootstrap_t bootstrap{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bootstrap.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"release executes with initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bootstrap_t bootstrap{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + bootstrap.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + bsl::ut_then{} = [&]() noexcept { + bootstrap.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch vp_pool allocate fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bootstrap_t bootstrap{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + bootstrap.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + vp_pool.set_allocate(bsl::safe_uint16::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !bootstrap.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch vps_pool allocate fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bootstrap_t bootstrap{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + bootstrap.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + vps_pool.set_allocate(bsl::safe_uint16::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !bootstrap.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bootstrap_t bootstrap{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + bootstrap.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + bootstrap.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {})); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/bootstrap_t/requirements.cpp b/example/default/test/src/bootstrap_t/requirements.cpp new file mode 100644 index 00000000..c6448062 --- /dev/null +++ b/example/default/test/src/bootstrap_t/requirements.cpp @@ -0,0 +1,119 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/bootstrap_t.hpp" + +#include +#include + +namespace +{ + constinit example::bootstrap_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::bootstrap_t m_bootstrap{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - bootstrap_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + + bsl::discard(example::bootstrap_t{}); + bsl::discard(m_bootstrap.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + m_bootstrap.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + bsl::discard(m_bootstrap.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::bootstrap_t bootstrap{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::bootstrap_t{})); + static_assert( + noexcept(bootstrap.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert( + noexcept(bootstrap.release(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert( + noexcept(bootstrap.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/fail_t/CMakeLists.txt b/example/default/test/src/fail_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/src/fail_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/src/fail_t/behavior.cpp b/example/default/test/src/fail_t/behavior.cpp new file mode 100644 index 00000000..e6a409b5 --- /dev/null +++ b/example/default/test/src/fail_t/behavior.cpp @@ -0,0 +1,127 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/fail_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fail_t fail{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(fail.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + }; + }; + }; + + bsl::ut_scenario{"release executes without initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fail_t fail{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + fail.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"release executes with initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fail_t fail{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + fail.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + bsl::ut_then{} = [&]() noexcept { + fail.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch always fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fail_t fail{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !fail.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {})); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/fail_t/requirements.cpp b/example/default/test/src/fail_t/requirements.cpp new file mode 100644 index 00000000..7a119cc4 --- /dev/null +++ b/example/default/test/src/fail_t/requirements.cpp @@ -0,0 +1,118 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/fail_t.hpp" + +#include +#include + +namespace +{ + constinit example::fail_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::fail_t m_fail{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - fail_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + + bsl::discard(example::fail_t{}); + bsl::discard(m_fail.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + m_fail.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + bsl::discard(m_fail.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::fail_t fail{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::fail_t{})); + static_assert( + noexcept(fail.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert(noexcept(fail.release(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert( + noexcept(fail.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/main/CMakeLists.txt b/example/default/test/src/main/CMakeLists.txt new file mode 100644 index 00000000..98c49bc7 --- /dev/null +++ b/example/default/test/src/main/CMakeLists.txt @@ -0,0 +1,73 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +list(APPEND SOURCES + ../../../src/main.cpp +) + +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES} SOURCES ${SOURCES}) diff --git a/example/default/test/src/main/behavior.cpp b/example/default/test/src/main/behavior.cpp new file mode 100644 index 00000000..022e90b7 --- /dev/null +++ b/example/default/test/src/main/behavior.cpp @@ -0,0 +1,406 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace example +{ + /// @brief stores the bf_syscall_t that this code will use + // NOLINTNEXTLINE(bsl-non-pod-static) + extern syscall::bf_syscall_t g_sys; + /// @brief stores the intrinsic_t that this code will use + // NOLINTNEXTLINE(bsl-non-pod-static) + extern intrinsic_t g_intrinsic; + + /// @brief stores the pool of VPs that we will use + // NOLINTNEXTLINE(bsl-non-pod-static) + extern vp_pool_t g_vp_pool; + /// @brief stores the pool of VPSs that we will use + // NOLINTNEXTLINE(bsl-non-pod-static) + extern vps_pool_t g_vps_pool; + + /// @brief stores the bootstrap_t that this code will use + // NOLINTNEXTLINE(bsl-non-pod-static) + extern bootstrap_t g_bootstrap; + /// @brief stores the fail_t that this code will use + // NOLINTNEXTLINE(bsl-non-pod-static) + extern fail_t g_fail; + /// @brief stores the vmexit_t that this code will use + // NOLINTNEXTLINE(bsl-non-pod-static) + extern vmexit_t g_vmexit; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept; + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept; + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept; + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void ext_main_entry(bsl::uint32 const version) noexcept; + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"bootstrap_entry success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + g_bootstrap.set_dispatch(bsl::errc_failure); + bootstrap_entry({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bootstrap_entry success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + g_bootstrap.set_dispatch(bsl::errc_success); + bootstrap_entry({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"fail_entry success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + g_fail.set_dispatch(bsl::errc_failure); + fail_entry({}, {}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"fail_entry success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + g_fail.set_dispatch(bsl::errc_success); + fail_entry({}, {}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"vmexit_entry success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + g_vmexit.set_dispatch(bsl::errc_failure); + vmexit_entry({}, {}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"vmexit_entry success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + g_vmexit.set_dispatch(bsl::errc_success); + vmexit_entry({}, {}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"main unsupported version"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + syscall::g_bf_control_op_wait_impl_executed = {}; + g_sys.set_initialize(bsl::errc_success); + g_intrinsic.set_initialize(bsl::errc_success); + g_vp_pool.set_initialize(bsl::errc_success); + g_vps_pool.set_initialize(bsl::errc_success); + g_bootstrap.set_initialize(bsl::errc_success); + g_fail.set_initialize(bsl::errc_success); + g_vmexit.set_initialize(bsl::errc_success); + ext_main_entry({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + bsl::ut_check(!syscall::g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"main bf_syscall_t initialize fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + syscall::g_bf_control_op_wait_impl_executed = {}; + g_sys.set_initialize(bsl::errc_failure); + g_intrinsic.set_initialize(bsl::errc_success); + g_vp_pool.set_initialize(bsl::errc_success); + g_vps_pool.set_initialize(bsl::errc_success); + g_bootstrap.set_initialize(bsl::errc_success); + g_fail.set_initialize(bsl::errc_success); + g_vmexit.set_initialize(bsl::errc_success); + ext_main_entry(syscall::BF_ALL_SPECS_SUPPORTED_VAL.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + bsl::ut_check(!syscall::g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"main intrinsic_t initialize fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + syscall::g_bf_control_op_wait_impl_executed = {}; + g_sys.set_initialize(bsl::errc_success); + g_intrinsic.set_initialize(bsl::errc_failure); + g_vp_pool.set_initialize(bsl::errc_success); + g_vps_pool.set_initialize(bsl::errc_success); + g_bootstrap.set_initialize(bsl::errc_success); + g_fail.set_initialize(bsl::errc_success); + g_vmexit.set_initialize(bsl::errc_success); + ext_main_entry(syscall::BF_ALL_SPECS_SUPPORTED_VAL.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + bsl::ut_check(!syscall::g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"main vp_pool_t initialize fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + syscall::g_bf_control_op_wait_impl_executed = {}; + g_sys.set_initialize(bsl::errc_success); + g_intrinsic.set_initialize(bsl::errc_success); + g_vp_pool.set_initialize(bsl::errc_failure); + g_vps_pool.set_initialize(bsl::errc_success); + g_bootstrap.set_initialize(bsl::errc_success); + g_fail.set_initialize(bsl::errc_success); + g_vmexit.set_initialize(bsl::errc_success); + ext_main_entry(syscall::BF_ALL_SPECS_SUPPORTED_VAL.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + bsl::ut_check(!syscall::g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"main vps_pool_t initialize fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + syscall::g_bf_control_op_wait_impl_executed = {}; + g_sys.set_initialize(bsl::errc_success); + g_intrinsic.set_initialize(bsl::errc_success); + g_vp_pool.set_initialize(bsl::errc_success); + g_vps_pool.set_initialize(bsl::errc_failure); + g_bootstrap.set_initialize(bsl::errc_success); + g_fail.set_initialize(bsl::errc_success); + g_vmexit.set_initialize(bsl::errc_success); + ext_main_entry(syscall::BF_ALL_SPECS_SUPPORTED_VAL.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + bsl::ut_check(!syscall::g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"main bootstrap_t initialize fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + syscall::g_bf_control_op_wait_impl_executed = {}; + g_sys.set_initialize(bsl::errc_success); + g_intrinsic.set_initialize(bsl::errc_success); + g_vp_pool.set_initialize(bsl::errc_success); + g_vps_pool.set_initialize(bsl::errc_success); + g_bootstrap.set_initialize(bsl::errc_failure); + g_fail.set_initialize(bsl::errc_success); + g_vmexit.set_initialize(bsl::errc_success); + ext_main_entry(syscall::BF_ALL_SPECS_SUPPORTED_VAL.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + bsl::ut_check(!syscall::g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"main fail_t initialize fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + syscall::g_bf_control_op_wait_impl_executed = {}; + g_sys.set_initialize(bsl::errc_success); + g_intrinsic.set_initialize(bsl::errc_success); + g_vp_pool.set_initialize(bsl::errc_success); + g_vps_pool.set_initialize(bsl::errc_success); + g_bootstrap.set_initialize(bsl::errc_success); + g_fail.set_initialize(bsl::errc_failure); + g_vmexit.set_initialize(bsl::errc_success); + ext_main_entry(syscall::BF_ALL_SPECS_SUPPORTED_VAL.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + bsl::ut_check(!syscall::g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"main vmexit_t initialize fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + syscall::g_bf_control_op_wait_impl_executed = {}; + g_sys.set_initialize(bsl::errc_success); + g_intrinsic.set_initialize(bsl::errc_success); + g_vp_pool.set_initialize(bsl::errc_success); + g_vps_pool.set_initialize(bsl::errc_success); + g_bootstrap.set_initialize(bsl::errc_success); + g_fail.set_initialize(bsl::errc_success); + g_vmexit.set_initialize(bsl::errc_failure); + ext_main_entry(syscall::BF_ALL_SPECS_SUPPORTED_VAL.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + bsl::ut_check(!syscall::g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"main success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + syscall::g_bf_control_op_exit_impl_executed = {}; + syscall::g_bf_control_op_wait_impl_executed = {}; + g_sys.set_initialize(bsl::errc_success); + g_intrinsic.set_initialize(bsl::errc_success); + g_vp_pool.set_initialize(bsl::errc_success); + g_vps_pool.set_initialize(bsl::errc_success); + g_bootstrap.set_initialize(bsl::errc_success); + g_fail.set_initialize(bsl::errc_success); + g_vmexit.set_initialize(bsl::errc_success); + ext_main_entry(syscall::BF_ALL_SPECS_SUPPORTED_VAL.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(!syscall::g_bf_control_op_exit_impl_executed); + bsl::ut_check(syscall::g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/vp_pool_t/CMakeLists.txt b/example/default/test/src/vp_pool_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/src/vp_pool_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/src/vp_pool_t/behavior.cpp b/example/default/test/src/vp_pool_t/behavior.cpp new file mode 100644 index 00000000..0bcfd5d1 --- /dev/null +++ b/example/default/test/src/vp_pool_t/behavior.cpp @@ -0,0 +1,187 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/vp_pool_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize vp_t reports failure"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vp_pool.initialize(gs, tls, sys, intrinsic)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vp_pool.initialize(gs, tls, sys, intrinsic)); + }; + }; + }; + + bsl::ut_scenario{"release executes without initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + vp_pool.release(gs, tls, sys, intrinsic); + }; + }; + }; + + bsl::ut_scenario{"release executes with initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp_pool.initialize(gs, tls, sys, intrinsic)); + bsl::ut_then{} = [&]() noexcept { + vp_pool.release(gs, tls, sys, intrinsic); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vp_op_create_vp fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp_pool.initialize(gs, tls, sys, intrinsic)); + sys.set_bf_vp_op_create_vp({}, {}, bsl::safe_uint16::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vp_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vp_op_create_vp returns invalid id"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp_pool.initialize(gs, tls, sys, intrinsic)); + sys.set_bf_vp_op_create_vp({}, {}, syscall::BF_INVALID_ID); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vp_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate vp_t allocate fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp_pool.initialize(gs, tls, sys, intrinsic)); + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vp_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_pool_t vp_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp_pool.initialize(gs, tls, sys, intrinsic)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vp_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/vp_pool_t/requirements.cpp b/example/default/test/src/vp_pool_t/requirements.cpp new file mode 100644 index 00000000..f2b578b1 --- /dev/null +++ b/example/default/test/src/vp_pool_t/requirements.cpp @@ -0,0 +1,112 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/vp_pool_t.hpp" + +#include +#include + +namespace +{ + constinit example::vp_pool_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vp_pool_t m_vp_pool{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vp_pool_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + + bsl::discard(example::vp_pool_t{}); + bsl::discard(m_vp_pool.initialize(gs, tls, sys, intrinsic)); + m_vp_pool.release(gs, tls, sys, intrinsic); + bsl::discard(m_vp_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vp_pool_t vp_pool{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vp_pool_t{})); + static_assert(noexcept(vp_pool.initialize(gs, tls, sys, intrinsic))); + static_assert(noexcept(vp_pool.release(gs, tls, sys, intrinsic))); + static_assert(noexcept(vp_pool.allocate(gs, tls, sys, intrinsic, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/vp_t/CMakeLists.txt b/example/default/test/src/vp_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/src/vp_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/src/vp_t/behavior.cpp b/example/default/test/src/vp_t/behavior.cpp new file mode 100644 index 00000000..8b320ee7 --- /dev/null +++ b/example/default/test/src/vp_t/behavior.cpp @@ -0,0 +1,261 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/vp_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize twice fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vp.initialize(gs, tls, sys, intrinsic, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize invalid id #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_check( + !vp.initialize(gs, tls, sys, intrinsic, bsl::safe_uint16::failure())); + }; + }; + }; + + bsl::ut_scenario{"initialize invalid id #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_check(!vp.initialize(gs, tls, sys, intrinsic, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_check(vp.initialize(gs, tls, sys, intrinsic, {})); + }; + }; + }; + + bsl::ut_scenario{"release executes without initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + vp.release(gs, tls, sys, intrinsic); + }; + }; + }; + + bsl::ut_scenario{"release executes with initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + vp.release(gs, tls, sys, intrinsic); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate not initialized"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vp.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + + bsl::ut_scenario{"allocate already allocated"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_required_step(vp.allocate(gs, tls, sys, intrinsic, {}, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vp.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid vmid #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vp.allocate(gs, tls, sys, intrinsic, bsl::safe_uint16::failure(), {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid vmid #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vp.allocate(gs, tls, sys, intrinsic, syscall::BF_INVALID_ID, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid ppid #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vp.allocate(gs, tls, sys, intrinsic, {}, bsl::safe_uint16::failure())); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid ppid #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vp.allocate(gs, tls, sys, intrinsic, {}, syscall::BF_INVALID_ID)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vp_t vp{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vp.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vp.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/vp_t/requirements.cpp b/example/default/test/src/vp_t/requirements.cpp new file mode 100644 index 00000000..1bc902c4 --- /dev/null +++ b/example/default/test/src/vp_t/requirements.cpp @@ -0,0 +1,112 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/vp_t.hpp" + +#include +#include + +namespace +{ + constinit example::vp_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vp_t m_vp{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vp_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + + bsl::discard(example::vp_t{}); + bsl::discard(m_vp.initialize(gs, tls, sys, intrinsic, {})); + m_vp.release(gs, tls, sys, intrinsic); + bsl::discard(m_vp.allocate(gs, tls, sys, intrinsic, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vp_t vp{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vp_t{})); + static_assert(noexcept(vp.initialize(gs, tls, sys, intrinsic, {}))); + static_assert(noexcept(vp.release(gs, tls, sys, intrinsic))); + static_assert(noexcept(vp.allocate(gs, tls, sys, intrinsic, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/vps_pool_t/CMakeLists.txt b/example/default/test/src/vps_pool_t/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/src/vps_pool_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/src/vps_pool_t/behavior.cpp b/example/default/test/src/vps_pool_t/behavior.cpp new file mode 100644 index 00000000..9baa5321 --- /dev/null +++ b/example/default/test/src/vps_pool_t/behavior.cpp @@ -0,0 +1,187 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/vps_pool_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize vps_t reports failure"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps_pool.initialize(gs, tls, sys, intrinsic)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vps_pool.initialize(gs, tls, sys, intrinsic)); + }; + }; + }; + + bsl::ut_scenario{"release executes without initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + vps_pool.release(gs, tls, sys, intrinsic); + }; + }; + }; + + bsl::ut_scenario{"release executes with initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps_pool.initialize(gs, tls, sys, intrinsic)); + bsl::ut_then{} = [&]() noexcept { + vps_pool.release(gs, tls, sys, intrinsic); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_create_vps fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps_pool.initialize(gs, tls, sys, intrinsic)); + sys.set_bf_vps_op_create_vps({}, {}, bsl::safe_uint16::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_create_vps returns invalid id"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps_pool.initialize(gs, tls, sys, intrinsic)); + sys.set_bf_vps_op_create_vps({}, {}, syscall::BF_INVALID_ID); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate vps_t allocate fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps_pool.initialize(gs, tls, sys, intrinsic)); + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_pool_t vps_pool{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps_pool.initialize(gs, tls, sys, intrinsic)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vps_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/vps_pool_t/requirements.cpp b/example/default/test/src/vps_pool_t/requirements.cpp new file mode 100644 index 00000000..2994997e --- /dev/null +++ b/example/default/test/src/vps_pool_t/requirements.cpp @@ -0,0 +1,112 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/vps_pool_t.hpp" + +#include +#include + +namespace +{ + constinit example::vps_pool_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vps_pool_t m_vps_pool{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vps_pool_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + + bsl::discard(example::vps_pool_t{}); + bsl::discard(m_vps_pool.initialize(gs, tls, sys, intrinsic)); + m_vps_pool.release(gs, tls, sys, intrinsic); + bsl::discard(m_vps_pool.allocate(gs, tls, sys, intrinsic, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vps_pool_t vps_pool{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vps_pool_t{})); + static_assert(noexcept(vps_pool.initialize(gs, tls, sys, intrinsic))); + static_assert(noexcept(vps_pool.release(gs, tls, sys, intrinsic))); + static_assert(noexcept(vps_pool.allocate(gs, tls, sys, intrinsic, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/x64/amd/intrinsic_t/CMakeLists.txt b/example/default/test/src/x64/amd/intrinsic_t/CMakeLists.txt new file mode 100644 index 00000000..22dd32fb --- /dev/null +++ b/example/default/test/src/x64/amd/intrinsic_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) +bf_add_test(behavior INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) diff --git a/example/default/test/src/x64/amd/intrinsic_t/behavior.cpp b/example/default/test/src/x64/amd/intrinsic_t/behavior.cpp new file mode 100644 index 00000000..16a18780 --- /dev/null +++ b/example/default/test/src/x64/amd/intrinsic_t/behavior.cpp @@ -0,0 +1,122 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/amd/intrinsic_t.hpp" + +#include +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(intrinsic.initialize(gs, tls)); + }; + }; + }; + + bsl::ut_scenario{"release executes without initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_then{} = [&]() noexcept { + intrinsic.release(gs, tls); + }; + }; + }; + + bsl::ut_scenario{"release executes with initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(intrinsic.initialize(gs, tls)); + bsl::ut_then{} = [&]() noexcept { + intrinsic.release(gs, tls); + }; + }; + }; + }; + + bsl::ut_scenario{"cpuid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + constexpr auto expected_result{42_u64}; + bsl::ut_when{} = [&]() noexcept { + gs.cpuid_val = expected_result; + intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(rax == expected_result); + bsl::ut_check(rbx == expected_result); + bsl::ut_check(rcx == expected_result); + bsl::ut_check(rdx == expected_result); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/x64/amd/intrinsic_t/requirements.cpp b/example/default/test/src/x64/amd/intrinsic_t/requirements.cpp new file mode 100644 index 00000000..c5adfbe7 --- /dev/null +++ b/example/default/test/src/x64/amd/intrinsic_t/requirements.cpp @@ -0,0 +1,116 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/amd/intrinsic_t.hpp" + +#include +#include + +namespace +{ + constinit example::intrinsic_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::intrinsic_t m_intrinsic{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - intrinsic_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + + bsl::discard(example::intrinsic_t{}); + bsl::discard(m_intrinsic.initialize(gs, tls)); + m_intrinsic.release(gs, tls); + m_intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::intrinsic_t intrinsic{}; + example::gs_t gs{}; + example::tls_t tls{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::intrinsic_t{})); + static_assert(noexcept(intrinsic.initialize(gs, tls))); + static_assert(noexcept(intrinsic.release(gs, tls))); + static_assert(noexcept(intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/x64/amd/vmexit_t/CMakeLists.txt b/example/default/test/src/x64/amd/vmexit_t/CMakeLists.txt new file mode 100644 index 00000000..22dd32fb --- /dev/null +++ b/example/default/test/src/x64/amd/vmexit_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) +bf_add_test(behavior INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) diff --git a/example/default/test/src/x64/amd/vmexit_t/behavior.cpp b/example/default/test/src/x64/amd/vmexit_t/behavior.cpp new file mode 100644 index 00000000..d253c004 --- /dev/null +++ b/example/default/test/src/x64/amd/vmexit_t/behavior.cpp @@ -0,0 +1,313 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/amd/vmexit_t.hpp" + +#include + +namespace example +{ + // ------------------------------------------------------------------------- + // constants + // ------------------------------------------------------------------------- + + /// @brief stores the answer to all things (in 32 bits) + constexpr auto ANSWER32{42_u32}; + + // ------------------------------------------------------------------------- + // tests + // ------------------------------------------------------------------------- + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + }; + }; + }; + + bsl::ut_scenario{"release executes without initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"release executes with initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + bsl::ut_then{} = [&]() noexcept { + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch cpuid stop"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0x72_u64}; + constexpr auto online_pps{0x2_u16}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + sys.bf_tls_set_rcx(bsl::to_u64(loader::CPUID_COMMAND_ECX_STOP)); + sys.bf_tls_set_online_pps(online_pps); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch cpuid stop last ppid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0x72_u64}; + constexpr auto online_pps{0x2_u16}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + sys.bf_tls_set_rcx(bsl::to_u64(loader::CPUID_COMMAND_ECX_STOP)); + sys.bf_tls_set_ppid(online_pps - 1_u16); + sys.bf_tls_set_online_pps(online_pps); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch cpuid stop bf_vps_op_advance_ip fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0x72_u64}; + constexpr auto online_pps{0x2_u16}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + sys.bf_tls_set_rcx(bsl::to_u64(loader::CPUID_COMMAND_ECX_STOP)); + sys.bf_tls_set_online_pps(online_pps); + sys.set_bf_vps_op_advance_ip({}, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch report on"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0x72_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + sys.bf_tls_set_rcx(bsl::to_u64(loader::CPUID_COMMAND_ECX_REPORT_ON)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch report off"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0x72_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + sys.bf_tls_set_rcx(bsl::to_u64(loader::CPUID_COMMAND_ECX_REPORT_OFF)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch cpuid default"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0x72_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + intrinsic.set_cpuid(ANSWER32, ANSWER32, ANSWER32, ANSWER32); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + bsl::ut_check(sys.bf_tls_rax() == bsl::to_u64(ANSWER32)); + bsl::ut_check(sys.bf_tls_rbx() == bsl::to_u64(ANSWER32)); + bsl::ut_check(sys.bf_tls_rcx() == bsl::to_u64(ANSWER32)); + bsl::ut_check(sys.bf_tls_rdx() == bsl::to_u64(ANSWER32)); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch invalid command"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0x72_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch fails by default"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vmexit.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {})); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/x64/amd/vmexit_t/requirements.cpp b/example/default/test/src/x64/amd/vmexit_t/requirements.cpp new file mode 100644 index 00000000..abc1b034 --- /dev/null +++ b/example/default/test/src/x64/amd/vmexit_t/requirements.cpp @@ -0,0 +1,118 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/amd/vmexit_t.hpp" + +#include +#include + +namespace +{ + constinit example::vmexit_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vmexit_t m_vmexit{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vmexit_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + + bsl::discard(example::vmexit_t{}); + bsl::discard(m_vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + m_vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + bsl::discard(m_vmexit.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vmexit_t vmexit{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vmexit_t{})); + static_assert( + noexcept(vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert(noexcept(vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert( + noexcept(vmexit.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/x64/amd/vps_t/CMakeLists.txt b/example/default/test/src/x64/amd/vps_t/CMakeLists.txt new file mode 100644 index 00000000..22dd32fb --- /dev/null +++ b/example/default/test/src/x64/amd/vps_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) +bf_add_test(behavior INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) diff --git a/example/default/test/src/x64/amd/vps_t/behavior.cpp b/example/default/test/src/x64/amd/vps_t/behavior.cpp new file mode 100644 index 00000000..3bd6e63f --- /dev/null +++ b/example/default/test/src/x64/amd/vps_t/behavior.cpp @@ -0,0 +1,352 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/amd/vps_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize twice fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.initialize(gs, tls, sys, intrinsic, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize invalid id #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_check( + !vps.initialize(gs, tls, sys, intrinsic, bsl::safe_uint16::failure())); + }; + }; + }; + + bsl::ut_scenario{"initialize invalid id #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_check(!vps.initialize(gs, tls, sys, intrinsic, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_check(vps.initialize(gs, tls, sys, intrinsic, {})); + }; + }; + }; + + bsl::ut_scenario{"release executes without initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + vps.release(gs, tls, sys, intrinsic); + }; + }; + }; + + bsl::ut_scenario{"release executes with initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + vps.release(gs, tls, sys, intrinsic); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate not initialized"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + + bsl::ut_scenario{"allocate already allocated"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_required_step(vps.allocate(gs, tls, sys, intrinsic, {}, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid vpid #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate( + gs, tls, sys, intrinsic, bsl::safe_uint16::failure(), {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid vpid #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vps.allocate(gs, tls, sys, intrinsic, syscall::BF_INVALID_ID, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid ppid #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate( + gs, tls, sys, intrinsic, {}, bsl::safe_uint16::failure())); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid ppid #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vps.allocate(gs, tls, sys, intrinsic, {}, syscall::BF_INVALID_ID)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_init_as_root fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_vps_op_init_as_root({}, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate when ppid does not match vpsid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto ppid{42_u16}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vps.allocate(gs, tls, sys, intrinsic, {}, ppid)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_write32 fails for asid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto idx{0x0058_u64}; + constexpr auto val{0x1_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_vps_op_write32({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_write32 fails for intercept 1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto idx{0x000C_u64}; + constexpr auto val{0x00040000_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_vps_op_write32({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_write32 fails for intercept 2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto idx{0x0010_u64}; + constexpr auto val{0x00000001_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_vps_op_write32({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/x64/amd/vps_t/requirements.cpp b/example/default/test/src/x64/amd/vps_t/requirements.cpp new file mode 100644 index 00000000..d4848f12 --- /dev/null +++ b/example/default/test/src/x64/amd/vps_t/requirements.cpp @@ -0,0 +1,112 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/amd/vps_t.hpp" + +#include +#include + +namespace +{ + constinit example::vps_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vps_t m_vps{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vps_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + + bsl::discard(example::vps_t{}); + bsl::discard(m_vps.initialize(gs, tls, sys, intrinsic, {})); + m_vps.release(gs, tls, sys, intrinsic); + bsl::discard(m_vps.allocate(gs, tls, sys, intrinsic, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vps_t vps{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vps_t{})); + static_assert(noexcept(vps.initialize(gs, tls, sys, intrinsic, {}))); + static_assert(noexcept(vps.release(gs, tls, sys, intrinsic))); + static_assert(noexcept(vps.allocate(gs, tls, sys, intrinsic, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/x64/intel/intrinsic_t/CMakeLists.txt b/example/default/test/src/x64/intel/intrinsic_t/CMakeLists.txt new file mode 100644 index 00000000..bdb65470 --- /dev/null +++ b/example/default/test/src/x64/intel/intrinsic_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) +bf_add_test(behavior INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) diff --git a/example/default/test/src/x64/intel/intrinsic_t/behavior.cpp b/example/default/test/src/x64/intel/intrinsic_t/behavior.cpp new file mode 100644 index 00000000..0559e790 --- /dev/null +++ b/example/default/test/src/x64/intel/intrinsic_t/behavior.cpp @@ -0,0 +1,122 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/intel/intrinsic_t.hpp" + +#include +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(intrinsic.initialize(gs, tls)); + }; + }; + }; + + bsl::ut_scenario{"release executes without initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_then{} = [&]() noexcept { + intrinsic.release(gs, tls); + }; + }; + }; + + bsl::ut_scenario{"release executes with initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(intrinsic.initialize(gs, tls)); + bsl::ut_then{} = [&]() noexcept { + intrinsic.release(gs, tls); + }; + }; + }; + }; + + bsl::ut_scenario{"cpuid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + intrinsic_t intrinsic{}; + gs_t gs{}; + tls_t tls{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + constexpr auto expected_result{42_u64}; + bsl::ut_when{} = [&]() noexcept { + gs.cpuid_val = expected_result; + intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(rax == expected_result); + bsl::ut_check(rbx == expected_result); + bsl::ut_check(rcx == expected_result); + bsl::ut_check(rdx == expected_result); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/x64/intel/intrinsic_t/requirements.cpp b/example/default/test/src/x64/intel/intrinsic_t/requirements.cpp new file mode 100644 index 00000000..85322d26 --- /dev/null +++ b/example/default/test/src/x64/intel/intrinsic_t/requirements.cpp @@ -0,0 +1,116 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/intel/intrinsic_t.hpp" + +#include +#include + +namespace +{ + constinit example::intrinsic_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::intrinsic_t m_intrinsic{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - intrinsic_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + + bsl::discard(example::intrinsic_t{}); + bsl::discard(m_intrinsic.initialize(gs, tls)); + m_intrinsic.release(gs, tls); + m_intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::intrinsic_t intrinsic{}; + example::gs_t gs{}; + example::tls_t tls{}; + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::intrinsic_t{})); + static_assert(noexcept(intrinsic.initialize(gs, tls))); + static_assert(noexcept(intrinsic.release(gs, tls))); + static_assert(noexcept(intrinsic.cpuid(gs, tls, rax, rbx, rcx, rdx))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/x64/intel/vmexit_t/CMakeLists.txt b/example/default/test/src/x64/intel/vmexit_t/CMakeLists.txt new file mode 100644 index 00000000..bdb65470 --- /dev/null +++ b/example/default/test/src/x64/intel/vmexit_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) +bf_add_test(behavior INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) diff --git a/example/default/test/src/x64/intel/vmexit_t/behavior.cpp b/example/default/test/src/x64/intel/vmexit_t/behavior.cpp new file mode 100644 index 00000000..dd4167ec --- /dev/null +++ b/example/default/test/src/x64/intel/vmexit_t/behavior.cpp @@ -0,0 +1,514 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/intel/vmexit_t.hpp" + +#include + +namespace example +{ + // ------------------------------------------------------------------------- + // constants + // ------------------------------------------------------------------------- + + /// @brief stores the answer to all things (in 32 bits) + constexpr auto ANSWER32{42_u32}; + + // ------------------------------------------------------------------------- + // tests + // ------------------------------------------------------------------------- + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize bf_mem_op_alloc_page fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_mem_op_alloc_page(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"release executes without initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_then{} = [&]() noexcept { + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"release executes with initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + bsl::ut_then{} = [&]() noexcept { + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + }; + + bsl::ut_scenario{"dispatch nmi bf_vps_op_read32 fails for proc ctls"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0_u64}; + constexpr auto idx{0x4002_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.set_bf_vps_op_read32({}, idx, bsl::safe_uint32::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch nmi bf_vps_op_write32 fails for proc ctls"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0_u64}; + constexpr auto idx{0x4002_u64}; + constexpr auto val{0x400000_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.set_bf_vps_op_write32({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch nmi default"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch nmi window bf_vps_op_read32 fails for proc ctls"} = + []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0x8_u64}; + constexpr auto idx{0x4002_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.set_bf_vps_op_read32({}, idx, bsl::safe_uint32::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch nmi bf_vps_op_write32 fails for proc ctls"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0x8_u64}; + constexpr auto idx{0x4002_u64}; + constexpr auto val{0x0_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.set_bf_vps_op_write32({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch nmi bf_vps_op_write32 fails for int info"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0x8_u64}; + constexpr auto idx{0x4016_u64}; + constexpr auto val{0x80000202_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.set_bf_vps_op_write32({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch nmi window default"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0x8_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch cpuid stop"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0xA_u64}; + constexpr auto online_pps{0x2_u16}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + sys.bf_tls_set_rcx(bsl::to_u64(loader::CPUID_COMMAND_ECX_STOP)); + sys.bf_tls_set_online_pps(online_pps); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch cpuid stop last ppid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0xA_u64}; + constexpr auto online_pps{0x2_u16}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + sys.bf_tls_set_rcx(bsl::to_u64(loader::CPUID_COMMAND_ECX_STOP)); + sys.bf_tls_set_ppid(online_pps - 1_u16); + sys.bf_tls_set_online_pps(online_pps); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch cpuid stop bf_vps_op_advance_ip fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0xA_u64}; + constexpr auto online_pps{0x2_u16}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + sys.bf_tls_set_rcx(bsl::to_u64(loader::CPUID_COMMAND_ECX_STOP)); + sys.bf_tls_set_online_pps(online_pps); + sys.set_bf_vps_op_advance_ip({}, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch report on"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0xA_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + sys.bf_tls_set_rcx(bsl::to_u64(loader::CPUID_COMMAND_ECX_REPORT_ON)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch report off"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0xA_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + sys.bf_tls_set_rcx(bsl::to_u64(loader::CPUID_COMMAND_ECX_REPORT_OFF)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch cpuid default"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0xA_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + intrinsic.set_cpuid(ANSWER32, ANSWER32, ANSWER32, ANSWER32); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + bsl::ut_check(sys.bf_tls_rax() == bsl::to_u64(ANSWER32)); + bsl::ut_check(sys.bf_tls_rbx() == bsl::to_u64(ANSWER32)); + bsl::ut_check(sys.bf_tls_rcx() == bsl::to_u64(ANSWER32)); + bsl::ut_check(sys.bf_tls_rdx() == bsl::to_u64(ANSWER32)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch invalid command"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0xA_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + sys.bf_tls_set_rax(bsl::to_u64(loader::CPUID_COMMAND_EAX)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + bsl::ut_scenario{"dispatch fails by default"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vmexit_t vmexit{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + vp_pool_t vp_pool{}; + vps_pool_t vps_pool{}; + constexpr auto exit_reason{0xFF_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step( + vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vmexit.dispatch( + gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, exit_reason)); + }; + vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/x64/intel/vmexit_t/requirements.cpp b/example/default/test/src/x64/intel/vmexit_t/requirements.cpp new file mode 100644 index 00000000..5d35784c --- /dev/null +++ b/example/default/test/src/x64/intel/vmexit_t/requirements.cpp @@ -0,0 +1,118 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/intel/vmexit_t.hpp" + +#include +#include + +namespace +{ + constinit example::vmexit_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vmexit_t m_vmexit{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vmexit_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + + bsl::discard(example::vmexit_t{}); + bsl::discard(m_vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool)); + m_vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool); + bsl::discard(m_vmexit.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vmexit_t vmexit{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + example::vp_pool_t vp_pool{}; + example::vps_pool_t vps_pool{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vmexit_t{})); + static_assert( + noexcept(vmexit.initialize(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert(noexcept(vmexit.release(gs, tls, sys, intrinsic, vp_pool, vps_pool))); + static_assert( + noexcept(vmexit.dispatch(gs, tls, sys, intrinsic, vp_pool, vps_pool, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/x64/intel/vps_t/CMakeLists.txt b/example/default/test/src/x64/intel/vps_t/CMakeLists.txt new file mode 100644 index 00000000..bdb65470 --- /dev/null +++ b/example/default/test/src/x64/intel/vps_t/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) +bf_add_test(behavior INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) diff --git a/example/default/test/src/x64/intel/vps_t/behavior.cpp b/example/default/test/src/x64/intel/vps_t/behavior.cpp new file mode 100644 index 00000000..da8e8c7c --- /dev/null +++ b/example/default/test/src/x64/intel/vps_t/behavior.cpp @@ -0,0 +1,550 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/intel/vps_t.hpp" + +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize twice fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.initialize(gs, tls, sys, intrinsic, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize invalid id #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vps.initialize(gs, tls, sys, intrinsic, bsl::safe_uint16::failure())); + }; + }; + }; + + bsl::ut_scenario{"initialize invalid id #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.initialize(gs, tls, sys, intrinsic, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vps.initialize(gs, tls, sys, intrinsic, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"release executes without initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + vps.release(gs, tls, sys, intrinsic); + }; + }; + }; + + bsl::ut_scenario{"release executes with initialize"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + vps.release(gs, tls, sys, intrinsic); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate not initialized"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + + bsl::ut_scenario{"allocate already allocated"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_required_step(vps.allocate(gs, tls, sys, intrinsic, {}, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid vpid #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate( + gs, tls, sys, intrinsic, bsl::safe_uint16::failure(), {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid vpid #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vps.allocate(gs, tls, sys, intrinsic, syscall::BF_INVALID_ID, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid ppid #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate( + gs, tls, sys, intrinsic, {}, bsl::safe_uint16::failure())); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid ppid #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + !vps.allocate(gs, tls, sys, intrinsic, {}, syscall::BF_INVALID_ID)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_init_as_root fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_vps_op_init_as_root({}, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate when ppid does not match vpsid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto ppid{42_u16}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vps.allocate(gs, tls, sys, intrinsic, {}, ppid)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_write16 fails for vpid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto idx{0x0000_u64}; + constexpr auto val{0x1_u16}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_vps_op_write16({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_write64 fails for link ptr"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto idx{0x2800_u64}; + constexpr auto val{0xFFFFFFFFFFFFFFFF_u64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_vps_op_write64({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_intrinsic_op_rdmsr fails for pin ctls"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto msr{0x48D_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_intrinsic_op_rdmsr(msr, bsl::safe_uint64::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_write32 fails for pin ctls"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto idx{0x4000_u64}; + constexpr auto val{0x0_u32}; + constexpr auto msr{0x48D_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_intrinsic_op_rdmsr(msr, {}); + sys.set_bf_vps_op_write32({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_intrinsic_op_rdmsr fails for proc ctls"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto msr{0x48E_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_intrinsic_op_rdmsr(msr, bsl::safe_uint64::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_write32 fails for proc ctls"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto idx{0x4002_u64}; + constexpr auto val{0x0_u32}; + constexpr auto msr{0x48E_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_intrinsic_op_rdmsr(msr, {}); + sys.set_bf_vps_op_write32({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_intrinsic_op_rdmsr fails for exit ctls"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto msr{0x48F_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_intrinsic_op_rdmsr(msr, bsl::safe_uint64::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_write32 fails for exit ctls"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto idx{0x400C_u64}; + constexpr auto val{0x0_u32}; + constexpr auto msr{0x48F_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_intrinsic_op_rdmsr(msr, {}); + sys.set_bf_vps_op_write32({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_intrinsic_op_rdmsr fails for entry ctls"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto msr{0x490_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_intrinsic_op_rdmsr(msr, bsl::safe_uint64::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_write32 fails for entry ctls"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto idx{0x4012_u64}; + constexpr auto val{0x0_u32}; + constexpr auto msr{0x490_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_intrinsic_op_rdmsr(msr, {}); + sys.set_bf_vps_op_write32({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_intrinsic_op_rdmsr fails for proc ctls2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto msr{0x48B_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_intrinsic_op_rdmsr(msr, bsl::safe_uint64::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_write32 fails for proc ctls2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto idx{0x401E_u64}; + constexpr auto val{0x0_u32}; + constexpr auto msr{0x48B_u32}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_intrinsic_op_rdmsr(msr, {}); + sys.set_bf_vps_op_write32({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate bf_vps_op_write64 fails for msr bitmap"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + constexpr auto idx{0x2004_u64}; + constexpr auto val{42_umax}; + bsl::ut_when{} = [&]() noexcept { + gs.msr_bitmap_phys = val; + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + sys.set_bf_vps_op_write64({}, idx, val, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + vps_t vps{}; + gs_t gs{}; + tls_t tls{}; + syscall::bf_syscall_t sys{}; + intrinsic_t intrinsic{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(vps.initialize(gs, tls, sys, intrinsic, {})); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(vps.allocate(gs, tls, sys, intrinsic, {}, {})); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/x64/intel/vps_t/requirements.cpp b/example/default/test/src/x64/intel/vps_t/requirements.cpp new file mode 100644 index 00000000..811f886c --- /dev/null +++ b/example/default/test/src/x64/intel/vps_t/requirements.cpp @@ -0,0 +1,112 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/x64/intel/vps_t.hpp" + +#include +#include + +namespace +{ + constinit example::vps_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + example::vps_t m_vps{}; + + public: + [[nodiscard]] static constexpr auto + test_member_const() noexcept -> bool + { + /// NOTE: + /// - vps_t does not contain const member functions + /// + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + + bsl::discard(example::vps_t{}); + bsl::discard(m_vps.initialize(gs, tls, sys, intrinsic, {})); + m_vps.release(gs, tls, sys, intrinsic); + bsl::discard(m_vps.allocate(gs, tls, sys, intrinsic, {}, {})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + example::vps_t vps{}; + example::gs_t gs{}; + example::tls_t tls{}; + syscall::bf_syscall_t sys{}; + example::intrinsic_t intrinsic{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::vps_t{})); + static_assert(noexcept(vps.initialize(gs, tls, sys, intrinsic, {}))); + static_assert(noexcept(vps.release(gs, tls, sys, intrinsic))); + static_assert(noexcept(vps.allocate(gs, tls, sys, intrinsic, {}, {}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/src/x64/intrinsic_cpuid_impl/CMakeLists.txt b/example/default/test/src/x64/intrinsic_cpuid_impl/CMakeLists.txt new file mode 100644 index 00000000..5d58f8e9 --- /dev/null +++ b/example/default/test/src/x64/intrinsic_cpuid_impl/CMakeLists.txt @@ -0,0 +1,74 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +list(APPEND SOURCES + ../../../../src/x64/intrinsic_cpuid_impl.S +) + +bf_add_test(requirements INCLUDES ${X64_INCLUDES} SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} DEFINES ${X64_DEFINES} SOURCES ${SOURCES}) +bf_add_test(behavior INCLUDES ${X64_INCLUDES} SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} DEFINES ${X64_DEFINES} SOURCES ${SOURCES}) diff --git a/example/default/test/src/x64/intrinsic_cpuid_impl/behavior.cpp b/example/default/test/src/x64/intrinsic_cpuid_impl/behavior.cpp new file mode 100644 index 00000000..72dd6450 --- /dev/null +++ b/example/default/test/src/x64/intrinsic_cpuid_impl/behavior.cpp @@ -0,0 +1,83 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/intrinsic_cpuid_impl.hpp" + +#include +#include + +namespace example +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"intrinsic_cpuid_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto data{0x1234567800000000_u64}; + constexpr auto mask{0xFFFFFFFF00000000_u64}; + auto rax{data}; + auto rbx{data}; + auto rcx{data}; + auto rdx{data}; + bsl::ut_when{} = [&]() noexcept { + intrinsic_cpuid_impl(nullptr, rax.data(), rbx.data(), rcx.data(), rdx.data()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check((rax & mask) == data); + bsl::ut_check((rbx & mask) == data); + bsl::ut_check((rcx & mask) == data); + bsl::ut_check((rdx & mask) == data); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/src/x64/intrinsic_cpuid_impl/requirements.cpp b/example/default/test/src/x64/intrinsic_cpuid_impl/requirements.cpp new file mode 100644 index 00000000..5e7e24de --- /dev/null +++ b/example/default/test/src/x64/intrinsic_cpuid_impl/requirements.cpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/intrinsic_cpuid_impl.hpp" + +#include +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(example::intrinsic_cpuid_impl({}, {}, {}, {}, {}))); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/test/template/CMakeLists.txt b/example/default/test/template/CMakeLists.txt new file mode 100644 index 00000000..17537cc2 --- /dev/null +++ b/example/default/test/template/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# NOTE: +# - Add the tests themselves here. There are several variables that you can +# add to the bf_add_test macro including: +# - SOURCES = any source files that should be included in the test +# - INCLUDES = any include directories that should be included in the test +# - SYSTEM_INCLUDES = any system include directories that should be included +# in the test. System includes are not included in a Clang Tidy check. +# - LIBRARIES = any libraries that should be included in the test +# - DEFINES = any definitions that should be included in the test +# +# - The high level CMake file for the tests already configures a number of +# these automatically for you. Each test needs to make sure it includes the +# proper variable (for example, code that does not have arch specific) stuff +# in it should use the COMMON_ versions, while code that has arch specific +# stuff in it should use the arch specific versions of these variables. +# +# - You can also add do these variables however you want for each test. For +# example, if you want to add the definition THE_ANSWER=42 to the behavior +# unit test, create a BEHAVIOR_DEFINES, append THE_ANSWER=42 and append +# ${COMMON_DEFINES}, and use BEHAVIOR_DEFINES instead of COMMON_DEFINES in +# the call to bf_add_test. This can be done to any of these variables to +# custom tailor a specific test as needed. If a test needs different versions +# of any of these, break the test into different files and create the custom +# tailor versions of each test as needed. +# +# - By default, we provide a "requirements" test and a "behavior" test. The +# "requirements" test verifies things like the ability to define globally +# using constinit, constness and noexcept. None of the code in this test +# actually runs and instead it is there to ensure the code signatures make +# sense. The "behavior" test is where the code is actually executed to make +# sure it executes as expected. This code will run the tests both at compile +# time and at runtime. If a specific test cannot be run at compile time +# (which hopefully is minimal if the code is structured properly), you can +# use the bsl::ut_given_at_runtime instead of bsl::ut_given, which will +# exclude the test from compile time checks. +# +# - Each test only includes the one thing that is trying to test. For example, +# suppose we are testing the bootstrap_t logic. This file includes a number +# of dependencies. We do not include the path to where these dependencies +# are located in the include path for the unit test. Instead, we include +# a folder than contains our mocks. All of the dependencies must be mocked. +# When the bootstrap_t code is compiled, it will not realize that it is +# using the mocked versions of it's dependecies, similar to how a lot of this +# code is unaware of which arch specific code it is using and the build +# system figures out which version to use, unit tests do the same thing. +# + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/example/default/test/template/behavior.cpp b/example/default/test/template/behavior.cpp new file mode 100644 index 00000000..df8797a0 --- /dev/null +++ b/example/default/test/template/behavior.cpp @@ -0,0 +1,284 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +// #include "../../src/.hpp" + +#include +#include + +namespace example +{ + /// + /// @brief Simple function for testing non-constexpr functions. + /// + /// + /// @param val a value to test + /// @return Returns true if val is correct + /// + [[nodiscard]] auto + runtime_only_function_that_knows_all(bsl::safe_uintmax const &val) noexcept -> bool + { + constexpr auto the_answer_to_everything{42_umax}; + return val == the_answer_to_everything; + } + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + /// NOTE: + /// - The tests() function is executed both at compile-time and at + /// runtime. This is done using the following at the bottom of this + /// file. + /// + /// static_assert(example::tests() == bsl::ut_success()); + /// return example::tests(); + /// + /// - Anything executed in a static_assert is executed at compile-time + /// while the other call is your typical runtime call. + /// + + /// NOTE: + /// - BSL unit tests use behavioral driven unit testing. + /// https://en.wikipedia.org/wiki/Behavior-driven_development + /// + /// - All of these calls are syntactic sugar, meaning they do + /// absolutely nothing, except to ensure you are setting up your + /// tests using behavioral driven methods. The actual work is + /// performed by the following: + /// - bsl::ut_check() - used inside bsl::ut_then, and is used to + /// verify the results of your unit test + /// - bsl::ut_required_step() - used inside of bsl::ut_when, and + /// is used to verify that your unit test's set up is correct. + /// + + bsl::ut_scenario{"this is what I am testing"} = []() noexcept { + bsl::ut_given{"given the following"} = []() noexcept { + /// add variables here + bsl::ut_when{"when we do the following"} = [&]() noexcept { + /// add function calls here + bsl::ut_then{"we expect the following"} = [&]() noexcept { + /// add results checking here + }; + }; + }; + }; + + /// NOTE: + /// - There are a couple of different ways to do this. Once way + /// is to group tests under the same scenario as follows: + /// + + bsl::ut_scenario{"verify +="} = []() noexcept { + bsl::ut_given{} = []() noexcept { + constexpr auto data1{42_umax}; + bsl::safe_uintmax data2{}; + bsl::ut_when{} = [&]() noexcept { + data2 += data1; + bsl::ut_then{"adds correctly"} = [&]() noexcept { + bsl::ut_check(data2 == data1); + }; + }; + }; + + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto data1{42_umax}; + auto data2{bsl::safe_uintmax::failure()}; + bsl::ut_when{} = [&]() noexcept { + data2 += data1; + bsl::ut_then{"preserves the error flag"} = [&]() noexcept { + bsl::ut_check(!data2); + }; + }; + }; + }; + + /// NOTE: + /// - Another way is to have one scenario for each test as follows. + /// Which way you choose if up to you, there likely isn't a right + /// way here. One advantage with this approach is each description + /// is a bit more helpful in determining what you are actually + /// changing as sometimes, the changes between each test can be + /// really hard to see, especially when each test is big and you + /// are only changing one thing (or even a single character) + /// + + bsl::ut_scenario{"verify += adds correctly"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + constexpr auto data1{42_umax}; + bsl::safe_uintmax data2{}; + bsl::ut_when{} = [&]() noexcept { + data2 += data1; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(data2 == data1); + }; + }; + }; + }; + + bsl::ut_scenario{"verify += preserves the error flag"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto data1{42_umax}; + auto data2{bsl::safe_uintmax::failure()}; + bsl::ut_when{} = [&]() noexcept { + data2 += data1; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!data2); + }; + }; + }; + }; + + /// NOTE: + /// - If you have to unit test something that does not support + /// constexpr, you can use this pattern. This should be avoided + /// whenever possible. These tests will only be verified at + /// runtime as they are excluded from compile-time verification. + /// - Also not how bsl::ut_when was removed. This is because there + /// was no additional action to take. + /// + + bsl::ut_scenario{"test something at runtime only"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto val{42_umax}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(runtime_only_function_that_knows_all(val)); + }; + }; + + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto val{23_umax}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!runtime_only_function_that_knows_all(val)); + }; + }; + }; + + /// NOTE: + /// - There are also times when you need to set up a test and ensure + /// that specific steps in the test's set up succeed. Otherwise, the + /// test itself might not be valid, could cause a crach, etc. When + /// this is needed, you can use the bsl::ut_required_step() function. + /// - This function is identical to bsl::ut_check(). It just has a + /// different name and is intended to be used in the bsl::ut_when() + /// block, and has a different name just to help with readability. + /// + + bsl::ut_scenario{"verify += preserves the error flag"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + constexpr auto data1{42_umax}; + auto data2{42_umax}; + bsl::ut_when{} = [&]() noexcept { + data2 += data1; + bsl::ut_required_step(data2 == 84_umax); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(data2 - 42_umax == 42_umax); + }; + }; + }; + }; + + /// NOTE: + /// - Finally, some tests will use the same variables, but check + /// different conditions. When you do this, we don't want to have + /// to manually reset a specific variable for each test. If the + /// type is copyable, we can use the following pattern, otherwise + /// you should create a new variable for each test to ensure you + /// have a clean slate as we did in the tests above. + /// - Note that the key difference here is that we are not passing + /// by reference but instead by value which performs a copy, but + /// when we do this, we need to add the mutable keyword. + /// + + bsl::ut_scenario{"verify two different conditions"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + constexpr auto data1{42_umax}; + bsl::safe_uintmax data2{}; + bsl::ut_when{} = [&, data2]() mutable noexcept { + data2 += data1; + bsl::ut_then{} = [&, data2]() noexcept { + bsl::ut_check(data2 == data1); + }; + }; + + bsl::ut_when{} = [&, data2]() mutable noexcept { + data2 += (data1 * data1); + bsl::ut_then{} = [&, data2]() noexcept { + bsl::ut_check(data2 == (data1 * data1)); + }; + }; + }; + }; + + /// NOTE: + /// - The following provides a basic block that you can cut/paste + /// for each test as needed. Don't forget that you have the following + /// make targets when you compile with CODECOV as the build target, + /// which will help you check for coverage. + /// - make codecov-grcov (puts the results in ${CMAKE_SOURCE_DIR}/grcov) + /// - make codecov-genhtml (Linux only, puts the results in ${CMAKE_SOURCE_DIR}/genhtml) + /// - make codecov-upload (uploads coverage reports to Codecov if you set your token) + /// + /// - Good luck!!! + /// + + bsl::ut_scenario{"description"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(true); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(example::tests() == bsl::ut_success()); + return example::tests(); +} diff --git a/example/default/test/template/requirements.cpp b/example/default/test/template/requirements.cpp new file mode 100644 index 00000000..7730d524 --- /dev/null +++ b/example/default/test/template/requirements.cpp @@ -0,0 +1,212 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +// #include "../../src/.hpp" + +#include +#include +#include + +namespace +{ + /// NOTE: + /// - The requirements unit test ensures that the code adhere to specific + /// C++ requirements including constinit, constness, constexpr and + /// noexcept. This is a quick double check to make sure that your code + /// meets all of these requirements. Note that not all of the code + /// needs to have all of these, but instead, this unit test ensures that + /// each function has these as intended, and forces you to give your + /// code a once over for these specific attributes. + /// - Replace bsl::errc_type with your type. We keep this in place so + /// that it is easy to see how to use each of these patterns. + /// + + /// NOTE: + /// - The following verifies that our type can be initialized using the + /// C++20 constinit keyword. This ensures that if we need to create a + /// global version of this (or something that uses this code), it is + /// initialized at compile-time and not at runtime. + /// + + constinit bsl::errc_type const g_verify_constinit{}; + + /// NOTE: + /// - The following is used to ensure that each function is marked as + /// const as needed. Everything in the test_member_const function + /// should be marked as const. If it is not, it will not compile. + /// The test_member_nonconst function should have all of the functions + /// to ensure that everything is tested. + /// - Also note that in this test we have two of our classes under test. + /// This is to support the == and != operator functions. These functions + /// are not member functions, but we add them to these tests anyways + /// as they have to use member functions, which adds an additional check + /// encase we are missing something, and it allows the non-const tests + /// to be the same as the noexcept tests. + /// - The const test does not need to test constructors as that doesn't + /// make much sense, and it is expect that for some classes, not all of + /// the member functions will be in the const test as they will not be + /// marked as const. The non-const test should have every function + /// including the constructors. + /// + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + bsl::errc_type m_errc1{}; + bsl::errc_type m_errc2{}; + + public: + [[nodiscard]] constexpr auto + test_member_const() const noexcept -> bool + { + bsl::discard(m_errc1.get()); + bsl::discard(!m_errc1); + bsl::discard(m_errc1.success()); + bsl::discard(m_errc1.failure()); + bsl::discard(m_errc1.is_checked()); + bsl::discard(m_errc1.is_unchecked()); + bsl::discard(m_errc1 == m_errc2); + bsl::discard(m_errc1 != m_errc2); + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + constexpr auto the_answer{42_i32}; + + bsl::discard(bsl::errc_type{}); + bsl::discard(bsl::errc_type{the_answer.get()}); + bsl::discard(bsl::errc_type{the_answer}); + bsl::discard(m_errc1.get()); + bsl::discard(!m_errc1); + bsl::discard(m_errc1.success()); + bsl::discard(m_errc1.failure()); + bsl::discard(m_errc1.is_checked()); + bsl::discard(m_errc1.is_unchecked()); + bsl::discard(m_errc1 == m_errc2); + bsl::discard(m_errc1 != m_errc2); + + return true; + } + }; + + /// NOTE: + /// - The following verifies that all of our code will compile as a + /// constexpr. If test_member_nonconst contains a call to all of the + /// functions in your class, the following will not compile if anything + /// in the class is not constexpr friendly. + /// + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + /// NOTE: + /// - This is really just here to make some compilers happy that we have + /// a global variable and that it is actually being used. + /// + + bsl::ut_scenario{"verify supports constinit/constexpr"} = []() noexcept { + bsl::discard(g_verify_constinit); + bsl::discard(FIXTURE1); + }; + + /// NOTE: + /// - The following verifies that all functions are marked as noexcept. + /// This list should include not only all of the functions, but all + /// constructors as well. + /// + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::errc_type errc1{}; + bsl::errc_type errc2{}; + constexpr auto the_answer{42_i32}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(bsl::errc_type{})); + static_assert(noexcept(bsl::errc_type{the_answer.get()})); + static_assert(noexcept(bsl::errc_type{the_answer})); + static_assert(noexcept(errc1.get())); + static_assert(noexcept(!errc1)); + static_assert(noexcept(errc1.success())); + static_assert(noexcept(errc1.failure())); + static_assert(noexcept(errc1.is_checked())); + static_assert(noexcept(errc1.is_unchecked())); + static_assert(noexcept(errc1 == errc2)); + static_assert(noexcept(errc1 != errc2)); + }; + }; + }; + + /// NOTE: + /// - The following is what actually verifies constness. This can be + /// left as is in each test. It is important to note that we use a + /// static_assert here to ensure that the const functions are also + /// constexpr friendly as yet another verifier that this is working + /// correctly. + /// + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + /// NOTE: + /// - The following a second version of this, designed to support + /// classes that are not constexpr friendly. Ideally, you will never + /// need this, but in some cases, this might be needed. The difference + /// is we use const instead of a global constexpr used in a static + /// assert. + /// + + bsl::ut_scenario{"verify constness without using constexpr"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + fixture_t const fixture3{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(fixture3.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/example/default/x64/amd/arch_support.hpp b/example/default/x64/amd/arch_support.hpp deleted file mode 100644 index fd23b5df..00000000 --- a/example/default/x64/amd/arch_support.hpp +++ /dev/null @@ -1,156 +0,0 @@ -/// @copyright -/// Copyright (C) 2020 Assured Information Security, Inc. -/// -/// @copyright -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// @copyright -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// @copyright -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -/// SOFTWARE. - -#ifndef ARCH_SUPPORT_HPP -#define ARCH_SUPPORT_HPP - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace example -{ - /// - /// @brief Implements the architecture specific VMExit handler. - /// - /// - /// @tparam HANDLE_CONCEPT the type of handle to use - /// @param handle the handle to use - /// @param vpsid the ID of the VPS that generated the VMExit - /// @param exit_reason the exit reason associated with the VMExit - /// - template - constexpr void - vmexit( - HANDLE_CONCEPT &handle, - bsl::safe_uint16 const &vpsid, - bsl::safe_uint64 const &exit_reason) noexcept - { - bsl::errc_type ret{}; - constexpr bsl::safe_uintmax EXIT_REASON_CPUID{bsl::to_umax(0x72U)}; - - /// NOTE: - /// - At a minimum, we need to handle CPUID on AMD. Note that the - /// "run" APIs all return an error code, but for the most part we - /// can ignore them. If the this function succeeds, it will not - /// return. If it fails, it will return, and the error code is - /// always UNKNOWN. We output the current line so that debugging - /// the issue is easier. - /// - - switch (exit_reason.get()) { - case EXIT_REASON_CPUID.get(): { - ret = handle_vmexit_cpuid(handle, vpsid); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return; - } - - bsl::discard(syscall::bf_vps_op_advance_ip_and_run_current(handle)); - bsl::print() << bsl::here(); - return; - } - - default: { - break; - } - } - - bsl::error() << "unknown exit_reason: " // -- - << bsl::hex(exit_reason) // -- - << bsl::endl // -- - << bsl::here(); // -- - } - - /// - /// @brief Initializes a VPS with architecture specific stuff. - /// - /// - /// @tparam HANDLE_CONCEPT the type of handle to use - /// @param handle the handle to use - /// @param vpsid the VPS being intialized - /// @return Returns bsl::errc_success on success and bsl::errc_failure - /// on failure. - /// - template - [[nodiscard]] constexpr auto - init_vps(HANDLE_CONCEPT &handle, bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type - { - syscall::bf_status_t status{}; - - /// NOTE: - /// - Set up ASID - /// - - constexpr bsl::safe_uint64 guest_asid_idx{bsl::to_u64(0x0058)}; - constexpr bsl::safe_uint32 guest_asid_val{bsl::to_u32(0x1)}; - - status = syscall::bf_vps_op_write32(handle, vpsid, guest_asid_idx, guest_asid_val); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - /// NOTE: - /// - Set up wht intercept controls. On AMD, we need to intercept - /// VMRun, and CPUID if we plan to support reporting and stopping. - /// - - constexpr bsl::safe_uint64 intercept_instruction1_idx{bsl::to_u64(0x000CU)}; - constexpr bsl::safe_uint32 intercept_instruction1_val{bsl::to_u32(0x00040000U)}; - constexpr bsl::safe_uint64 intercept_instruction2_idx{bsl::to_u64(0x0010U)}; - constexpr bsl::safe_uint32 intercept_instruction2_val{bsl::to_u32(0x00000001U)}; - - status = syscall::bf_vps_op_write32( - handle, vpsid, intercept_instruction1_idx, intercept_instruction1_val); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - status = syscall::bf_vps_op_write32( - handle, vpsid, intercept_instruction2_idx, intercept_instruction2_val); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - /// NOTE: - /// - Report success. Specifically, when we return to the root OS, - /// setting RAX tells the loader that the hypervisor was successfully - /// set up. - /// - - syscall::bf_tls_set_rax(handle, bsl::ZERO_UMAX); - return bsl::errc_success; - } -} - -#endif diff --git a/example/nested_paging/CMakeLists.txt b/example/nested_paging/CMakeLists.txt new file mode 100644 index 00000000..530c701d --- /dev/null +++ b/example/nested_paging/CMakeLists.txt @@ -0,0 +1,160 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +add_executable(example_nested_paging) + +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + +target_include_directories(example_nested_paging PRIVATE + . +) + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + target_include_directories(example_nested_paging PRIVATE + x64 + ) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") + target_include_directories(example_nested_paging PRIVATE + x64/amd + ) + endif() + + if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + target_include_directories(example_nested_paging PRIVATE + x64/intel + ) + endif() +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + target_include_directories(example_nested_paging PRIVATE + arm + ) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + target_include_directories(example_nested_paging PRIVATE + arm/aarch64 + ) + endif() +endif() + +# ------------------------------------------------------------------------------ +# Headers +# ------------------------------------------------------------------------------ + +list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/page_pool_t.hpp +) + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/x64/common_arch_support.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/intrinsic_cpuid.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/map_page_flags.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/memory_type.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/mtrrs_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/range_t.hpp + ) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/x64/amd/arch_support.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/amd/nested_page_table_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/amd/npdpt_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/amd/npdpte_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/amd/npdt_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/amd/npdte_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/amd/npml4t_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/amd/npml4te_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/amd/npt_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/amd/npte_t.hpp + ) + endif() + + if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/x64/intel/arch_support.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/intel/epdpt_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/intel/epdpte_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/intel/epdt_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/intel/epdte_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/intel/epml4t_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/intel/epml4te_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/intel/ept_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/intel/epte_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/x64/intel/extended_page_table_t.hpp + ) + endif() +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/arm/common_arch_support.hpp + ) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/arm/aarch64/arch_support.hpp + ) + endif() +endif() + +# ------------------------------------------------------------------------------ +# Sources +# ------------------------------------------------------------------------------ + +target_sources(example_nested_paging PRIVATE + main.cpp +) + +set_property(SOURCE main.cpp APPEND PROPERTY OBJECT_DEPENDS ${HEADERS}) + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + target_sources(example_nested_paging PRIVATE + x64/intrinsic_cpuid.S + ) + + set_property(SOURCE x64/intrinsic_cpuid.S APPEND PROPERTY OBJECT_DEPENDS ${HEADERS}) +endif() + +# ------------------------------------------------------------------------------ +# Libraries +# ------------------------------------------------------------------------------ + +target_link_libraries(example_nested_paging PRIVATE + runtime + bsl + loader + syscall +) + +# ------------------------------------------------------------------------------ +# Install +# ------------------------------------------------------------------------------ + +if(CMAKE_BUILD_TYPE STREQUAL RELEASE OR CMAKE_BUILD_TYPE STREQUAL MINSIZEREL) + add_custom_command(TARGET example_nested_paging POST_BUILD COMMAND ${CMAKE_STRIP} example_nested_paging) +endif() + +install(TARGETS example_nested_paging DESTINATION bin) diff --git a/example/nested_paging/arm/aarch64/arch_support.hpp b/example/nested_paging/arm/aarch64/arch_support.hpp new file mode 100644 index 00000000..c159de67 --- /dev/null +++ b/example/nested_paging/arm/aarch64/arch_support.hpp @@ -0,0 +1,77 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef ARCH_SUPPORT_HPP +#define ARCH_SUPPORT_HPP + +#include + +#include +#include +#include +#include +#include +#include + +namespace example +{ + /// + /// @brief Implements the architecture specific VMExit handler. + /// + /// + /// @param handle the handle to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + constexpr void + vmexit( + syscall::bf_handle_t &handle, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint64 const &exit_reason) noexcept + { + bsl::discard(handle); + bsl::discard(vpsid); + bsl::discard(exit_reason); + } + + /// + /// @brief Initializes a VPS with architecture specific stuff. + /// + /// + /// @param handle the handle to use + /// @param vpsid the VPS being intialized + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + init_vps(syscall::bf_handle_t &handle, bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + { + bsl::discard(handle); + bsl::discard(vpsid); + + return bsl::errc_success; + } +} + +#endif diff --git a/example/nested_paging/arm/common_arch_support.hpp b/example/nested_paging/arm/common_arch_support.hpp new file mode 100644 index 00000000..dd82eaea --- /dev/null +++ b/example/nested_paging/arm/common_arch_support.hpp @@ -0,0 +1,28 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef COMMON_ARCH_SUPPORT_HPP +#define COMMON_ARCH_SUPPORT_HPP + +#endif diff --git a/kernel/src/x64/smap_guard_t.hpp b/example/nested_paging/lock_guard.hpp similarity index 63% rename from kernel/src/x64/smap_guard_t.hpp rename to example/nested_paging/lock_guard.hpp index dec8a064..a9e9493f 100644 --- a/kernel/src/x64/smap_guard_t.hpp +++ b/example/nested_paging/lock_guard.hpp @@ -22,58 +22,53 @@ /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE /// SOFTWARE. -#ifndef SMAP_GUARD_HPP -#define SMAP_GUARD_HPP +#ifndef LOCK_GUARD_HPP +#define LOCK_GUARD_HPP -#include - -namespace mk +namespace example { - namespace details - { - /// - /// @brief Unlocks SMAP - /// - extern "C" void unlock_smap() noexcept; - - /// - /// @brief Locks SMAP - /// - extern "C" void lock_smap() noexcept; - } - - /// @class mk::smap_guard_t + /// @class example::lock_guard /// /// - /// @brief Ensures that user-space memory is accessible from the - /// microkernel. Once this class loses scope, extension memory may - /// no longer be accessible. + /// @brief Implements a lock_guard. /// - class smap_guard_t final + /// + /// @tparam T the type of mutex being locked + /// + template + class lock_guard final { + /// @brief stores the lock that is being guarded + T &m_lock; + public: /// - /// @brief Default constructor + /// @brief Creates a lock_guard, locking the provided + /// spinlock/mutex on construction. /// - constexpr smap_guard_t() noexcept + /// + /// @param lck the spinlock/mutex to guard + /// + explicit constexpr lock_guard(T &lck) noexcept // -- + : m_lock{lck} { - if (bsl::is_constant_evaluated()) { - return; - } - - details::unlock_smap(); + m_lock.lock(); } + /// + /// @brief Do not allow temporaries. + /// + /// + /// @param lck the spinlock/mutex to guard + /// + constexpr lock_guard(T const &lck) noexcept = delete; + /// /// @brief Destructor /// - constexpr ~smap_guard_t() noexcept + constexpr ~lock_guard() noexcept { - if (bsl::is_constant_evaluated()) { - return; - } - - details::lock_smap(); + m_lock.unlock(); } /// @@ -82,7 +77,7 @@ namespace mk /// /// @param o the object being copied /// - constexpr smap_guard_t(smap_guard_t const &o) noexcept = delete; + constexpr lock_guard(lock_guard const &o) noexcept = delete; /// /// @brief move constructor @@ -90,7 +85,7 @@ namespace mk /// /// @param o the object being moved /// - constexpr smap_guard_t(smap_guard_t &&o) noexcept = delete; + constexpr lock_guard(lock_guard &&o) noexcept = default; /// /// @brief copy assignment @@ -99,8 +94,7 @@ namespace mk /// @param o the object being copied /// @return a reference to *this /// - [[maybe_unused]] constexpr auto operator=(smap_guard_t const &o) &noexcept - -> smap_guard_t & = delete; + [[maybe_unused]] auto operator=(lock_guard const &o) noexcept -> lock_guard & = delete; /// /// @brief move assignment @@ -109,8 +103,7 @@ namespace mk /// @param o the object being moved /// @return a reference to *this /// - [[maybe_unused]] constexpr auto operator=(smap_guard_t &&o) &noexcept - -> smap_guard_t & = delete; + [[maybe_unused]] auto operator=(lock_guard &&o) noexcept -> lock_guard & = default; }; } diff --git a/example/default/main.cpp b/example/nested_paging/main.cpp similarity index 70% rename from example/default/main.cpp rename to example/nested_paging/main.cpp index c795861f..713cd4b4 100644 --- a/example/default/main.cpp +++ b/example/nested_paging/main.cpp @@ -30,6 +30,7 @@ #include #include #include +#include namespace example { @@ -38,13 +39,14 @@ namespace example /// /// @brief Implements the VMExit entry function. This is registered - /// by the bootstrap function to execute whenever a VMExit occurs. + /// by the main function to execute whenever a VMExit occurs. /// /// /// @param vpsid the ID of the VPS that generated the VMExit /// @param exit_reason the exit reason associated with the VMExit /// void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) vmexit_entry(bsl::uint16 const vpsid, bsl::uint64 const exit_reason) noexcept { vmexit(g_handle, vpsid, exit_reason); @@ -56,17 +58,18 @@ namespace example /// bsl::print() << bsl::here(); - syscall::bf_control_op_exit(); + return syscall::bf_control_op_exit(); } /// /// @brief Implements the fast fail entry function. This is registered - /// by the bootstrap function to execute whenever a fast fail occurs. + /// by the main function to execute whenever a fast fail occurs. /// /// /// @param fail_reason the exit reason associated with the fail /// void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) fail_entry(syscall::bf_status_t::value_type const fail_reason) noexcept { bsl::discard(fail_reason); @@ -97,7 +100,7 @@ namespace example /// bsl::print() << bsl::here(); - syscall::bf_control_op_exit(); + return syscall::bf_control_op_exit(); } /// @@ -112,66 +115,33 @@ namespace example /// @param ppid the physical process to bootstrap /// void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) bootstrap_entry(bsl::uint16 const ppid) noexcept { - bsl::safe_uint16 vmid{}; + bsl::errc_type ret{}; + bsl::safe_uint16 vpid{}; bsl::safe_uint16 vpsid{}; - syscall::bf_status_t status{}; /// NOTE: - /// - Before we can create a VM, VP and VPS, we must first register - /// for VMExits. If we don't, the microkernel will complain as it - /// ensures the extension that registers for VMExits is the only - /// extension that can create and manage these resources. - /// - We also register for fast fail events in case something bad - /// happens. - /// - - status = syscall::bf_callback_op_register_vmexit(g_handle, vmexit_entry); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { - bsl::print() << bsl::here(); - syscall::bf_control_op_exit(); - } - - status = syscall::bf_callback_op_register_fail(g_handle, fail_entry); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { - bsl::print() << bsl::here(); - syscall::bf_control_op_exit(); - } - - /// NOTE: - /// - Create the root VM, root VP and root VPS that we will start. + /// - Create the root VP and root VPS that we will start. /// Since we are not implementing nested virtualization or VSM - /// support, the VP and VPS are always identical. - /// - /// IMPORTANT: - /// - The microkernel does not check to make sure that a VPS is not - /// run on different PPs at the same time. This would require an - /// enormous amount of overhead on every VMExit to address. As a - /// result, it is possible to corrupt the system if you are not - /// careful with respect to creating VPSs and running them on the - /// proper PPs. You have been warned. + /// support, the VPID and VPSID are always identical. + /// - There is no need to create the root VM as this is created + /// for you. You only need to create VMs if you plan to add guest + /// VM support to your extension. /// - if (bsl::ZERO_U16 == ppid) { - status = syscall::bf_vm_op_create_vm(g_handle, vmid); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { - bsl::print() << bsl::here(); - syscall::bf_control_op_exit(); - } + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_ROOT_VMID, ppid, vpid); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); } - status = syscall::bf_vp_op_create_vp(g_handle, vpid); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_create_vps(g_handle, vpid, ppid, vpsid); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - syscall::bf_control_op_exit(); - } - - status = syscall::bf_vps_op_create_vps(g_handle, vpsid); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { - bsl::print() << bsl::here(); - syscall::bf_control_op_exit(); + return syscall::bf_control_op_exit(); } /// NOTE: @@ -182,31 +152,31 @@ namespace example /// just before the microkernel was started. /// - status = syscall::bf_vps_op_init_as_root(g_handle, vpsid); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_init_as_root(g_handle, vpsid); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - syscall::bf_control_op_exit(); + return syscall::bf_control_op_exit(); } /// NOTE: /// - Initialize architecture specific logic in the VPS. /// - if (bsl::unlikely(!init_vps(g_handle, vpsid))) { + if (bsl::unlikely_assert(!init_vps(g_handle, vpsid))) { bsl::print() << bsl::here(); - syscall::bf_control_op_exit(); + return syscall::bf_control_op_exit(); } /// NOTE: - /// - Run the newly created VP on behalf of the newly created VM - /// using the newly created and initialized VPS. + /// - Run the newly created VP on behalf of the root VM using the + /// newly created and initialized VPS. /// - It should be noted that if bf_vps_op_run succeeds, it will /// not return. Like the rest of the code in this example, we /// return success for unit testing purposes. If this function /// returns, it is actually an error. /// - bsl::discard(syscall::bf_vps_op_run(g_handle, vpsid, vpid, vmid)); + bsl::discard(syscall::bf_vps_op_run(g_handle, syscall::BF_ROOT_VMID, vpid, vpsid)); /// NOTE: /// - The following is only called if an error occurs. Failure to @@ -227,9 +197,9 @@ namespace example /// microkernel speak the same ABI. /// extern "C" void - ext_main_entry(bsl::safe_uint32 const &version) noexcept + ext_main_entry(bsl::uint32 const version) noexcept { - syscall::bf_status_t status; + bsl::errc_type ret{}; /// NOTE: /// - Check to see if the microkernel speaks the same version as we @@ -241,7 +211,7 @@ namespace example if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { bsl::error() << "unsupported microkernel\n" << bsl::here(); - syscall::bf_control_op_exit(); + return syscall::bf_control_op_exit(); } /// NOTE: @@ -249,10 +219,10 @@ namespace example /// remaining syscalls. /// - status = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - syscall::bf_control_op_exit(); + return syscall::bf_control_op_exit(); } /// NOTE: @@ -260,10 +230,32 @@ namespace example /// each PP /// - status = syscall::bf_callback_op_register_bootstrap(g_handle, bootstrap_entry); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_callback_op_register_bootstrap(g_handle, &bootstrap_entry); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - syscall::bf_control_op_exit(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - Register the vmexit entry function so that we can handle + /// VMExits + /// + + ret = syscall::bf_callback_op_register_vmexit(g_handle, &vmexit_entry); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + /// NOTE: + /// - Register the vmexit entry function so that we can handle + /// fast fail events + /// + + ret = syscall::bf_callback_op_register_fail(g_handle, &fail_entry); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); } /// NOTE: @@ -274,6 +266,6 @@ namespace example /// function leads to undefined behaviour (likely a page fault). /// - syscall::bf_callback_op_wait(); + syscall::bf_control_op_wait(); } } diff --git a/example/nested_paging/page_pool_t.hpp b/example/nested_paging/page_pool_t.hpp new file mode 100644 index 00000000..0ed8b388 --- /dev/null +++ b/example/nested_paging/page_pool_t.hpp @@ -0,0 +1,249 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef PAGE_POOL_T_HPP +#define PAGE_POOL_T_HPP + +#include "lock_guard.hpp" +#include "spinlock.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::page_pool_t + /// + /// + /// @brief The page pool is responsible for allocating and freeing + /// pages. The page pool exists in the extensions's direct map and so + /// the page pool can also return the physical address of any page + /// that it has allocated. For more information about how this page + /// pool works, see the page_pool_t in the kernel, as they are + /// very similar. + /// + /// One question you might ask if, why have a page_pool_t in the + /// extension in the first place? The reason is because some + /// microkernel implementation might not implement the free_page + /// ABI as it is optional, but the extension will still need to be + /// able to free memory and reuse it. For this reason, all allocations + /// are done using this class, instead of allocating memory manually. + /// Any time memory is freed, it is returned to the page pool to be + /// used again on the next allocation, and any time an allocation + /// occurs and there isn't enough memory, the extension asks the + /// kernel for another page. This way, the extension is only asking + /// for pages when it needs it, and it is able to reuse memory + /// when it is freed. + /// + class page_pool_t final + { + /// @brief stores true if initialized() has been executed + bool m_initialized{}; + /// @brief stores the handle used to communicate with the kernel + syscall::bf_handle_t m_handle{}; + /// @brief stores the head of the page pool stack. + void *m_head{}; + /// @brief stores the total number of bytes in the page pool. + bsl::safe_uintmax m_size{}; + /// @brief safe guards operations on the pool. + mutable spinlock m_pool_lock{}; + + public: + /// + /// @brief Initializes the page pool + /// + /// + /// @param handle the handle used to communicate with the kernel + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize(syscall::bf_handle_t const &handle) noexcept -> bsl::errc_type + { + if (bsl::unlikely(m_initialized)) { + bsl::error() << "page_pool_t already initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + bsl::finally release_on_error{[this]() noexcept -> void { + this->release(); + }}; + + m_handle = handle; + + release_on_error.ignore(); + m_initialized = true; + + return bsl::errc_success; + } + + /// + /// @brief Release the page_pool_t + /// + constexpr void + release() noexcept + { + m_size = {}; + m_head = {}; + + m_handle = {}; + m_initialized = {}; + } + + /// + /// @brief Allocates a page from the page pool. + /// + /// + /// @tparam T the type of pointer to return + /// @return Returns a pointer to the newly allocated page + /// + template + [[nodiscard]] constexpr auto + allocate() noexcept -> T * + { + lock_guard lock{m_pool_lock}; + + if (bsl::unlikely(!m_initialized)) { + bsl::error() << "page_pool_t not initialized\n" << bsl::here(); + return nullptr; + } + + if (bsl::unlikely(nullptr == m_head)) { + m_head = syscall::bf_mem_op_alloc_page(m_handle); + if (bsl::unlikely(nullptr == m_head)) { + bsl::print() << bsl::here(); + return nullptr; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + void *const ptr{m_head}; + m_head = *static_cast(m_head); + + bsl::builtin_memset(ptr, '\0', bsl::to_umax(HYPERVISOR_PAGE_SIZE).get()); + + if constexpr (!bsl::is_void::value) { + static_assert(bsl::is_standard_layout::value, "T must be a standard layout"); + bsl::construct_at(ptr); + } + + return static_cast(ptr); + } + + /// + /// @brief Returns a page previously allocated using the allocate + /// function to the page pool. + /// + /// + /// @param ptr the pointer to the page to deallocate + /// + constexpr void + deallocate(void *const ptr) noexcept + { + lock_guard lock{m_pool_lock}; + + if (bsl::unlikely(!m_initialized)) { + bsl::error() << "page_pool_t not initialized\n" << bsl::here(); + return; + } + + if (bsl::unlikely(nullptr == ptr)) { + return; + } + + if (bsl::to_umax(ptr) < bsl::to_umax(HYPERVISOR_EXT_PAGE_POOL_ADDR)) { + bsl::error() << "invalid ptr" // -- + << ptr // -- + << bsl::endl // -- + << bsl::here(); + + return; + } + + *static_cast(ptr) = m_head; + m_head = ptr; + } + + /// + /// @brief Converts a virtual address to a physical address for + /// any page allocated by the page pool. If the provided ptr + /// was not allocated using the allocate function by the same + /// page pool, this results of this function are UB. It should + /// be noted that any virtual address may be used meaning the + /// provided address does not have to be page aligned, it simply + /// needs to be allocated using the same page pool. + /// + /// + /// @tparam T defines the type of virtual address being converted + /// @param virt the virtual address to convert + /// @return the resulting physical address + /// + template + [[nodiscard]] constexpr auto + virt_to_phys(T const *const virt) const noexcept -> bsl::safe_uintmax + { + static_assert(bsl::disjunction, bsl::is_standard_layout>::value); + return bsl::to_umax(virt) - bsl::to_umax(HYPERVISOR_EXT_PAGE_POOL_ADDR); + } + + /// + /// @brief Converts a physical address to a virtual address for + /// any page allocated by the page pool. If the provided address + /// was not allocated using the allocate function by the same + /// page pool, this results of this function are UB. It should + /// be noted that any physical address may be used meaning the + /// provided address does not have to be page aligned, it simply + /// needs to be allocated using the same page pool. + /// + /// + /// @tparam T defines the type of virtual address to convert to + /// @param phys the physical address to convert + /// @return the resulting virtual address + /// + template + [[nodiscard]] constexpr auto + phys_to_virt(bsl::safe_uintmax const &phys) const noexcept -> T * + { + static_assert(bsl::disjunction, bsl::is_standard_layout>::value); + return bsl::to_ptr(phys + bsl::to_umax(HYPERVISOR_EXT_PAGE_POOL_ADDR)); + } + }; +} + +#endif diff --git a/example/nested_paging/spinlock.hpp b/example/nested_paging/spinlock.hpp new file mode 100644 index 00000000..4caf25fc --- /dev/null +++ b/example/nested_paging/spinlock.hpp @@ -0,0 +1,128 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef SPINLOCK_HPP +#define SPINLOCK_HPP + +#include + +#pragma clang diagnostic ignored "-Watomic-implicit-seq-cst" + +namespace example +{ + /// @class example::spinlock + /// + /// + /// @brief Implements a spinlock + /// + class spinlock final + { + /// @brief stores whether or not the lock is acquired + _Atomic bool m_flag; + + public: + /// + /// @brief Default constructor. + /// + // We cannot member initialize atomics so this is not possible + // NOLINTNEXTLINE(bsl-class-member-init) + constexpr spinlock() noexcept + { + // This is the only way to initialize this + // NOLINTNEXTLINE(bsl-implicit-conversions-forbidden) + m_flag = false; + } + + /// + /// @brief Destructor + /// + constexpr ~spinlock() noexcept = default; + + /// + /// @brief copy constructor + /// + /// + /// @param o the object being copied + /// + constexpr spinlock(spinlock const &o) noexcept = delete; + + /// + /// @brief move constructor + /// + /// + /// @param o the object being moved + /// + constexpr spinlock(spinlock &&o) noexcept = default; + + /// + /// @brief copy assignment + /// + /// + /// @param o the object being copied + /// @return a reference to *this + /// + [[maybe_unused]] auto operator=(spinlock const &o) noexcept -> spinlock & = delete; + + /// + /// @brief move assignment + /// + /// + /// @param o the object being moved + /// @return a reference to *this + /// + [[maybe_unused]] auto operator=(spinlock &&o) noexcept -> spinlock & = default; + + /// + /// @brief Locks the spinlock. This will not return until the + /// spinlock can be successfully acquired. + /// + constexpr void + lock() noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + while (__c11_atomic_exchange(&m_flag, true, __ATOMIC_ACQUIRE)) { + while (__c11_atomic_load(&m_flag, __ATOMIC_RELAXED)) { + } + } + } + + /// + /// @brief Unlocks the spinlock. + /// + constexpr void + unlock() noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + __c11_atomic_store(&m_flag, false, __ATOMIC_RELEASE); + } + }; +} + +#endif diff --git a/example/nested_paging/x64/amd/arch_support.hpp b/example/nested_paging/x64/amd/arch_support.hpp new file mode 100644 index 00000000..1805e906 --- /dev/null +++ b/example/nested_paging/x64/amd/arch_support.hpp @@ -0,0 +1,283 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef ARCH_SUPPORT_HPP +#define ARCH_SUPPORT_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace example +{ + /// @brief stores the page pool to use for page allocation + constinit inline page_pool_t g_page_pool{}; + /// @brief stores the nested page tables + constinit inline nested_page_table_t g_npt{}; + + /// + /// @brief Implements the architecture specific VMExit handler. + /// + /// + /// @param handle the handle to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + constexpr void + vmexit( + syscall::bf_handle_t &handle, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint64 const &exit_reason) noexcept + { + bsl::errc_type ret{}; + constexpr bsl::safe_uintmax exit_reason_cpuid{bsl::to_umax(0x72U)}; + + /// NOTE: + /// - At a minimum, we need to handle CPUID on AMD. Note that the + /// "run" APIs all return an error code, but for the most part we + /// can ignore them. If the this function succeeds, it will not + /// return. If it fails, it will return, and the error code is + /// always UNKNOWN. We output the current line so that debugging + /// the issue is easier. + /// + + switch (exit_reason.get()) { + case exit_reason_cpuid.get(): { + ret = handle_vmexit_cpuid(handle, vpsid); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return; + } + + bsl::discard(syscall::bf_vps_op_advance_ip_and_run_current(handle)); + bsl::print() << bsl::here(); + return; + } + + default: { + break; + } + } + + syscall::bf_debug_op_dump_vps(vpsid); + + bsl::error() << "unknown exit_reason: " // -- + << bsl::hex(exit_reason) // -- + << bsl::endl // -- + << bsl::here(); // -- + } + + /// + /// @brief Initializes a VPS with architecture specific stuff. + /// + /// + /// @param handle the handle to use + /// @param vpsid the VPS being intialized + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + init_vps(syscall::bf_handle_t &handle, bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + + /// NOTE: + /// - Set up ASID + /// + + constexpr bsl::safe_uint64 guest_asid_idx{bsl::to_u64(0x0058U)}; + constexpr bsl::safe_uint32 guest_asid_val{bsl::to_u32(0x1U)}; + + ret = syscall::bf_vps_op_write32(handle, vpsid, guest_asid_idx, guest_asid_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Set up intercept controls. On AMD, we need to intercept + /// VMRun, and CPUID if we plan to support reporting and stopping. + /// + + constexpr bsl::safe_uint64 intercept_instruction1_idx{bsl::to_u64(0x000CU)}; + constexpr bsl::safe_uint32 intercept_instruction1_val{bsl::to_u32(0x00040000U)}; + constexpr bsl::safe_uint64 intercept_instruction2_idx{bsl::to_u64(0x0010U)}; + constexpr bsl::safe_uint32 intercept_instruction2_val{bsl::to_u32(0x00000001U)}; + + ret = syscall::bf_vps_op_write32( + handle, vpsid, intercept_instruction1_idx, intercept_instruction1_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + ret = syscall::bf_vps_op_write32( + handle, vpsid, intercept_instruction2_idx, intercept_instruction2_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - The first step in setting up nested paging is to determine + /// if we have support for it. We do this on each physical processor + /// we are being started on, but likely you could just do this + /// check on the first physical processor and be done. + /// + + constexpr bsl::safe_uintmax cpuid_svm_feature_identification{bsl::to_umax(0x8000000AU)}; + constexpr bsl::safe_uintmax cpuid_svm_feature_identification_np{bsl::to_umax(0x00000001U)}; + + rax = cpuid_svm_feature_identification; + rcx = {}; + intrinsic_cpuid(rax.data(), rbx.data(), rcx.data(), rdx.data()); + + if (bsl::unlikely((rdx & cpuid_svm_feature_identification_np).is_zero())) { + bsl::error() << "nested paging not supported\n" << bsl::here(); + return bsl::errc_failure; + } + + /// NOTE: + /// - The next step is to enable nested paging in the VMCB. + /// + + constexpr bsl::safe_uint64 guest_ctls1_idx{bsl::to_u64(0x0090U)}; + constexpr bsl::safe_uint64 guest_ctls1_val{bsl::to_u64(0x1U)}; + + ret = syscall::bf_vps_op_write64(handle, vpsid, guest_ctls1_idx, guest_ctls1_val); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - Before we can set up the nested page tables, we need to set up + /// a page pool. This is needed because not all microkernels will + /// support the free_page() ABI. If we want to change the nested + /// page tables, or make new ones and then release them when we are + /// done, etc, we will need the ability to free a page so that we + /// can use it again. To do this we create our own page pool. + /// Whenever we allocate a page, if the page pool is empty, it will + /// as the microkernel for a page. When memory is freed, it puts + /// the freed page into our page pool so that we can use it the next + /// time an allocation occurs. + /// - Note that this approach is basically how malloc/free engines + /// work when you write your own application for Windows/Linux. + /// The allocation engine asks the kernel for memory (usually it + /// asks for heap memory, but that is not a requirement), and then + /// it provides this memory when you run malloc(). We are doing the + /// samething here, but with page granularity. + /// - It should also be noted that the microkernel does provide a + /// heap if you want to use it, but in this case we really do want + /// page allocation as you cannot do virtual address to physical + /// address conversions for memory that was allocated on the heap. + /// + + if (syscall::bf_tls_ppid(handle) == bsl::ZERO_U16) { + ret = g_page_pool.initialize(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + /// NOTE: + /// - The next step is to initialize and set up the nested page + /// tables. One issue with this is you need to know how much + /// physical memory to map in. You could determine how much + /// physical address space you will need, or you could use on-demand + /// paging. You could also fill the entire physical address space + /// (up to the MAX value provided by CPUID), but how much memory + /// you need to allocate for the page tables to make that work is + /// up to what granularity you use. In this example, we only + /// provide 2M granularity, so this approach is likely a bad idea. + /// - Also note that what we are creating here is what we call an + /// identify map. Basically, each guest physical address is mapped + /// to the same system physical address. This is needed (usually) + /// for the root OS. If you plan to create your own guest VMs, + /// you will need a different mapping scheme. + /// - By default, we map in 512 GB of memory. Again, this is likely + /// not safe, but is good enough for an example. + /// + + constexpr bsl::safe_uint64 page_size_2m{bsl::to_umax(0x200000U)}; + constexpr bsl::safe_uint64 max_physical_mem{bsl::to_umax(0x8000000000U)}; + + if (syscall::bf_tls_ppid(handle) == bsl::ZERO_U16) { + ret = g_npt.initialize(&g_page_pool); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + for (bsl::safe_uintmax gpa{}; gpa < max_physical_mem; gpa += page_size_2m) { + ret = g_npt.map_2m_page(gpa, gpa, MAP_PAGE_RWE, MEMORY_TYPE_WB); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + } + else { + bsl::touch(); + } + + /// NOTE: + /// - Finally, we need to set N_CR3 in the VMCB so that the CPU + /// knows where to find our nested page tables. + /// + + constexpr bsl::safe_uint64 guest_n_cr3_idx{bsl::to_u64(0x00B0U)}; + + ret = syscall::bf_vps_op_write64(handle, vpsid, guest_n_cr3_idx, g_npt.phys()); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } +} + +#endif diff --git a/example/nested_paging/x64/amd/nested_page_table_t.hpp b/example/nested_paging/x64/amd/nested_page_table_t.hpp new file mode 100644 index 00000000..53221780 --- /dev/null +++ b/example/nested_paging/x64/amd/nested_page_table_t.hpp @@ -0,0 +1,863 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef NESTED_PAGE_TABLE_T_HPP +#define NESTED_PAGE_TABLE_T_HPP + +#include "npdpt_t.hpp" +#include "npdpte_t.hpp" +#include "npdt_t.hpp" +#include "npdte_t.hpp" +#include "npml4t_t.hpp" +#include "npml4te_t.hpp" +#include "npt_t.hpp" +#include "npte_t.hpp" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::nested_page_table_t + /// + /// + /// @brief Implements the nested pages tables used by the extension + /// for mapping guest physical memory. + /// + class nested_page_table_t final + { + /// @brief stores true if initialized() has been executed + bool m_initialized{}; + /// @brief stores a reference to the page pool to use + page_pool_t *m_page_pool{}; + /// @brief stores a pointer to the npml4t + npml4t_t *m_npml4t{}; + /// @brief stores the physical address of the npml4t + bsl::safe_uintmax m_npml4t_phys{bsl::safe_uintmax::failure()}; + /// @brief safe guards operations on the NPT. + mutable spinlock m_npt_lock{}; + + /// + /// @brief Returns the nested page-map level-4 (NPML4T) offset given + /// a guest physical address. + /// + /// + /// @param gpa the guest physical address to get the NPML4T offset from. + /// @return the NPML4T offset from the guest physical address + /// + [[nodiscard]] static constexpr auto + npml4to(bsl::safe_uintmax const &gpa) noexcept -> bsl::safe_uintmax + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + constexpr bsl::safe_uintmax shift{bsl::to_umax(39)}; + return (gpa >> shift) & mask; + } + + /// + /// @brief Adds a npdpt_t to the provided npml4te_t. + /// + /// + /// @param npml4te the npml4te_t to add a npdpt_t too + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + add_npdpt(npml4te_t *const npml4te) noexcept -> bsl::errc_type + { + auto const *const table{m_page_pool->template allocate()}; + if (bsl::unlikely(nullptr == table)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const table_phys{m_page_pool->virt_to_phys(table)}; + if (bsl::unlikely(!table_phys)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + npml4te->phys = (table_phys >> bsl::to_umax(HYPERVISOR_PAGE_SHIFT)).get(); + npml4te->p = bsl::ONE_UMAX.get(); + npml4te->rw = bsl::ONE_UMAX.get(); + npml4te->us = bsl::ONE_UMAX.get(); + + return bsl::errc_success; + } + + /// + /// @brief Adds a npdpt_t to the provided npml4te_t. + /// + /// + /// @param npml4te the npml4te_t to add a npdpt_t too + /// + constexpr void + remove_npdpt(npml4te_t *const npml4te) noexcept + { + for (auto const elem : get_npdpt(npml4te)->entries) { + if (elem.data->p != bsl::ZERO_UMAX) { + this->remove_npdt(elem.data); + } + else { + bsl::touch(); + } + } + + m_page_pool->deallocate(get_npdpt(npml4te)); + } + + /// + /// @brief Returns the npdpt_t associated with the provided + /// npml4te_t. + /// + /// + /// @param npml4te the npml4te_t to get the npdpt_t from + /// @return A pointer to the requested npdpt_t + /// + [[nodiscard]] constexpr auto + get_npdpt(npml4te_t *const npml4te) noexcept -> npdpt_t * + { + bsl::safe_uintmax entry_phys{npml4te->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the npdpt_t associated with the provided + /// npml4te_t. + /// + /// + /// @param npml4te the npml4te_t to get the npdpt_t from + /// @return A pointer to the requested npdpt_t + /// + [[nodiscard]] constexpr auto + get_npdpt(npml4te_t const *const npml4te) const noexcept -> npdpt_t const * + { + bsl::safe_uintmax entry_phys{npml4te->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the nested page-directory-pointer table (NPDPT) + /// offset given a guest physical address. + /// + /// + /// @param gpa the guest physical address to get the NPDPT offset from. + /// @return the NPDPT offset from the guest physical address + /// + [[nodiscard]] static constexpr auto + npdpto(bsl::safe_uintmax const &gpa) noexcept -> bsl::safe_uintmax + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + constexpr bsl::safe_uintmax shift{bsl::to_umax(30)}; + return (gpa >> shift) & mask; + } + + /// + /// @brief Adds a npdt_t to the provided npdpte_t. + /// + /// + /// @param npdpte the npdpte_t to add a npdt_t too + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + add_npdt(npdpte_t *const npdpte) noexcept -> bsl::errc_type + { + auto const *const table{m_page_pool->template allocate()}; + if (bsl::unlikely(nullptr == table)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const table_phys{m_page_pool->virt_to_phys(table)}; + if (bsl::unlikely(!table_phys)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + npdpte->phys = (table_phys >> bsl::to_umax(HYPERVISOR_PAGE_SHIFT)).get(); + npdpte->p = bsl::ONE_UMAX.get(); + npdpte->rw = bsl::ONE_UMAX.get(); + npdpte->us = bsl::ONE_UMAX.get(); + + return bsl::errc_success; + } + + /// + /// @brief Adds a npdt_t to the provided npdpte_t. + /// + /// + /// @param npdpte the npdpte_t to add a npdt_t too + /// + constexpr void + remove_npdt(npdpte_t *const npdpte) noexcept + { + for (auto const elem : get_npdt(npdpte)->entries) { + if (elem.data->p != bsl::ZERO_UMAX) { + this->remove_npt(elem.data); + } + else { + bsl::touch(); + } + } + + m_page_pool->deallocate(get_npdt(npdpte)); + } + + /// + /// @brief Returns the npdt_t associated with the provided + /// npdpte_t. + /// + /// + /// @param npdpte the npdpte_t to get the npdt_t from + /// @return A pointer to the requested npdt_t + /// + [[nodiscard]] constexpr auto + get_npdt(npdpte_t *const npdpte) noexcept -> npdt_t * + { + bsl::safe_uintmax entry_phys{npdpte->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the npdt_t associated with the provided + /// npdpte_t. + /// + /// + /// @param npdpte the npdpte_t to get the npdt_t from + /// @return A pointer to the requested npdt_t + /// + [[nodiscard]] constexpr auto + get_npdt(npdpte_t const *const npdpte) const noexcept -> npdt_t const * + { + bsl::safe_uintmax entry_phys{npdpte->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the nested page-directory table (NPDT) offset + /// given a guest physical address. + /// + /// + /// @param gpa the guest physical address to get the NPDT offset from. + /// @return the NPDT offset from the guest physical address. + /// + [[nodiscard]] static constexpr auto + npdto(bsl::safe_uintmax const &gpa) noexcept -> bsl::safe_uintmax + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + constexpr bsl::safe_uintmax shift{bsl::to_umax(21)}; + return (gpa >> shift) & mask; + } + + /// + /// @brief Adds a npt_t to the provided npdte_t. + /// + /// + /// @param npdte the npdte_t to add a npt_t too + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + add_npt(npdte_t *const npdte) noexcept -> bsl::errc_type + { + auto const *const table{m_page_pool->template allocate()}; + if (bsl::unlikely(nullptr == table)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const table_phys{m_page_pool->virt_to_phys(table)}; + if (bsl::unlikely(!table_phys)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + npdte->phys = (table_phys >> bsl::to_umax(HYPERVISOR_PAGE_SHIFT)).get(); + npdte->p = bsl::ONE_UMAX.get(); + npdte->rw = bsl::ONE_UMAX.get(); + npdte->us = bsl::ONE_UMAX.get(); + + return bsl::errc_success; + } + + /// + /// @brief Adds a npt_t to the provided npdte_t. + /// + /// + /// @param npdte the npdte_t to add a npt_t too + /// + constexpr void + remove_npt(npdte_t *const npdte) noexcept + { + m_page_pool->deallocate(get_npt(npdte)); + } + + /// + /// @brief Returns the npt_t associated with the provided + /// npdte_t. + /// + /// + /// @param npdte the npdte_t to get the npt_t from + /// @return A pointer to the requested npt_t + /// + [[nodiscard]] constexpr auto + get_npt(npdte_t *const npdte) noexcept -> npt_t * + { + bsl::safe_uintmax entry_phys{npdte->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the npt_t associated with the provided + /// npdte_t. + /// + /// + /// @param npdte the npdte_t to get the npt_t from + /// @return A pointer to the requested npt_t + /// + [[nodiscard]] constexpr auto + get_npt(npdte_t const *const npdte) const noexcept -> npt_t const * + { + bsl::safe_uintmax entry_phys{npdte->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the page-table (NPT) offset given a + /// guest physical address. + /// + /// + /// @param gpa the guest physical address to get the NPT offset from. + /// @return the NPT offset from the guest physical address + /// + [[nodiscard]] static constexpr auto + npto(bsl::safe_uintmax const &gpa) noexcept -> bsl::safe_uintmax + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + constexpr bsl::safe_uintmax shift{bsl::to_umax(12)}; + return (gpa >> shift) & mask; + } + + /// + /// @brief Returns true if the provided address is page aligned + /// + /// + /// @param addr the address to query + /// @return Returns true if the provided address is page aligned + /// + [[nodiscard]] static constexpr auto + is_page_aligned(bsl::safe_uintmax const &addr) noexcept -> bool + { + return (addr & (bsl::to_umax(HYPERVISOR_PAGE_SIZE) - bsl::ONE_UMAX)) == bsl::ZERO_UMAX; + } + + /// + /// @brief Releases the memory allocated in this root page table + /// + constexpr void + auto_release() noexcept + { + if (bsl::unlikely(nullptr == m_npml4t)) { + return; + } + + if (bsl::unlikely(nullptr == m_page_pool)) { + return; + } + + for (auto const elem : m_npml4t->entries) { + if (elem.data->p == bsl::ZERO_UMAX) { + continue; + } + + this->remove_npdpt(elem.data); + } + + m_page_pool->deallocate(m_npml4t); + m_npml4t = {}; + m_npml4t_phys = bsl::safe_uintmax::failure(); + } + + public: + /// + /// @brief Initializes this nested_page_table_t + /// + /// + /// @param page_pool the page pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize(page_pool_t *const page_pool) noexcept -> bsl::errc_type + { + if (bsl::unlikely(m_initialized)) { + bsl::error() << "nested_page_table_t already initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + bsl::finally release_on_error{[this]() noexcept -> void { + this->release(); + }}; + + m_page_pool = page_pool; + if (bsl::unlikely(nullptr == page_pool)) { + bsl::error() << "invalid page_pool\n" << bsl::here(); + return bsl::errc_failure; + } + + m_npml4t = m_page_pool->template allocate(); + if (bsl::unlikely(nullptr == m_npml4t)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + m_npml4t_phys = m_page_pool->virt_to_phys(m_npml4t); + if (bsl::unlikely(!m_npml4t_phys)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + release_on_error.ignore(); + m_initialized = true; + + return bsl::errc_success; + } + + /// + /// @brief Releases the memory allocated in this nested page tables + /// + constexpr void + release() noexcept + { + this->auto_release(); + + m_page_pool = {}; + m_initialized = false; + } + + /// + /// @brief Returns the physical address of the PML4 + /// + /// + /// @return Returns the physical address of the PML4 + /// + [[nodiscard]] constexpr auto + phys() const noexcept -> bsl::safe_uintmax const & + { + return m_npml4t_phys; + } + + /// + /// @brief Maps a 4k page into the nested page tables being managed + /// by this class. + /// + /// + /// @param page_gpa the guest physical address to map the system + /// physical address to + /// @param page_spa the system physical address to map. + /// @param page_flags defines how memory should be mapped + /// @param page_type defines the memory type for the mapping + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + map_4k_page( + bsl::safe_uintmax const &page_gpa, + bsl::safe_uintmax const &page_spa, + bsl::safe_uintmax const &page_flags, + bsl::safe_uintmax const &page_type) noexcept -> bsl::errc_type + { + lock_guard lock{m_npt_lock}; + + if (bsl::unlikely(!m_initialized)) { + bsl::error() << "nested_page_table_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_gpa)) { + bsl::error() << "guest physical address is invalid: " // -- + << bsl::hex(page_gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_aligned(page_gpa))) { + bsl::error() << "guest physical address is not page aligned: " // -- + << bsl::hex(page_gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_spa)) { + bsl::error() << "system physical address is invalid: " // -- + << bsl::hex(page_spa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_aligned(page_spa))) { + bsl::error() << "system physical address is not page aligned: " // -- + << bsl::hex(page_spa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_flags)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_type)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_type) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(page_type == MEMORY_TYPE_WC)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(page_type == MEMORY_TYPE_WT)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(page_type == MEMORY_TYPE_WP)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + auto *const npml4te{m_npml4t->entries.at_if(this->npml4to(page_gpa))}; + if (npml4te->p == bsl::ZERO_UMAX) { + if (bsl::unlikely(!this->add_npdpt(npml4te))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + auto *const npdpt{this->get_npdpt(npml4te)}; + auto *const npdpte{npdpt->entries.at_if(this->npdpto(page_gpa))}; + if (npdpte->p == bsl::ZERO_UMAX) { + if (bsl::unlikely(!this->add_npdt(npdpte))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + auto *const npdt{this->get_npdt(npdpte)}; + auto *const npdte{npdt->entries.at_if(this->npdto(page_gpa))}; + if (npdte->p == bsl::ZERO_UMAX) { + if (bsl::unlikely(!this->add_npt(npdte))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + auto *const npt{this->get_npt(npdte)}; + auto *const npte{npt->entries.at_if(this->npto(page_gpa))}; + if (bsl::unlikely(npte->p != bsl::ZERO_UMAX)) { + bsl::error() << "guest physical address " // -- + << bsl::hex(page_gpa) // -- + << " already mapped" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + npte->phys = (page_spa >> bsl::to_umax(HYPERVISOR_PAGE_SHIFT)).get(); + npte->p = bsl::ONE_UMAX.get(); + npte->us = bsl::ONE_UMAX.get(); + + if (!(page_flags & MAP_PAGE_WRITE).is_zero()) { + npte->rw = bsl::ONE_UMAX.get(); + } + else { + npte->rw = bsl::ZERO_UMAX.get(); + } + + if (!(page_flags & MAP_PAGE_EXECUTE).is_zero()) { + npte->nx = bsl::ZERO_UMAX.get(); + } + else { + npte->nx = bsl::ONE_UMAX.get(); + } + + if (page_type == MEMORY_TYPE_UC) { + npte->pwt = bsl::ONE_UMAX.get(); + npte->pcd = bsl::ONE_UMAX.get(); + } + else { + bsl::touch(); + } + + return bsl::errc_success; + } + + /// + /// @brief Maps a 2m page into the nested page tables being managed + /// by this class. + /// + /// + /// @param page_gpa the guest physical address to map the system + /// physical address to + /// @param page_spa the system physical address to map. + /// @param page_flags defines how memory should be mapped + /// @param page_type defines the memory type for the mapping + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + map_2m_page( + bsl::safe_uintmax const &page_gpa, + bsl::safe_uintmax const &page_spa, + bsl::safe_uintmax const &page_flags, + bsl::safe_uintmax const &page_type) noexcept -> bsl::errc_type + { + lock_guard lock{m_npt_lock}; + + if (bsl::unlikely(!m_initialized)) { + bsl::error() << "nested_page_table_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_gpa)) { + bsl::error() << "guest physical address is invalid: " // -- + << bsl::hex(page_gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_aligned(page_gpa))) { + bsl::error() << "guest physical address is not page aligned: " // -- + << bsl::hex(page_gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_spa)) { + bsl::error() << "system physical address is invalid: " // -- + << bsl::hex(page_spa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_aligned(page_spa))) { + bsl::error() << "system physical address is not page aligned: " // -- + << bsl::hex(page_spa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_flags)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_type)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_type) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(page_type == MEMORY_TYPE_WC)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(page_type == MEMORY_TYPE_WT)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(page_type == MEMORY_TYPE_WP)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + auto *const npml4te{m_npml4t->entries.at_if(this->npml4to(page_gpa))}; + if (npml4te->p == bsl::ZERO_UMAX) { + if (bsl::unlikely(!this->add_npdpt(npml4te))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + auto *const npdpt{this->get_npdpt(npml4te)}; + auto *const npdpte{npdpt->entries.at_if(this->npdpto(page_gpa))}; + if (npdpte->p == bsl::ZERO_UMAX) { + if (bsl::unlikely(!this->add_npdt(npdpte))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + auto *const npdt{this->get_npdt(npdpte)}; + auto *const npdte{npdt->entries.at_if(this->npdto(page_gpa))}; + if (bsl::unlikely(npdte->p != bsl::ZERO_UMAX)) { + bsl::error() << "guest physical address " // -- + << bsl::hex(page_gpa) // -- + << " already mapped" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + npdte->phys = (page_spa >> bsl::to_umax(HYPERVISOR_PAGE_SHIFT)).get(); + npdte->p = bsl::ONE_UMAX.get(); + npdte->us = bsl::ONE_UMAX.get(); + npdte->ps = bsl::ONE_UMAX.get(); + + if (!(page_flags & MAP_PAGE_WRITE).is_zero()) { + npdte->rw = bsl::ONE_UMAX.get(); + } + else { + npdte->rw = bsl::ZERO_UMAX.get(); + } + + if (!(page_flags & MAP_PAGE_EXECUTE).is_zero()) { + npdte->nx = bsl::ZERO_UMAX.get(); + } + else { + npdte->nx = bsl::ONE_UMAX.get(); + } + + if (page_type == MEMORY_TYPE_UC) { + npdte->pwt = bsl::ONE_UMAX.get(); + npdte->pcd = bsl::ONE_UMAX.get(); + } + else { + bsl::touch(); + } + + return bsl::errc_success; + } + }; +} + +#endif diff --git a/example/nested_paging/x64/amd/npdpt_t.hpp b/example/nested_paging/x64/amd/npdpt_t.hpp new file mode 100644 index 00000000..397b7bda --- /dev/null +++ b/example/nested_paging/x64/amd/npdpt_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef NPDPT_T_HPP +#define NPDPT_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @brief defined the expected size of the npdpt_t struct + constexpr bsl::safe_uintmax NUM_NPDPT_ENTRIES{bsl::to_umax(512)}; + + /// @struct example::npdpt_t + /// + /// + /// @brief Defines the layout of a page-directory-pionter table (npdpt). + /// + struct npdpt_t final + { + /// @brief stores the entires in the table + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/amd/npdpte_t.hpp b/example/nested_paging/x64/amd/npdpte_t.hpp new file mode 100644 index 00000000..16e4c003 --- /dev/null +++ b/example/nested_paging/x64/amd/npdpte_t.hpp @@ -0,0 +1,75 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef NPDPTE_T_HPP +#define NPDPTE_T_HPP + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @struct example::npdpte_t + /// + /// + /// @brief Defines the layout of a nested page-directory-pointer table + /// entry (NPDPTE). + /// + struct npdpte_t final + { + /// @brief defines the "present" field in the page + bsl::uint64 p : static_cast(1); + /// @brief defines the "read/write" field in the page + bsl::uint64 rw : static_cast(1); + /// @brief defines the "user/supervisor" field in the page + bsl::uint64 us : static_cast(1); + /// @brief defines the "page-level writethrough" field in the page + bsl::uint64 pwt : static_cast(1); + /// @brief defines the "page-level cache disable" field in the page + bsl::uint64 pcd : static_cast(1); + /// @brief defines the "accessed" field in the page + bsl::uint64 a : static_cast(1); + /// @brief defines the "dirty" field in the page (ignored) + bsl::uint64 d : static_cast(1); + /// @brief defines the "page size" field in the page (must be 0) + bsl::uint64 ps : static_cast(1); + /// @brief defines the "global" field in the page (must be 0) + bsl::uint64 g : static_cast(1); + /// @brief defines the "available to software" field in the page + bsl::uint64 available1 : static_cast(3); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(40); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(11); + /// @brief defines the "no-execute" field in the page + bsl::uint64 nx : static_cast(1); + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/amd/npdt_t.hpp b/example/nested_paging/x64/amd/npdt_t.hpp new file mode 100644 index 00000000..a020d295 --- /dev/null +++ b/example/nested_paging/x64/amd/npdt_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef NPDT_T_HPP +#define NPDT_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @brief defined the expected size of the npdt_t struct + constexpr bsl::safe_uintmax NUM_NPDT_ENTRIES{bsl::to_umax(512)}; + + /// @struct example::npdt_t + /// + /// + /// @brief Defines the layout of a page-directory table (npdt). + /// + struct npdt_t final + { + /// @brief stores the entires in the table + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/amd/npdte_t.hpp b/example/nested_paging/x64/amd/npdte_t.hpp new file mode 100644 index 00000000..6bd53a27 --- /dev/null +++ b/example/nested_paging/x64/amd/npdte_t.hpp @@ -0,0 +1,75 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef NPDTE_T_HPP +#define NPDTE_T_HPP + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @struct example::npdte_t + /// + /// + /// @brief Defines the layout of a nested page-directory table entry + /// (NPDTE). + /// + struct npdte_t final + { + /// @brief defines the "present" field in the page + bsl::uint64 p : static_cast(1); + /// @brief defines the "read/write" field in the page + bsl::uint64 rw : static_cast(1); + /// @brief defines the "user/supervisor" field in the page + bsl::uint64 us : static_cast(1); + /// @brief defines the "page-level writethrough" field in the page + bsl::uint64 pwt : static_cast(1); + /// @brief defines the "page-level cache disable" field in the page + bsl::uint64 pcd : static_cast(1); + /// @brief defines the "accessed" field in the page + bsl::uint64 a : static_cast(1); + /// @brief defines the "dirty" field in the page (ignored) + bsl::uint64 d : static_cast(1); + /// @brief defines the "page size" field in the page (must be 0) + bsl::uint64 ps : static_cast(1); + /// @brief defines the "global" field in the page (must be 0) + bsl::uint64 g : static_cast(1); + /// @brief defines the "available to software" field in the page + bsl::uint64 available1 : static_cast(3); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(40); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(11); + /// @brief defines the "no-execute" field in the page + bsl::uint64 nx : static_cast(1); + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/amd/npml4t_t.hpp b/example/nested_paging/x64/amd/npml4t_t.hpp new file mode 100644 index 00000000..989a6ba4 --- /dev/null +++ b/example/nested_paging/x64/amd/npml4t_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef NPML4T_T_HPP +#define NPML4T_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @brief defined the expected size of the npml4t_t struct + constexpr bsl::safe_uintmax NUM_NPML4T_ENTRIES{bsl::to_umax(512)}; + + /// @struct example::npml4t_t + /// + /// + /// @brief Defines the layout of a page-map level-4 table (pml4). + /// + struct npml4t_t final + { + /// @brief stores the entires in the table + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/amd/npml4te_t.hpp b/example/nested_paging/x64/amd/npml4te_t.hpp new file mode 100644 index 00000000..2026666f --- /dev/null +++ b/example/nested_paging/x64/amd/npml4te_t.hpp @@ -0,0 +1,75 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef NPML4TE_T_HPP +#define NPML4TE_T_HPP + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @struct example::npml4te_t + /// + /// + /// @brief Defines the layout of a nested page-map level-4 table entry + /// (NPML4TE). + /// + struct npml4te_t final + { + /// @brief defines the "present" field in the page + bsl::uint64 p : static_cast(1); + /// @brief defines the "read/write" field in the page + bsl::uint64 rw : static_cast(1); + /// @brief defines the "user/supervisor" field in the page + bsl::uint64 us : static_cast(1); + /// @brief defines the "page-level writethrough" field in the page + bsl::uint64 pwt : static_cast(1); + /// @brief defines the "page-level cache disable" field in the page + bsl::uint64 pcd : static_cast(1); + /// @brief defines the "accessed" field in the page + bsl::uint64 a : static_cast(1); + /// @brief defines the "dirty" field in the page (ignored) + bsl::uint64 ignored : static_cast(1); + /// @brief defines the "page size" field in the page (must be 0) + bsl::uint64 mbz1 : static_cast(1); + /// @brief defines the "global" field in the page (must be 0) + bsl::uint64 mbz2 : static_cast(1); + /// @brief defines the "available to software" field in the page + bsl::uint64 available1 : static_cast(3); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(40); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(11); + /// @brief defines the "no-execute" field in the page + bsl::uint64 nx : static_cast(1); + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/amd/npt_t.hpp b/example/nested_paging/x64/amd/npt_t.hpp new file mode 100644 index 00000000..44216b36 --- /dev/null +++ b/example/nested_paging/x64/amd/npt_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef NPT_T_HPP +#define NPT_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @brief defined the expected size of the npt_t struct + constexpr bsl::safe_uintmax NUM_NPT_ENTRIES{bsl::to_umax(512)}; + + /// @struct example::npt_t + /// + /// + /// @brief Defines the layout of a page table (npt). + /// + struct npt_t final + { + /// @brief stores the entires in the table + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/amd/npte_t.hpp b/example/nested_paging/x64/amd/npte_t.hpp new file mode 100644 index 00000000..be3ab0d6 --- /dev/null +++ b/example/nested_paging/x64/amd/npte_t.hpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef NPTE_T_HPP +#define NPTE_T_HPP + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @struct example::npte_t + /// + /// @brief Defines the layout of a nested page table entry (NPTE). + /// + struct npte_t final + { + /// @brief defines the "present" field in the page + bsl::uint64 p : static_cast(1); + /// @brief defines the "read/write" field in the page + bsl::uint64 rw : static_cast(1); + /// @brief defines the "user/supervisor" field in the page + bsl::uint64 us : static_cast(1); + /// @brief defines the "page-level writethrough" field in the page + bsl::uint64 pwt : static_cast(1); + /// @brief defines the "page-level cache disable" field in the page + bsl::uint64 pcd : static_cast(1); + /// @brief defines the "accessed" field in the page + bsl::uint64 a : static_cast(1); + /// @brief defines the "dirty" field in the page (ignored) + bsl::uint64 d : static_cast(1); + /// @brief defines the "page size" field in the page (must be 0) + bsl::uint64 ps : static_cast(1); + /// @brief defines the "global" field in the page (must be 0) + bsl::uint64 g : static_cast(1); + /// @brief defines the "available to software" field in the page + bsl::uint64 available1 : static_cast(3); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(40); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(11); + /// @brief defines the "no-execute" field in the page + bsl::uint64 nx : static_cast(1); + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/default/x64/common_arch_support.hpp b/example/nested_paging/x64/common_arch_support.hpp similarity index 72% rename from example/default/x64/common_arch_support.hpp rename to example/nested_paging/x64/common_arch_support.hpp index 03aa37d3..9289f9fa 100644 --- a/example/default/x64/common_arch_support.hpp +++ b/example/nested_paging/x64/common_arch_support.hpp @@ -25,6 +25,8 @@ #ifndef COMMON_ARCH_SUPPORT_HPP #define COMMON_ARCH_SUPPORT_HPP +#include "intrinsic_cpuid.hpp" + #include #include @@ -34,41 +36,25 @@ #include #include #include -#include +#include namespace example { - /// - /// @brief Executes the CPUID instruction given the provided EAX and ECX - /// and returns the results - /// - /// - /// @param rax the index used by CPUID, returns resulting rax - /// @param rbx returns resulting rbx - /// @param rcx the subindex used by CPUID, returns the resulting rcx - /// @param rdx returns resulting rdx - /// - extern "C" void intrinsic_cpuid( - bsl::uint64 *const rax, - bsl::uint64 *const rbx, - bsl::uint64 *const rcx, - bsl::uint64 *const rdx) noexcept; - /// /// @brief Handle CPUID VMExits /// /// - /// @tparam HANDLE_CONCEPT the type of handle to use /// @param handle the handle to use /// @param vpsid the ID of the VPS that caused the VMExit /// @return Returns bsl::errc_success on success and bsl::errc_failure /// on failure. /// - template - [[nodiscard]] constexpr auto - handle_vmexit_cpuid(HANDLE_CONCEPT &handle, bsl::safe_uint16 const &vpsid) noexcept + [[nodiscard]] inline auto + handle_vmexit_cpuid(syscall::bf_handle_t &handle, bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type { + bsl::errc_type ret{}; + bsl::safe_uintmax rax{syscall::bf_tls_rax(handle)}; bsl::safe_uintmax rbx{syscall::bf_tls_rbx(handle)}; bsl::safe_uintmax rcx{syscall::bf_tls_rcx(handle)}; @@ -96,32 +82,43 @@ namespace example syscall::bf_tls_set_rax(handle, bsl::ZERO_UMAX); - auto const status{syscall::bf_vps_op_advance_ip(handle, vpsid)}; - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_advance_ip(handle, vpsid); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - syscall::bf_vps_op_promote(handle, vpsid); - return bsl::errc_failure; + ret = syscall::bf_vps_op_promote(handle, vpsid); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + // Unreachable + return bsl::errc_success; } case loader::CPUID_COMMAND_ECX_REPORT_ON.get(): { - bsl::debug() << "host os is" // -- - << bsl::bold_green // -- - << " now " // -- - << bsl::reset_color // -- - << "in a vm\n"; // -- + bsl::debug() << bsl::rst << "host os is" // -- + << bsl::grn << " now " // -- + << bsl::rst << "in a vm (nested_paging example)\n"; // -- + + if (vpsid + bsl::ONE_U16 == syscall::bf_tls_online_pps(handle)) { + bsl::print() << bsl::endl; + syscall::bf_debug_op_dump_page_pool(); + bsl::print() << bsl::endl; + } + else { + bsl::touch(); + } return bsl::errc_success; } case loader::CPUID_COMMAND_ECX_REPORT_OFF.get(): { - bsl::debug() << "host os is" // -- - << bsl::bold_red // -- - << " not " // -- - << bsl::reset_color // -- - << "in a vm\n"; // -- + bsl::debug() << bsl::rst << "host os is" // -- + << bsl::red << " not " // -- + << bsl::rst << "in a vm\n"; // -- return bsl::errc_success; } diff --git a/example/default/x64/intel/arch_support.hpp b/example/nested_paging/x64/intel/arch_support.hpp similarity index 54% rename from example/default/x64/intel/arch_support.hpp rename to example/nested_paging/x64/intel/arch_support.hpp index 41072075..e39d525c 100644 --- a/example/default/x64/intel/arch_support.hpp +++ b/example/nested_paging/x64/intel/arch_support.hpp @@ -26,7 +26,11 @@ #define ARCH_SUPPORT_HPP #include +#include +#include #include +#include +#include #include #include @@ -38,23 +42,28 @@ namespace example { /// @brief stores the MSR bitmap used by this extension - inline void const *g_msr_bitmaps{}; + constinit inline void *g_msr_bitmaps{}; /// @brief stores the physical address of the MSR bitmap - inline bsl::safe_uintmax g_msr_bitmaps_phys{}; + constinit inline bsl::safe_uintmax g_msr_bitmaps_phys{}; + + /// @brief stores the page pool to use for page allocation + constinit inline page_pool_t g_page_pool{}; + /// @brief stores the mtrrs used to create EPT + constinit inline mtrrs_t g_mtrrs{}; + /// @brief stores the extended page tables + constinit inline extended_page_table_t g_ept{}; /// /// @brief Handle NMIs. This is required by Intel. /// /// - /// @tparam HANDLE_CONCEPT the type of handle to use /// @param handle the handle to use /// @param vpsid the ID of the VPS that caused the VMExit /// @return Returns bsl::errc_success on success and bsl::errc_failure /// on failure. /// - template [[nodiscard]] constexpr auto - handle_vmexit_nmi(HANDLE_CONCEPT &handle, bsl::safe_uint16 const &vpsid) noexcept + handle_vmexit_nmi(syscall::bf_handle_t &handle, bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type { /// NOTE: @@ -70,39 +79,37 @@ namespace example constexpr bsl::safe_uintmax vmcs_procbased_ctls_idx{bsl::to_umax(0x4002U)}; constexpr bsl::safe_uint32 vmcs_set_nmi_window_exiting{bsl::to_u32(0x400000U)}; - bsl::safe_uint32 val; - syscall::bf_status_t status{}; + bsl::errc_type ret{}; + bsl::safe_uint32 val{}; - status = syscall::bf_vps_op_read32(handle, vpsid, vmcs_procbased_ctls_idx, val); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_read32(handle, vpsid, vmcs_procbased_ctls_idx, val); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } val |= vmcs_set_nmi_window_exiting; - status = syscall::bf_vps_op_write32(handle, vpsid, vmcs_procbased_ctls_idx, val); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_write32(handle, vpsid, vmcs_procbased_ctls_idx, val); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - return bsl::errc_success; + return ret; } /// /// @brief Handle NMIs Windows /// /// - /// @tparam HANDLE_CONCEPT the type of handle to use /// @param handle the handle to use /// @param vpsid the ID of the VPS that caused the VMExit /// @return Returns bsl::errc_success on success and bsl::errc_failure /// on failure. /// - template [[nodiscard]] constexpr auto - handle_vmexit_nmi_window(HANDLE_CONCEPT &handle, bsl::safe_uint16 const &vpsid) noexcept + handle_vmexit_nmi_window(syscall::bf_handle_t &handle, bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type { /// NOTE: @@ -118,21 +125,21 @@ namespace example constexpr bsl::safe_uintmax vmcs_procbased_ctls_idx{bsl::to_umax(0x4002U)}; constexpr bsl::safe_uint32 vmcs_clear_nmi_window_exiting{bsl::to_u32(0xFFBFFFFFU)}; - bsl::safe_uint32 val; - syscall::bf_status_t status{}; + bsl::errc_type ret{}; + bsl::safe_uint32 val{}; - status = syscall::bf_vps_op_read32(handle, vpsid, vmcs_procbased_ctls_idx, val); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_read32(handle, vpsid, vmcs_procbased_ctls_idx, val); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } val &= vmcs_clear_nmi_window_exiting; - status = syscall::bf_vps_op_write32(handle, vpsid, vmcs_procbased_ctls_idx, val); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_write32(handle, vpsid, vmcs_procbased_ctls_idx, val); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } /// NOTE: @@ -145,36 +152,34 @@ namespace example constexpr bsl::safe_uintmax vmcs_entry_interrupt_info_idx{bsl::to_umax(0x4016U)}; constexpr bsl::safe_uint32 vmcs_entry_interrupt_info_val{bsl::to_u32(0x80000202U)}; - status = syscall::bf_vps_op_write32( + ret = syscall::bf_vps_op_write32( handle, vpsid, vmcs_entry_interrupt_info_idx, vmcs_entry_interrupt_info_val); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - return bsl::errc_success; + return ret; } /// /// @brief Implements the architecture specific VMExit handler. /// /// - /// @tparam HANDLE_CONCEPT the type of handle to use /// @param handle the handle to use /// @param vpsid the ID of the VPS that generated the VMExit /// @param exit_reason the exit reason associated with the VMExit /// - template constexpr void vmexit( - HANDLE_CONCEPT &handle, + syscall::bf_handle_t &handle, bsl::safe_uint16 const &vpsid, bsl::safe_uint64 const &exit_reason) noexcept { bsl::errc_type ret{}; - constexpr bsl::safe_uintmax EXIT_REASON_NMI{bsl::to_umax(0x0)}; - constexpr bsl::safe_uintmax EXIT_REASON_NMI_WINDOW{bsl::to_umax(0x8)}; - constexpr bsl::safe_uintmax EXIT_REASON_CPUID{bsl::to_umax(0xA)}; + constexpr bsl::safe_uintmax exit_reason_nmi{bsl::to_umax(0x0)}; + constexpr bsl::safe_uintmax exit_reason_nmi_window{bsl::to_umax(0x8)}; + constexpr bsl::safe_uintmax exit_reason_cpuid{bsl::to_umax(0xA)}; /// NOTE: /// - At a minimum, we need to handle CPUID and NMIs on Intel. Note @@ -186,7 +191,7 @@ namespace example /// switch (exit_reason.get()) { - case EXIT_REASON_NMI.get(): { + case exit_reason_nmi.get(): { ret = handle_vmexit_nmi(handle, vpsid); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); @@ -198,7 +203,7 @@ namespace example return; } - case EXIT_REASON_NMI_WINDOW.get(): { + case exit_reason_nmi_window.get(): { ret = handle_vmexit_nmi_window(handle, vpsid); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); @@ -210,7 +215,7 @@ namespace example return; } - case EXIT_REASON_CPUID.get(): { + case exit_reason_cpuid.get(): { ret = handle_vmexit_cpuid(handle, vpsid); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); @@ -227,27 +232,45 @@ namespace example } } + syscall::bf_debug_op_dump_vps(vpsid); + bsl::error() << "unknown exit_reason: " // -- << bsl::hex(exit_reason) // -- << bsl::endl // -- << bsl::here(); // -- } + /// + /// @brief Returns the controls as their masked versions using the + /// conversion rules defined in the Intel Manual for determining + /// which controls must be enabled, and which controls are not + /// allowed to be enabled. + /// + /// + /// @param val the control to mask + /// @return Returns the masked version of the control + /// + [[nodiscard]] constexpr auto + mask_enabled_and_disabled(bsl::safe_uintmax const &val) noexcept -> bsl::safe_uint32 + { + constexpr bsl::safe_uintmax ctls_mask{bsl::to_umax(0x00000000FFFFFFFFU)}; + constexpr bsl::safe_uintmax ctls_shift{bsl::to_umax(32)}; + return bsl::to_u32_unsafe((val & ctls_mask) & (val >> ctls_shift)); + }; + /// /// @brief Initializes a VPS with architecture specific stuff. /// /// - /// @tparam HANDLE_CONCEPT the type of handle to use /// @param handle the handle to use /// @param vpsid the VPS being intialized /// @return Returns bsl::errc_success on success and bsl::errc_failure /// on failure. /// - template [[nodiscard]] constexpr auto - init_vps(HANDLE_CONCEPT &handle, bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + init_vps(syscall::bf_handle_t &handle, bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type { - syscall::bf_status_t status{}; + bsl::errc_type ret{}; /// NOTE: /// - Set up VPID @@ -256,10 +279,10 @@ namespace example constexpr bsl::safe_uintmax vmcs_vpid_idx{bsl::to_umax(0x0000U)}; constexpr bsl::safe_uint16 vmcs_vpid_val{bsl::to_u16(0x1)}; - status = syscall::bf_vps_op_write16(handle, vpsid, vmcs_vpid_idx, vmcs_vpid_val); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_write16(handle, vpsid, vmcs_vpid_idx, vmcs_vpid_val); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } /// NOTE: @@ -269,10 +292,10 @@ namespace example constexpr bsl::safe_uintmax vmcs_link_ptr_idx{bsl::to_umax(0x2800U)}; constexpr bsl::safe_uintmax vmcs_link_ptr_val{bsl::to_umax(0xFFFFFFFFFFFFFFFFU)}; - status = syscall::bf_vps_op_write64(handle, vpsid, vmcs_link_ptr_idx, vmcs_link_ptr_val); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_write64(handle, vpsid, vmcs_link_ptr_idx, vmcs_link_ptr_val); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } /// NOTE: @@ -312,26 +335,21 @@ namespace example bsl::safe_uintmax ctls{}; - auto mask = [](bsl::safe_uintmax const &val) noexcept -> bsl::safe_uint32 { - constexpr bsl::safe_uintmax ctls_mask{bsl::to_umax(0x00000000FFFFFFFFU)}; - constexpr bsl::safe_uintmax ctls_shift{bsl::to_umax(32)}; - return bsl::to_u32_unsafe((val & ctls_mask) & (val >> ctls_shift)); - }; - /// NOTE: /// - Configure the pin based controls /// - status = syscall::bf_intrinsic_op_read_msr(handle, ia32_vmx_true_pinbased_ctls, ctls); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_intrinsic_op_rdmsr(handle, ia32_vmx_true_pinbased_ctls, ctls); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - status = syscall::bf_vps_op_write32(handle, vpsid, vmcs_pinbased_ctls_idx, mask(ctls)); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_write32( + handle, vpsid, vmcs_pinbased_ctls_idx, mask_enabled_and_disabled(ctls)); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } /// NOTE: @@ -341,51 +359,54 @@ namespace example constexpr bsl::safe_uintmax enable_msr_bitmaps{bsl::to_umax(0x10000000U)}; constexpr bsl::safe_uintmax enable_procbased_ctls2{bsl::to_umax(0x80000000U)}; - status = syscall::bf_intrinsic_op_read_msr(handle, ia32_vmx_true_procbased_ctls, ctls); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_intrinsic_op_rdmsr(handle, ia32_vmx_true_procbased_ctls, ctls); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } ctls |= enable_msr_bitmaps; ctls |= enable_procbased_ctls2; - status = syscall::bf_vps_op_write32(handle, vpsid, vmcs_procbased_ctls_idx, mask(ctls)); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_write32( + handle, vpsid, vmcs_procbased_ctls_idx, mask_enabled_and_disabled(ctls)); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } /// NOTE: /// - Configure the exit controls /// - status = syscall::bf_intrinsic_op_read_msr(handle, ia32_vmx_true_exit_ctls, ctls); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_intrinsic_op_rdmsr(handle, ia32_vmx_true_exit_ctls, ctls); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - status = syscall::bf_vps_op_write32(handle, vpsid, vmcs_exit_ctls_idx, mask(ctls)); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_write32( + handle, vpsid, vmcs_exit_ctls_idx, mask_enabled_and_disabled(ctls)); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } /// NOTE: /// - Configure the entry controls /// - status = syscall::bf_intrinsic_op_read_msr(handle, ia32_vmx_true_entry_ctls, ctls); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_intrinsic_op_rdmsr(handle, ia32_vmx_true_entry_ctls, ctls); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - status = syscall::bf_vps_op_write32(handle, vpsid, vmcs_entry_ctls_idx, mask(ctls)); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_write32( + handle, vpsid, vmcs_entry_ctls_idx, mask_enabled_and_disabled(ctls)); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } /// NOTE: @@ -397,11 +418,12 @@ namespace example constexpr bsl::safe_uintmax enable_invpcid{bsl::to_umax(0x00001000U)}; constexpr bsl::safe_uintmax enable_xsave{bsl::to_umax(0x00100000U)}; constexpr bsl::safe_uintmax enable_uwait{bsl::to_umax(0x04000000U)}; + constexpr bsl::safe_uintmax enable_ept{bsl::to_umax(0x00000002U)}; - status = syscall::bf_intrinsic_op_read_msr(handle, ia32_vmx_true_procbased_ctls2, ctls); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_intrinsic_op_rdmsr(handle, ia32_vmx_true_procbased_ctls2, ctls); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } ctls |= enable_vpid; @@ -409,11 +431,13 @@ namespace example ctls |= enable_invpcid; ctls |= enable_xsave; ctls |= enable_uwait; + ctls |= enable_ept; - status = syscall::bf_vps_op_write32(handle, vpsid, vmcs_procbased_ctls2_idx, mask(ctls)); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_write32( + handle, vpsid, vmcs_procbased_ctls2_idx, mask_enabled_and_disabled(ctls)); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } /// NOTE: @@ -426,27 +450,150 @@ namespace example constexpr bsl::safe_uintmax vmcs_msr_bitmaps{bsl::to_umax(0x2004U)}; if (nullptr == g_msr_bitmaps) { - status = syscall::bf_mem_op_alloc_page(handle, g_msr_bitmaps, g_msr_bitmaps_phys); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_mem_op_alloc_page(handle, g_msr_bitmaps, g_msr_bitmaps_phys); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); + } + else { + bsl::touch(); } - status = syscall::bf_vps_op_write64(handle, vpsid, vmcs_msr_bitmaps, g_msr_bitmaps_phys); - if (bsl::unlikely(status != syscall::BF_STATUS_SUCCESS)) { + ret = syscall::bf_vps_op_write64(handle, vpsid, vmcs_msr_bitmaps, g_msr_bitmaps_phys); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); + return ret; + } + + /// NOTE: + /// - The first step in setting up EPT is to determine + /// if we have support for it. We do this on each physical processor + /// we are being started on, but likely you could just do this + /// check on the first physical processor and be done. + /// - To determine if we have support for EPT, we need to check to see + /// if attempting to enable EPT above worked. This can be done by + /// checking to see if EPT was actually enabled. + /// + + ret = syscall::bf_vps_op_read64(handle, vpsid, vmcs_procbased_ctls2_idx, ctls); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + if ((ctls & (~enable_ept)).is_zero()) { + bsl::error() << "EPT not supported\n" << bsl::here(); return bsl::errc_failure; } /// NOTE: - /// - Report success. Specifically, when we return to the root OS, - /// setting RAX tells the loader that the hypervisor was successfully - /// set up. + /// - Before we can set up the extended page tables, we need to set up + /// a page pool. This is needed because not all microkernels will + /// support the free_page() ABI. If we want to change the extended + /// page tables, or make new ones and then release them when we are + /// done, etc, we will need the ability to free a page so that we + /// can use it again. To do this we create our own page pool. + /// Whenever we allocate a page, if the page pool is empty, it will + /// as the microkernel for a page. When memory is freed, it puts + /// the freed page into our page pool so that we can use it the next + /// time an allocation occurs. + /// - Note that this approach is basically how malloc/free engines + /// work when you write your own application for Windows/Linux. + /// The allocation engine asks the kernel for memory (usually it + /// asks for heap memory, but that is not a requirement), and then + /// it provides this memory when you run malloc(). We are doing the + /// samething here, but with page granularity. + /// - It should also be noted that the microkernel does provide a + /// heap if you want to use it, but in this case we really do want + /// page allocation as you cannot do virtual address to physical + /// address conversions for memory that was allocated on the heap. /// - syscall::bf_tls_set_rax(handle, bsl::ZERO_UMAX); - return bsl::errc_success; + if (syscall::bf_tls_ppid(handle) == bsl::ZERO_U16) { + ret = g_page_pool.initialize(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + /// NOTE: + /// - The next step is to initialize and set up the nested page + /// tables. One issue with this is you need to know how much + /// physical memory to map in. You could determine how much + /// physical address space you will need, or you could use on-demand + /// paging. You could also fill the entire physical address space + /// (up to the MAX value provided by CPUID), but how much memory + /// you need to allocate for the page tables to make that work is + /// up to what granularity you use. In this example, we only + /// provide 2M granularity, so this approach is likely a bad idea. + /// - Also note that what we are creating here is what we call an + /// identify map. Basically, each guest physical address is mapped + /// to the same system physical address. This is needed (usually) + /// for the root OS. If you plan to create your own guest VMs, + /// you will need a different mapping scheme. + /// - By default, we map in 512 GB of memory. Again, this is likely + /// not safe, but is good enough for an example. If the MTRRs report + /// that there is less physical memory than 512GB, we use the value + /// returned by the MTRRs instead. + /// + + constexpr bsl::safe_uint64 max_physical_mem{bsl::to_umax(0x8000000000U)}; + + if (syscall::bf_tls_ppid(handle) == bsl::ZERO_U16) { + ret = g_ept.initialize(&g_page_pool); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + ret = g_mtrrs.parse(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + ret = g_mtrrs.identity_map_2m( + g_ept, bsl::ZERO_UMAX, g_mtrrs.max_phys().min(max_physical_mem), MAP_PAGE_RWE); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + /// NOTE: + /// - Finally, we need to set EPTP in the VMCS so that the CPU + /// knows where to find our extended page tables. + /// - Similar to CR3, we also need to set some bits in the EPTP. + /// In this case we have told the CPU that it has 4 page levels + /// to walk and that the default memory type is WB. + /// + + constexpr bsl::safe_uintmax eptp_fields{bsl::to_umax(0x1EU)}; + constexpr bsl::safe_uintmax vmcs_ept_pointer{bsl::to_umax(0x201AU)}; + + bsl::safe_uintmax eptp{g_ept.phys() | eptp_fields}; + + ret = syscall::bf_vps_op_write64(handle, vpsid, vmcs_ept_pointer, eptp); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; } } diff --git a/example/nested_paging/x64/intel/epdpt_t.hpp b/example/nested_paging/x64/intel/epdpt_t.hpp new file mode 100644 index 00000000..e12296de --- /dev/null +++ b/example/nested_paging/x64/intel/epdpt_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef EPDPT_T_HPP +#define EPDPT_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @brief defined the expected size of the epdpt_t struct + constexpr bsl::safe_uintmax NUM_EPDPT_ENTRIES{bsl::to_umax(512)}; + + /// @struct example::epdpt_t + /// + /// + /// @brief Defines the layout of a page-directory-pionter table (epdpt). + /// + struct epdpt_t final + { + /// @brief stores the entires in the table + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/intel/epdpte_t.hpp b/example/nested_paging/x64/intel/epdpte_t.hpp new file mode 100644 index 00000000..78bd4b47 --- /dev/null +++ b/example/nested_paging/x64/intel/epdpte_t.hpp @@ -0,0 +1,75 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef EPDPTE_T_HPP +#define EPDPTE_T_HPP + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @struct example::epdpte_t + /// + /// + /// @brief Defines the layout of a nested page-directory-pointer table + /// entry (EPDPTE). + /// + struct epdpte_t final + { + /// @brief defines the "read access" field in the page + bsl::uint64 r : static_cast(1); + /// @brief defines the "write access" field in the page + bsl::uint64 w : static_cast(1); + /// @brief defines the "execute access" field in the page + bsl::uint64 e : static_cast(1); + /// @brief defines the "memory type" field in the page + bsl::uint64 type : static_cast(3); + /// @brief defines the "ignore pat" field in the page + bsl::uint64 ignore_pat : static_cast(1); + /// @brief defines the "page size" field in the page + bsl::uint64 ps : static_cast(1); + /// @brief defines the "accessed" field in the page + bsl::uint64 a : static_cast(1); + /// @brief defines the "ignored" field in the page + bsl::uint64 d : static_cast(1); + /// @brief defines the "user execute access" field in the page + bsl::uint64 e_user : static_cast(1); + /// @brief defines the "ignored" field in the page + bsl::uint64 ignored1 : static_cast(1); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(40); + /// @brief defines the "ignored" field in the page + bsl::uint64 ignored2 : static_cast(11); + /// @brief defines the "virtualization exception" field in the page + bsl::uint64 ve : static_cast(1); + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/intel/epdt_t.hpp b/example/nested_paging/x64/intel/epdt_t.hpp new file mode 100644 index 00000000..cc3a9239 --- /dev/null +++ b/example/nested_paging/x64/intel/epdt_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef EPDT_T_HPP +#define EPDT_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @brief defined the expected size of the epdt_t struct + constexpr bsl::safe_uintmax NUM_EPDT_ENTRIES{bsl::to_umax(512)}; + + /// @struct example::epdt_t + /// + /// + /// @brief Defines the layout of a page-directory table (epdt). + /// + struct epdt_t final + { + /// @brief stores the entires in the table + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/intel/epdte_t.hpp b/example/nested_paging/x64/intel/epdte_t.hpp new file mode 100644 index 00000000..103878ca --- /dev/null +++ b/example/nested_paging/x64/intel/epdte_t.hpp @@ -0,0 +1,75 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef EPDTE_T_HPP +#define EPDTE_T_HPP + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @struct example::epdte_t + /// + /// + /// @brief Defines the layout of a nested page-directory table entry + /// (EPDTE). + /// + struct epdte_t final + { + /// @brief defines the "read access" field in the page + bsl::uint64 r : static_cast(1); + /// @brief defines the "write access" field in the page + bsl::uint64 w : static_cast(1); + /// @brief defines the "execute access" field in the page + bsl::uint64 e : static_cast(1); + /// @brief defines the "memory type" field in the page + bsl::uint64 type : static_cast(3); + /// @brief defines the "ignore pat" field in the page + bsl::uint64 ignore_pat : static_cast(1); + /// @brief defines the "page size" field in the page + bsl::uint64 ps : static_cast(1); + /// @brief defines the "accessed" field in the page + bsl::uint64 a : static_cast(1); + /// @brief defines the "ignored" field in the page + bsl::uint64 d : static_cast(1); + /// @brief defines the "user execute access" field in the page + bsl::uint64 e_user : static_cast(1); + /// @brief defines the "ignored" field in the page + bsl::uint64 ignored1 : static_cast(1); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(40); + /// @brief defines the "ignored" field in the page + bsl::uint64 ignored2 : static_cast(11); + /// @brief defines the "virtualization exception" field in the page + bsl::uint64 ve : static_cast(1); + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/intel/epml4t_t.hpp b/example/nested_paging/x64/intel/epml4t_t.hpp new file mode 100644 index 00000000..991dc4df --- /dev/null +++ b/example/nested_paging/x64/intel/epml4t_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef EPML4T_T_HPP +#define EPML4T_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @brief defined the expected size of the epml4t_t struct + constexpr bsl::safe_uintmax NUM_EPML4T_ENTRIES{bsl::to_umax(512)}; + + /// @struct example::epml4t_t + /// + /// + /// @brief Defines the layout of a page-map level-4 table (pml4). + /// + struct epml4t_t final + { + /// @brief stores the entires in the table + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/intel/epml4te_t.hpp b/example/nested_paging/x64/intel/epml4te_t.hpp new file mode 100644 index 00000000..fcc97624 --- /dev/null +++ b/example/nested_paging/x64/intel/epml4te_t.hpp @@ -0,0 +1,69 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef EPML4TE_T_HPP +#define EPML4TE_T_HPP + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @struct example::epml4te_t + /// + /// + /// @brief Defines the layout of a nested page-map level-4 table entry + /// (EPML4TE). + /// + struct epml4te_t final + { + /// @brief defines the "read access" field in the page + bsl::uint64 r : static_cast(1); + /// @brief defines the "write access" field in the page + bsl::uint64 w : static_cast(1); + /// @brief defines the "execute access" field in the page + bsl::uint64 e : static_cast(1); + /// @brief defines the "must be zero" field in the page + bsl::uint64 mbz1 : static_cast(5); + /// @brief defines the "accessed" field in the page + bsl::uint64 a : static_cast(1); + /// @brief defines the "ignored" field in the page + bsl::uint64 ignored1 : static_cast(1); + /// @brief defines the "user execute access" field in the page + bsl::uint64 e_user : static_cast(1); + /// @brief defines the "ignored" field in the page + bsl::uint64 ignored2 : static_cast(1); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(40); + /// @brief defines the "ignored" field in the page + bsl::uint64 ignored3 : static_cast(12); + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/intel/ept_t.hpp b/example/nested_paging/x64/intel/ept_t.hpp new file mode 100644 index 00000000..eb643b6e --- /dev/null +++ b/example/nested_paging/x64/intel/ept_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef EPT_T_HPP +#define EPT_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @brief defined the expected size of the ept_t struct + constexpr bsl::safe_uintmax NUM_EPT_ENTRIES{bsl::to_umax(512)}; + + /// @struct example::ept_t + /// + /// + /// @brief Defines the layout of a page table (ept). + /// + struct ept_t final + { + /// @brief stores the entires in the table + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/intel/epte_t.hpp b/example/nested_paging/x64/intel/epte_t.hpp new file mode 100644 index 00000000..ba4fc3bc --- /dev/null +++ b/example/nested_paging/x64/intel/epte_t.hpp @@ -0,0 +1,77 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef EPTE_T_HPP +#define EPTE_T_HPP + +#include +#include +#include + +#pragma pack(push, 1) + +namespace example +{ + /// @struct example::epte_t + /// + /// @brief Defines the layout of a nested page table entry (EPTE). + /// + struct epte_t final + { + /// @brief defines the "read access" field in the page + bsl::uint64 r : static_cast(1); + /// @brief defines the "write access" field in the page + bsl::uint64 w : static_cast(1); + /// @brief defines the "execute access" field in the page + bsl::uint64 e : static_cast(1); + /// @brief defines the "memory type" field in the page + bsl::uint64 type : static_cast(3); + /// @brief defines the "ignore pat" field in the page + bsl::uint64 ignore_pat : static_cast(1); + /// @brief defines the "ignored" field in the page + bsl::uint64 ignored1 : static_cast(1); + /// @brief defines the "accessed" field in the page + bsl::uint64 a : static_cast(1); + /// @brief defines the "ignored" field in the page + bsl::uint64 d : static_cast(1); + /// @brief defines the "user execute access" field in the page + bsl::uint64 e_user : static_cast(1); + /// @brief defines the "ignored" field in the page + bsl::uint64 ignored2 : static_cast(1); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(40); + /// @brief defines the "ignored" field in the page + bsl::uint64 ignored3 : static_cast(9); + /// @brief defines the "sub page write permissions" field in the page + bsl::uint64 sub : static_cast(1); + /// @brief defines the "ignored" field in the page + bsl::uint64 ignored4 : static_cast(1); + /// @brief defines the "virtualization exception" field in the page + bsl::uint64 ve : static_cast(1); + }; +} + +#pragma pack(pop) + +#endif diff --git a/example/nested_paging/x64/intel/extended_page_table_t.hpp b/example/nested_paging/x64/intel/extended_page_table_t.hpp new file mode 100644 index 00000000..4f05ebb8 --- /dev/null +++ b/example/nested_paging/x64/intel/extended_page_table_t.hpp @@ -0,0 +1,793 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef EXTENDED_PAGE_TABLE_T_HPP +#define EXTENDED_PAGE_TABLE_T_HPP + +#include "epdpt_t.hpp" +#include "epdpte_t.hpp" +#include "epdt_t.hpp" +#include "epdte_t.hpp" +#include "epml4t_t.hpp" +#include "epml4te_t.hpp" +#include "ept_t.hpp" +#include "epte_t.hpp" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::extended_page_table_t + /// + /// + /// @brief Implements the extended pages tables used by the extension + /// for mapping guest physical memory. + /// + class extended_page_table_t final + { + /// @brief stores true if initialized() has been executed + bool m_initialized{}; + /// @brief stores a reference to the page pool to use + page_pool_t *m_page_pool{}; + /// @brief stores a pointer to the epml4t + epml4t_t *m_epml4t{}; + /// @brief stores the physical address of the epml4t + bsl::safe_uintmax m_epml4t_phys{bsl::safe_uintmax::failure()}; + /// @brief safe guards operations on the NPT. + mutable spinlock m_ept_lock{}; + + /// + /// @brief Returns the extended page-map level-4 (NPML4T) offset given + /// a guest physical address. + /// + /// + /// @param gpa the guest physical address to get the NPML4T offset from. + /// @return the NPML4T offset from the guest physical address + /// + [[nodiscard]] static constexpr auto + epml4to(bsl::safe_uintmax const &gpa) noexcept -> bsl::safe_uintmax + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + constexpr bsl::safe_uintmax shift{bsl::to_umax(39)}; + return (gpa >> shift) & mask; + } + + /// + /// @brief Adds a epdpt_t to the provided epml4te_t. + /// + /// + /// @param epml4te the epml4te_t to add a epdpt_t too + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + add_epdpt(epml4te_t *const epml4te) noexcept -> bsl::errc_type + { + auto const *const table{m_page_pool->template allocate()}; + if (bsl::unlikely(nullptr == table)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const table_phys{m_page_pool->virt_to_phys(table)}; + if (bsl::unlikely(!table_phys)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + epml4te->phys = (table_phys >> bsl::to_umax(HYPERVISOR_PAGE_SHIFT)).get(); + epml4te->r = bsl::ONE_UMAX.get(); + epml4te->w = bsl::ONE_UMAX.get(); + epml4te->e = bsl::ONE_UMAX.get(); + + return bsl::errc_success; + } + + /// + /// @brief Adds a epdpt_t to the provided epml4te_t. + /// + /// + /// @param epml4te the epml4te_t to add a epdpt_t too + /// + constexpr void + remove_epdpt(epml4te_t *const epml4te) noexcept + { + for (auto const elem : get_epdpt(epml4te)->entries) { + if (elem.data->r != bsl::ZERO_UMAX) { + this->remove_epdt(elem.data); + } + else { + bsl::touch(); + } + } + + m_page_pool->deallocate(get_epdpt(epml4te)); + } + + /// + /// @brief Returns the epdpt_t associated with the provided + /// epml4te_t. + /// + /// + /// @param epml4te the epml4te_t to get the epdpt_t from + /// @return A pointer to the requested epdpt_t + /// + [[nodiscard]] constexpr auto + get_epdpt(epml4te_t *const epml4te) noexcept -> epdpt_t * + { + bsl::safe_uintmax entry_phys{epml4te->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the epdpt_t associated with the provided + /// epml4te_t. + /// + /// + /// @param epml4te the epml4te_t to get the epdpt_t from + /// @return A pointer to the requested epdpt_t + /// + [[nodiscard]] constexpr auto + get_epdpt(epml4te_t const *const epml4te) const noexcept -> epdpt_t const * + { + bsl::safe_uintmax entry_phys{epml4te->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the extended page-directory-pointer table (NPDPT) + /// offset given a guest physical address. + /// + /// + /// @param gpa the guest physical address to get the NPDPT offset from. + /// @return the NPDPT offset from the guest physical address + /// + [[nodiscard]] static constexpr auto + epdpto(bsl::safe_uintmax const &gpa) noexcept -> bsl::safe_uintmax + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + constexpr bsl::safe_uintmax shift{bsl::to_umax(30)}; + return (gpa >> shift) & mask; + } + + /// + /// @brief Adds a epdt_t to the provided epdpte_t. + /// + /// + /// @param epdpte the epdpte_t to add a epdt_t too + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + add_epdt(epdpte_t *const epdpte) noexcept -> bsl::errc_type + { + auto const *const table{m_page_pool->template allocate()}; + if (bsl::unlikely(nullptr == table)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const table_phys{m_page_pool->virt_to_phys(table)}; + if (bsl::unlikely(!table_phys)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + epdpte->phys = (table_phys >> bsl::to_umax(HYPERVISOR_PAGE_SHIFT)).get(); + epdpte->r = bsl::ONE_UMAX.get(); + epdpte->w = bsl::ONE_UMAX.get(); + epdpte->e = bsl::ONE_UMAX.get(); + + return bsl::errc_success; + } + + /// + /// @brief Adds a epdt_t to the provided epdpte_t. + /// + /// + /// @param epdpte the epdpte_t to add a epdt_t too + /// + constexpr void + remove_epdt(epdpte_t *const epdpte) noexcept + { + for (auto const elem : get_epdt(epdpte)->entries) { + if (elem.data->r != bsl::ZERO_UMAX) { + this->remove_ept(elem.data); + } + else { + bsl::touch(); + } + } + + m_page_pool->deallocate(get_epdt(epdpte)); + } + + /// + /// @brief Returns the epdt_t associated with the provided + /// epdpte_t. + /// + /// + /// @param epdpte the epdpte_t to get the epdt_t from + /// @return A pointer to the requested epdt_t + /// + [[nodiscard]] constexpr auto + get_epdt(epdpte_t *const epdpte) noexcept -> epdt_t * + { + bsl::safe_uintmax entry_phys{epdpte->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the epdt_t associated with the provided + /// epdpte_t. + /// + /// + /// @param epdpte the epdpte_t to get the epdt_t from + /// @return A pointer to the requested epdt_t + /// + [[nodiscard]] constexpr auto + get_epdt(epdpte_t const *const epdpte) const noexcept -> epdt_t const * + { + bsl::safe_uintmax entry_phys{epdpte->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the extended page-directory table (NPDT) offset + /// given a guest physical address. + /// + /// + /// @param gpa the guest physical address to get the NPDT offset from. + /// @return the NPDT offset from the guest physical address. + /// + [[nodiscard]] static constexpr auto + epdto(bsl::safe_uintmax const &gpa) noexcept -> bsl::safe_uintmax + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + constexpr bsl::safe_uintmax shift{bsl::to_umax(21)}; + return (gpa >> shift) & mask; + } + + /// + /// @brief Adds a ept_t to the provided epdte_t. + /// + /// + /// @param epdte the epdte_t to add a ept_t too + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + add_ept(epdte_t *const epdte) noexcept -> bsl::errc_type + { + auto const *const table{m_page_pool->template allocate()}; + if (bsl::unlikely(nullptr == table)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const table_phys{m_page_pool->virt_to_phys(table)}; + if (bsl::unlikely(!table_phys)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + epdte->phys = (table_phys >> bsl::to_umax(HYPERVISOR_PAGE_SHIFT)).get(); + epdte->r = bsl::ONE_UMAX.get(); + epdte->w = bsl::ONE_UMAX.get(); + epdte->e = bsl::ONE_UMAX.get(); + + return bsl::errc_success; + } + + /// + /// @brief Adds a ept_t to the provided epdte_t. + /// + /// + /// @param epdte the epdte_t to add a ept_t too + /// + constexpr void + remove_ept(epdte_t *const epdte) noexcept + { + m_page_pool->deallocate(get_ept(epdte)); + } + + /// + /// @brief Returns the ept_t associated with the provided + /// epdte_t. + /// + /// + /// @param epdte the epdte_t to get the ept_t from + /// @return A pointer to the requested ept_t + /// + [[nodiscard]] constexpr auto + get_ept(epdte_t *const epdte) noexcept -> ept_t * + { + bsl::safe_uintmax entry_phys{epdte->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the ept_t associated with the provided + /// epdte_t. + /// + /// + /// @param epdte the epdte_t to get the ept_t from + /// @return A pointer to the requested ept_t + /// + [[nodiscard]] constexpr auto + get_ept(epdte_t const *const epdte) const noexcept -> ept_t const * + { + bsl::safe_uintmax entry_phys{epdte->phys}; + entry_phys <<= bsl::to_umax(HYPERVISOR_PAGE_SHIFT); + + return m_page_pool->template phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the page-table (NPT) offset given a + /// guest physical address. + /// + /// + /// @param gpa the guest physical address to get the NPT offset from. + /// @return the NPT offset from the guest physical address + /// + [[nodiscard]] static constexpr auto + epto(bsl::safe_uintmax const &gpa) noexcept -> bsl::safe_uintmax + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + constexpr bsl::safe_uintmax shift{bsl::to_umax(12)}; + return (gpa >> shift) & mask; + } + + /// + /// @brief Returns true if the provided address is page aligned + /// + /// + /// @param addr the address to query + /// @return Returns true if the provided address is page aligned + /// + [[nodiscard]] static constexpr auto + is_page_aligned(bsl::safe_uintmax const &addr) noexcept -> bool + { + return (addr & (bsl::to_umax(HYPERVISOR_PAGE_SIZE) - bsl::ONE_UMAX)) == bsl::ZERO_UMAX; + } + + /// + /// @brief Releases the memory allocated in this root page table + /// + constexpr void + auto_release() noexcept + { + if (bsl::unlikely(nullptr == m_epml4t)) { + return; + } + + if (bsl::unlikely(nullptr == m_page_pool)) { + return; + } + + for (auto const elem : m_epml4t->entries) { + if (elem.data->r == bsl::ZERO_UMAX) { + continue; + } + + this->remove_epdpt(elem.data); + } + + m_page_pool->deallocate(m_epml4t); + m_epml4t = {}; + m_epml4t_phys = bsl::safe_uintmax::failure(); + } + + public: + /// + /// @brief Initializes this extended_page_table_t + /// + /// + /// @param page_pool the page pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize(page_pool_t *const page_pool) noexcept -> bsl::errc_type + { + if (bsl::unlikely(m_initialized)) { + bsl::error() << "extended_page_table_t already initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + bsl::finally release_on_error{[this]() noexcept -> void { + this->release(); + }}; + + m_page_pool = page_pool; + if (bsl::unlikely(nullptr == page_pool)) { + bsl::error() << "invalid page_pool\n" << bsl::here(); + return bsl::errc_failure; + } + + m_epml4t = m_page_pool->template allocate(); + if (bsl::unlikely(nullptr == m_epml4t)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + m_epml4t_phys = m_page_pool->virt_to_phys(m_epml4t); + if (bsl::unlikely(!m_epml4t_phys)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + release_on_error.ignore(); + m_initialized = true; + + return bsl::errc_success; + } + + /// + /// @brief Releases the memory allocated in this extended page tables + /// + constexpr void + release() noexcept + { + this->auto_release(); + + m_page_pool = {}; + m_initialized = false; + } + + /// + /// @brief Returns the physical address of the PML4 + /// + /// + /// @return Returns the physical address of the PML4 + /// + [[nodiscard]] constexpr auto + phys() const noexcept -> bsl::safe_uintmax const & + { + return m_epml4t_phys; + } + + /// + /// @brief Maps a 4k page into the extended page tables being managed + /// by this class. + /// + /// + /// @param page_gpa the guest physical address to map the system + /// physical address to + /// @param page_spa the system physical address to map. + /// @param page_flags defines how memory should be mapped + /// @param page_type defines the memory type for the mapping + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + map_4k_page( + bsl::safe_uintmax const &page_gpa, + bsl::safe_uintmax const &page_spa, + bsl::safe_uintmax const &page_flags, + bsl::safe_uintmax const &page_type) noexcept -> bsl::errc_type + { + lock_guard lock{m_ept_lock}; + + if (bsl::unlikely(!m_initialized)) { + bsl::error() << "extended_page_table_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_gpa)) { + bsl::error() << "guest physical address is invalid: " // -- + << bsl::hex(page_gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_aligned(page_gpa))) { + bsl::error() << "guest physical address is not page aligned: " // -- + << bsl::hex(page_gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_spa)) { + bsl::error() << "system physical address is invalid: " // -- + << bsl::hex(page_spa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_aligned(page_spa))) { + bsl::error() << "system physical address is not page aligned: " // -- + << bsl::hex(page_spa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_flags)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_type)) { + bsl::error() << "invalid type: " // -- + << bsl::hex(page_type) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + auto *const epml4te{m_epml4t->entries.at_if(this->epml4to(page_gpa))}; + if (epml4te->r == bsl::ZERO_UMAX) { + if (bsl::unlikely(!this->add_epdpt(epml4te))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + auto *const epdpt{this->get_epdpt(epml4te)}; + auto *const epdpte{epdpt->entries.at_if(this->epdpto(page_gpa))}; + if (epdpte->r == bsl::ZERO_UMAX) { + if (bsl::unlikely(!this->add_epdt(epdpte))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + auto *const epdt{this->get_epdt(epdpte)}; + auto *const epdte{epdt->entries.at_if(this->epdto(page_gpa))}; + if (epdte->r == bsl::ZERO_UMAX) { + if (bsl::unlikely(!this->add_ept(epdte))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + auto *const ept{this->get_ept(epdte)}; + auto *const epte{ept->entries.at_if(this->epto(page_gpa))}; + if (bsl::unlikely(epte->r != bsl::ZERO_UMAX)) { + bsl::error() << "guest physical address " // -- + << bsl::hex(page_gpa) // -- + << " already mapped" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + epte->phys = (page_spa >> bsl::to_umax(HYPERVISOR_PAGE_SHIFT)).get(); + epte->r = bsl::ONE_UMAX.get(); + epte->type = page_type.get(); + + if (!(page_flags & MAP_PAGE_WRITE).is_zero()) { + epte->w = bsl::ONE_UMAX.get(); + } + else { + bsl::touch(); + } + + if (!(page_flags & MAP_PAGE_EXECUTE).is_zero()) { + epte->e = bsl::ONE_UMAX.get(); + } + else { + bsl::touch(); + } + + return bsl::errc_success; + } + + /// + /// @brief Maps a 2m page into the extended page tables being managed + /// by this class. + /// + /// + /// @param page_gpa the guest physical address to map the system + /// physical address to + /// @param page_spa the system physical address to map. + /// @param page_flags defines how memory should be mapped + /// @param page_type defines the memory type for the mapping + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + map_2m_page( + bsl::safe_uintmax const &page_gpa, + bsl::safe_uintmax const &page_spa, + bsl::safe_uintmax const &page_flags, + bsl::safe_uintmax const &page_type) noexcept -> bsl::errc_type + { + lock_guard lock{m_ept_lock}; + + if (bsl::unlikely(!m_initialized)) { + bsl::error() << "extended_page_table_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_gpa)) { + bsl::error() << "guest physical address is invalid: " // -- + << bsl::hex(page_gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_aligned(page_gpa))) { + bsl::error() << "guest physical address is not page aligned: " // -- + << bsl::hex(page_gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_spa)) { + bsl::error() << "system physical address is invalid: " // -- + << bsl::hex(page_spa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_aligned(page_spa))) { + bsl::error() << "system physical address is not page aligned: " // -- + << bsl::hex(page_spa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_flags)) { + bsl::error() << "invalid flags: " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!page_type)) { + bsl::error() << "invalid type: " // -- + << bsl::hex(page_type) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + auto *const epml4te{m_epml4t->entries.at_if(this->epml4to(page_gpa))}; + if (epml4te->r == bsl::ZERO_UMAX) { + if (bsl::unlikely(!this->add_epdpt(epml4te))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + auto *const epdpt{this->get_epdpt(epml4te)}; + auto *const epdpte{epdpt->entries.at_if(this->epdpto(page_gpa))}; + if (epdpte->r == bsl::ZERO_UMAX) { + if (bsl::unlikely(!this->add_epdt(epdpte))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + auto *const epdt{this->get_epdt(epdpte)}; + auto *const epdte{epdt->entries.at_if(this->epdto(page_gpa))}; + if (bsl::unlikely(epdte->r != bsl::ZERO_UMAX)) { + bsl::error() << "guest physical address " // -- + << bsl::hex(page_gpa) // -- + << " already mapped" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + epdte->phys = (page_spa >> bsl::to_umax(HYPERVISOR_PAGE_SHIFT)).get(); + epdte->r = bsl::ONE_UMAX.get(); + epdte->type = page_type.get(); + epdte->ps = bsl::ONE_UMAX.get(); + + if (!(page_flags & MAP_PAGE_WRITE).is_zero()) { + epdte->w = bsl::ONE_UMAX.get(); + } + else { + bsl::touch(); + } + + if (!(page_flags & MAP_PAGE_EXECUTE).is_zero()) { + epdte->e = bsl::ONE_UMAX.get(); + } + else { + bsl::touch(); + } + + return bsl::errc_success; + } + }; +} + +#endif diff --git a/example/default/x64/intrinsic_cpuid.S b/example/nested_paging/x64/intrinsic_cpuid.S similarity index 100% rename from example/default/x64/intrinsic_cpuid.S rename to example/nested_paging/x64/intrinsic_cpuid.S diff --git a/example/nested_paging/x64/intrinsic_cpuid.hpp b/example/nested_paging/x64/intrinsic_cpuid.hpp new file mode 100644 index 00000000..8b48fc35 --- /dev/null +++ b/example/nested_paging/x64/intrinsic_cpuid.hpp @@ -0,0 +1,49 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INTRINSIC_CPUID_HPP +#define INTRINSIC_CPUID_HPP + +#include + +namespace example +{ + /// + /// @brief Executes the CPUID instruction given the provided EAX and ECX + /// and returns the results + /// + /// + /// @param rax the index used by CPUID, returns resulting rax + /// @param rbx returns resulting rbx + /// @param rcx the subindex used by CPUID, returns the resulting rcx + /// @param rdx returns resulting rdx + /// + extern "C" void intrinsic_cpuid( + bsl::uint64 *const rax, + bsl::uint64 *const rbx, + bsl::uint64 *const rcx, + bsl::uint64 *const rdx) noexcept; +} + +#endif diff --git a/example/nested_paging/x64/map_page_flags.hpp b/example/nested_paging/x64/map_page_flags.hpp new file mode 100644 index 00000000..f5c88070 --- /dev/null +++ b/example/nested_paging/x64/map_page_flags.hpp @@ -0,0 +1,48 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MAP_PAGE_FLAGS_HPP +#define MAP_PAGE_FLAGS_HPP + +#include +#include + +namespace example +{ + /// @brief Map a page with read permmissions (has no effect) + constexpr bsl::safe_uintmax MAP_PAGE_READ{bsl::to_umax(0x0000000000000001U)}; + /// @brief Map a page with write permmissions + constexpr bsl::safe_uintmax MAP_PAGE_WRITE{bsl::to_umax(0x0000000000000002U)}; + /// @brief Map a page with execute permmissions + constexpr bsl::safe_uintmax MAP_PAGE_EXECUTE{bsl::to_umax(0x0000000000000004U)}; + + /// @brief Map a page with read/execute permmissions + constexpr bsl::safe_uintmax MAP_PAGE_RE{MAP_PAGE_READ | MAP_PAGE_EXECUTE}; + /// @brief Map a page with read/write permmissions + constexpr bsl::safe_uintmax MAP_PAGE_RW{MAP_PAGE_READ | MAP_PAGE_WRITE}; + /// @brief Map a page with read/write/execute permmissions + constexpr bsl::safe_uintmax MAP_PAGE_RWE{MAP_PAGE_READ | MAP_PAGE_WRITE | MAP_PAGE_EXECUTE}; +} + +#endif diff --git a/example/nested_paging/x64/memory_type.hpp b/example/nested_paging/x64/memory_type.hpp new file mode 100644 index 00000000..fd99c747 --- /dev/null +++ b/example/nested_paging/x64/memory_type.hpp @@ -0,0 +1,45 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MEMORY_TYPE_HPP +#define MEMORY_TYPE_HPP + +#include +#include + +namespace example +{ + /// @brief defines the uncacheable memory type + constexpr bsl::safe_uintmax MEMORY_TYPE_UC{bsl::to_umax(0)}; + /// @brief defines the write-combine memory type + constexpr bsl::safe_uintmax MEMORY_TYPE_WC{bsl::to_umax(1)}; + /// @brief defines the write-through memory type + constexpr bsl::safe_uintmax MEMORY_TYPE_WT{bsl::to_umax(4)}; + /// @brief defines the write-protect memory type + constexpr bsl::safe_uintmax MEMORY_TYPE_WP{bsl::to_umax(5)}; + /// @brief defines the write-back memory type + constexpr bsl::safe_uintmax MEMORY_TYPE_WB{bsl::to_umax(6)}; +} + +#endif diff --git a/example/nested_paging/x64/mtrrs_t.hpp b/example/nested_paging/x64/mtrrs_t.hpp new file mode 100644 index 00000000..a4ddb721 --- /dev/null +++ b/example/nested_paging/x64/mtrrs_t.hpp @@ -0,0 +1,1747 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MTRRS_T_HPP +#define MTRRS_T_HPP + +#include "intrinsic_cpuid.hpp" +#include "memory_type.hpp" +#include "range_t.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace example +{ + /// @brief defines the CPUID feature identifier bit for MTRR + constexpr bsl::safe_uintmax MAX_RANGES{bsl::to_umax(512)}; + + /// @brief defines the CPUID feature identifier index + constexpr bsl::safe_uintmax CPUID_FEATURE_IDENTIFIERS{bsl::to_umax(0x00000001U)}; + /// @brief defines the CPUID feature identifier bit for MTRR + constexpr bsl::safe_uintmax CPUID_FEATURE_IDENTIFIERS_MTRR{bsl::to_umax(0x00001000U)}; + + /// @brief defines the CPUID linear/physical address size index + constexpr bsl::safe_uintmax CPUID_LP_ADDRESS_SIZE{bsl::to_umax(0x80000008U)}; + /// @brief defines the CPUID linear/physical address size phys addr bits + constexpr bsl::safe_uintmax CPUID_LP_ADDRESS_SIZE_PHYS_ADDR_BITS{bsl::to_umax(0x000000FFU)}; + + /// @brief defines the MTRRcap MSR + constexpr bsl::safe_uint32 IA32_MTRRCAP{bsl::to_u32(0x000000FEU)}; + /// @brief defines the MTRRcap MSR VCNT field + constexpr bsl::safe_uintmax IA32_MTRRCAP_VCNT{bsl::to_umax(0x00000000000000FFU)}; + /// @brief defines the MTRRcap MSR FIX field + constexpr bsl::safe_uintmax IA32_MTRRCAP_FIX{bsl::to_umax(0x0000000000000100U)}; + + /// @brief defines the MTRRdefType MSR + constexpr bsl::safe_uint32 IA32_MTRRDEFTYPE{bsl::to_u32(0x000002FFU)}; + /// @brief defines the MTRRdefType MSR type field + constexpr bsl::safe_uintmax IA32_MTRRDEFTYPE_TYPE{bsl::to_umax(0x00000000000000FFU)}; + /// @brief defines the MTRRdefType MSR fixed range enable field + constexpr bsl::safe_uintmax IA32_MTRRDEFTYPE_FE{bsl::to_umax(0x0000000000000400U)}; + /// @brief defines the MTRRdefType MSR enable field + constexpr bsl::safe_uintmax IA32_MTRRDEFTYPE_E{bsl::to_umax(0x0000000000000800U)}; + + /// @brief defines the MTRRfix64K_00000 MSR + constexpr bsl::safe_uint32 IA32_MTRRFIX64K_00000{bsl::to_u32(0x000000250U)}; + /// @brief defines the MTRRfix16K_80000 MSR + constexpr bsl::safe_uint32 IA32_MTRRFIX16K_80000{bsl::to_u32(0x000000258U)}; + /// @brief defines the MTRRfix16K_A0000 MSR + constexpr bsl::safe_uint32 IA32_MTRRFIX16K_A0000{bsl::to_u32(0x000000259U)}; + /// @brief defines the MTRRfix4K_C0000 MSR + constexpr bsl::safe_uint32 IA32_MTRRFIX4K_C0000{bsl::to_u32(0x000000268U)}; + /// @brief defines the MTRRfix4K_C8000 MSR + constexpr bsl::safe_uint32 IA32_MTRRFIX4K_C8000{bsl::to_u32(0x000000269U)}; + /// @brief defines the MTRRfix4K_D0000 MSR + constexpr bsl::safe_uint32 IA32_MTRRFIX4K_D0000{bsl::to_u32(0x00000026AU)}; + /// @brief defines the MTRRfix4K_D8000 MSR + constexpr bsl::safe_uint32 IA32_MTRRFIX4K_D8000{bsl::to_u32(0x00000026BU)}; + /// @brief defines the MTRRfix4K_E0000 MSR + constexpr bsl::safe_uint32 IA32_MTRRFIX4K_E0000{bsl::to_u32(0x00000026CU)}; + /// @brief defines the MTRRfix4K_E8000 MSR + constexpr bsl::safe_uint32 IA32_MTRRFIX4K_E8000{bsl::to_u32(0x00000026DU)}; + /// @brief defines the MTRRfix4K_F0000 MSR + constexpr bsl::safe_uint32 IA32_MTRRFIX4K_F0000{bsl::to_u32(0x00000026EU)}; + /// @brief defines the MTRRfix4K_F8000 MSR + constexpr bsl::safe_uint32 IA32_MTRRFIX4K_F8000{bsl::to_u32(0x00000026FU)}; + + /// @brief defines the memory type mask for fixed ranges + constexpr bsl::safe_uintmax MTRR_FIX_MASK{bsl::to_umax(0x00000000000000FFU)}; + /// @brief defines the memory type shift for fixed ranges + constexpr bsl::safe_uintmax MTRR_FIX_SHFT{bsl::to_umax(8)}; + /// @brief defines the total number of MTRRs per MSR for fixed ranges + constexpr bsl::safe_uintmax MTRR_FIX_MTRRS_PER_MSR{bsl::to_umax(8)}; + + /// @brief defines the address of MTRRFIX64K_00000 + constexpr bsl::safe_uintmax MTRRFIX64K_00000_ADDR{bsl::to_umax(0x0000000000000000U)}; + /// @brief defines the size of MTRRFIX64K_00000 + constexpr bsl::safe_uintmax MTRRFIX64K_00000_SIZE{bsl::to_umax(0x10000U)}; + /// @brief defines the address of MTRRFIX16K_80000 + constexpr bsl::safe_uintmax MTRRFIX16K_80000_ADDR{bsl::to_umax(0x0000000000080000U)}; + /// @brief defines the size of MTRRFIX16K_80000 + constexpr bsl::safe_uintmax MTRRFIX16K_80000_SIZE{bsl::to_umax(0x4000U)}; + /// @brief defines the address of MTRRFIX16K_A0000 + constexpr bsl::safe_uintmax MTRRFIX16K_A0000_ADDR{bsl::to_umax(0x00000000000A0000U)}; + /// @brief defines the size of MTRRFIX16K_A0000 + constexpr bsl::safe_uintmax MTRRFIX16K_A0000_SIZE{bsl::to_umax(0x4000U)}; + /// @brief defines the address of MTRRFIX4K_C0000 + constexpr bsl::safe_uintmax MTRRFIX4K_C0000_ADDR{bsl::to_umax(0x00000000000C0000U)}; + /// @brief defines the size of MTRRFIX4K_C0000 + constexpr bsl::safe_uintmax MTRRFIX4K_C0000_SIZE{bsl::to_umax(0x1000U)}; + /// @brief defines the address of MTRRFIX4K_C8000 + constexpr bsl::safe_uintmax MTRRFIX4K_C8000_ADDR{bsl::to_umax(0x00000000000C8000U)}; + /// @brief defines the size of MTRRFIX4K_C8000 + constexpr bsl::safe_uintmax MTRRFIX4K_C8000_SIZE{bsl::to_umax(0x1000U)}; + /// @brief defines the address of MTRRFIX4K_D0000 + constexpr bsl::safe_uintmax MTRRFIX4K_D0000_ADDR{bsl::to_umax(0x00000000000D0000U)}; + /// @brief defines the size of MTRRFIX4K_D0000 + constexpr bsl::safe_uintmax MTRRFIX4K_D0000_SIZE{bsl::to_umax(0x1000U)}; + /// @brief defines the address of MTRRFIX4K_D8000 + constexpr bsl::safe_uintmax MTRRFIX4K_D8000_ADDR{bsl::to_umax(0x00000000000D8000U)}; + /// @brief defines the size of MTRRFIX4K_D8000 + constexpr bsl::safe_uintmax MTRRFIX4K_D8000_SIZE{bsl::to_umax(0x1000U)}; + /// @brief defines the address of MTRRFIX4K_E0000 + constexpr bsl::safe_uintmax MTRRFIX4K_E0000_ADDR{bsl::to_umax(0x00000000000E0000U)}; + /// @brief defines the size of MTRRFIX4K_E0000 + constexpr bsl::safe_uintmax MTRRFIX4K_E0000_SIZE{bsl::to_umax(0x1000U)}; + /// @brief defines the address of MTRRFIX4K_E8000 + constexpr bsl::safe_uintmax MTRRFIX4K_E8000_ADDR{bsl::to_umax(0x00000000000E8000U)}; + /// @brief defines the size of MTRRFIX4K_E8000 + constexpr bsl::safe_uintmax MTRRFIX4K_E8000_SIZE{bsl::to_umax(0x1000U)}; + /// @brief defines the address of MTRRFIX4K_F0000 + constexpr bsl::safe_uintmax MTRRFIX4K_F0000_ADDR{bsl::to_umax(0x00000000000F0000U)}; + /// @brief defines the size of MTRRFIX4K_F0000 + constexpr bsl::safe_uintmax MTRRFIX4K_F0000_SIZE{bsl::to_umax(0x1000U)}; + /// @brief defines the address of MTRRFIX4K_F8000 + constexpr bsl::safe_uintmax MTRRFIX4K_F8000_ADDR{bsl::to_umax(0x00000000000F8000U)}; + /// @brief defines the size of MTRRFIX4K_F8000 + constexpr bsl::safe_uintmax MTRRFIX4K_F8000_SIZE{bsl::to_umax(0x1000U)}; + + /// @brief defines the MTRRphysBase MSR + constexpr bsl::safe_uint32 IA32_MTRRPHYSBASE{bsl::to_u32(0x000000200U)}; + /// @brief defines the MTRRphysMask MSR + constexpr bsl::safe_uint32 IA32_MTRRPHYSMASK{bsl::to_u32(0x000000201U)}; + + /// + /// @brief Implements the sort function that we use for a range_t + /// + /// + /// @param a the first element to compare + /// @param b the second element to compare + /// @return Returns true if a is less b, false otherwise + /// + [[nodiscard]] constexpr auto + range_t_sort_cmp(range_t const &a, range_t const &b) noexcept -> bool + { + if (!a.addr) { + return false; + } + + if (!b.addr) { + return true; + } + + return a.addr < b.addr; + }; + + /// @class example::mtrrs_t + /// + /// + /// @brief Parses the MTRRs and provides a continuous, non-overlapping + /// view of the ranges as needed. + /// + class mtrrs_t final + { + /// @brief stores the ranges associated with this mtrrs_t + bsl::array m_ranges{}; + /// @brief stores the number of ranges in the list. + bsl::safe_uintmax m_ranges_count{}; + + /// + /// @brief Returns true if the provided address is 4k page aligned + /// + /// + /// @param addr the address to query + /// @return Returns true if the provided address is 4k page aligned + /// + [[nodiscard]] static constexpr auto + is_page_4k_aligned(bsl::safe_uintmax const &addr) noexcept -> bool + { + constexpr bsl::safe_uint64 mask_4k{bsl::to_umax(0xFFFU)}; + return (addr & mask_4k) == bsl::ZERO_UMAX; + } + + /// + /// @brief Returns true if the provided address is 2m page aligned + /// + /// + /// @param addr the address to query + /// @return Returns true if the provided address is 2m page aligned + /// + [[nodiscard]] static constexpr auto + is_page_2m_aligned(bsl::safe_uintmax const &addr) noexcept -> bool + { + constexpr bsl::safe_uint64 mask_2m{bsl::to_umax(0x1FFFFFU)}; + return (addr & mask_2m) == bsl::ZERO_UMAX; + } + /// + /// @brief Returns the combination of two memory type based on the + /// memory combining rules defined in the AMD/Intel manuals. + /// + /// + /// @param r1 the first range to combine + /// @param r2 the second range to combine + /// @return Returns the combination of two memory type based on the + /// memory combining rules defined in the AMD/Intel manuals. + /// + [[nodiscard]] static constexpr auto + combine(range_t const &r1, range_t const &r2) noexcept -> bsl::safe_uintmax + { + if (r1.dflt) { + return r2.type; + } + + if (r2.dflt) { + return r1.type; + } + + /// NOTE: + /// - "a. If the memory types are identical, then that memory type + /// is used." + /// + + if (r1.type == r2.type) { + return r1.type; + } + + /// NOTE: + /// - "b. If at least one of the memory types is UC, the UC memory + /// type is used." + /// + + if (r1.type == MEMORY_TYPE_UC) { + return MEMORY_TYPE_UC; + } + + if (r2.type == MEMORY_TYPE_UC) { + return MEMORY_TYPE_UC; + } + + /// NOTE: + /// - "c. If at least one of the memory types is WT, and the only + /// other memory type is WB, then the WT memory type is used" + /// + + if (r1.type == MEMORY_TYPE_WT) { + if (r2.type == MEMORY_TYPE_WB) { + return MEMORY_TYPE_WT; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + if (r2.type == MEMORY_TYPE_WT) { + if (r1.type == MEMORY_TYPE_WB) { + return MEMORY_TYPE_WT; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + /// NOTE: + /// - "d. If the combination of memory types is not listed Steps A + /// through C immediately above, then the memory type used is + /// undefined" + /// + + return MEMORY_TYPE_UC; + } + + /// + /// @brief Adds a range to the list. This version of the function + /// does not attempt to clean up the ranges in the list. It + /// simply adds the range to the list and moves on. + /// + /// + /// @param r the range to add + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_range(range_t const &r) noexcept -> bsl::errc_type + { + auto *const ptr{m_ranges.at_if(m_ranges_count)}; + if (bsl::unlikely(nullptr == ptr)) { + bsl::error() << "mtrrs_t full\n" << bsl::here(); + return bsl::errc_failure; + } + + *ptr = r; + ++m_ranges_count; + + return bsl::errc_success; + } + + /// + /// @brief Adds a range to the list. If the range that is being added + /// is a subset of any other range, or a range is a subset of the + /// range being added, the subsets are split. Any intersecting + /// ranges that are not subsets will cause this function to fail + /// as they are not supported by this algorithm. + /// + /// + /// @param addr the address of the range + /// @param size the size of the range + /// @param type the type of memory in the range + /// type for all of memory, false otherwise + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_range( + bsl::safe_uintmax const &addr, + bsl::safe_uintmax const &size, + bsl::safe_uintmax const &type) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + range_t r1{addr, size, type, false}; + + if (bsl::unlikely(!this->is_page_4k_aligned(addr))) { + bsl::error() << "addr is not 4k page aligned: " // -- + << bsl::hex(addr) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_4k_aligned(size))) { + bsl::error() << "size is not 4k page aligned: " // -- + << bsl::hex(size) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < m_ranges_count; ++i) { + auto *const r2{m_ranges.at_if(i)}; + + auto const r1_l{r1.addr}; + auto const r1_r{r1.addr + r1.size}; + auto const r2_l{r2->addr}; + auto const r2_r{r2->addr + r2->size}; + + /// NOTE: + /// - If the range has a size of 0, there is no range to add + /// and we can stop. This could either happen because we + /// were given a 0 sized range to start, or the range we + /// were overlaps multiple ranges, in which case we have to + /// slowly remove from the provided range until it is 0, and + /// this will stop the loop when it is done. + /// + + if (r1.size.is_zero()) { + break; + } + + /// NOTE: + /// - We need to scan the ranges until we find the first + /// range in the list that the provided range actually + /// intersects. For example: + /// + /// ---------------------------------------- + /// | | | +++++ | + /// | | | + 1 + 2 | + /// | | | +++++ | + /// ---------------------------------------- + /// + /// Until the left side of r1 is greater than or equal to + /// the left side of r2, we can keep scanning because r1 + /// and r2 do not intersect. Note that, you might be + /// thinking about, what if r1's right side overlaps into + /// r2. In this case, it would mean that r1's left side is + /// greater than or equal to the range to the left, which + /// means we have found a match. In other words, we only + /// have to pay attention to the left side, because if + /// the right side is an issue, the left side must also + /// be an issue with the adjacent range, which is really the + /// r2 we should be concerned with. + /// + /// - It should be noted that the above assumes that the + /// entire physical address range is represented by a range. + /// Meaning, there are not wholes. To ensure this, we the + /// first thing we do is fill the range list with the + /// default range that goes from 0 to MAX. From there, this + /// algorithm will perform it's work to add the range, and + /// then sort the list to ensure the list of ranges continues + /// to completely cover the entire physical address range. + /// + + if (!(r1_l < r2_r)) { + continue; + } + + /// NOTE: + /// - Ok, if we got this far, it means that we have found a + /// range that intersects. Now, we need to handle the + /// different types of scenarios that might occur. + /// + + if (r1_l == r2_l) { + + /// Case #1: + /// - In this case, r1's left side is the same as r2's left + /// side, meaning they are touching. When this happens, + /// we need to divide r2 into two ranges. + /// + /// -------------------- + /// | 2 | + /// |+++++ | + /// |+ 1 + | + /// |+++++ | + /// | | + /// -------------------- + /// + /// or + /// + /// -------------------- + /// | 2 | + /// |++++++++++++++++++++++ + /// |+ 1 + + /// |++++++++++++++++++++++ + /// | | + /// -------------------- + /// + + if (r1_r < r2_r) { + auto const new_r1_addr{r1.addr}; + auto const new_r1_size{r1.size}; + auto const new_r1_type{this->combine(r1, *r2)}; + bool const new_r1_dflt{false}; + + ret = this->add_range({new_r1_addr, new_r1_size, new_r1_type, new_r1_dflt}); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const new_r2_addr{r1_r}; + auto const new_r2_size{r2_r - r1_r}; + auto const new_r2_type{r2->type}; + bool const new_r2_dflt{r2->dflt}; + + ret = this->add_range({new_r2_addr, new_r2_size, new_r2_type, new_r2_dflt}); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + r1.addr = bsl::ZERO_UMAX; + r1.size = bsl::ZERO_UMAX; + } + else { + auto const new_r1_addr{r1.addr}; + auto const new_r1_size{r2->size}; + auto const new_r1_type{this->combine(r1, *r2)}; + bool const new_r1_dflt{false}; + + ret = this->add_range({new_r1_addr, new_r1_size, new_r1_type, new_r1_dflt}); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + r1.addr = r2_r; + r1.size = r1_r - r2_r; + } + + r2->addr = bsl::safe_uintmax::failure(); + r2->size = bsl::safe_uintmax::failure(); + r2->type = bsl::safe_uintmax::failure(); + r2->dflt = false; + --m_ranges_count; + + bsl::sort(m_ranges, &range_t_sort_cmp); + } + else { + /// Case #2: + /// - In this case, r1 is inside r1, meaning their left + /// sides are not touching. This will force us to add + /// 2 or 3 ranges depending on the right side of r1. + /// + /// -------------------- + /// | 2 | + /// | +++++ | + /// | + 1 + | + /// | +++++ | + /// | | + /// -------------------- + /// + /// or + /// + /// -------------------- + /// | 2 | + /// | +++++++++++++++++++ + /// | + 1 + + /// | +++++++++++++++++++ + /// | | + /// -------------------- + /// + + if (r1_r < r2_r) { + auto const new_r1_addr{r2->addr}; + auto const new_r1_size{r1_l - r2_l}; + auto const new_r1_type{r2->type}; + bool const new_r1_dflt{r2->dflt}; + + ret = this->add_range({new_r1_addr, new_r1_size, new_r1_type, new_r1_dflt}); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const new_r2_addr{r1.addr}; + auto const new_r2_size{r1.size}; + auto const new_r2_type{this->combine(r1, *r2)}; + bool const new_r2_dflt{false}; + + ret = this->add_range({new_r2_addr, new_r2_size, new_r2_type, new_r2_dflt}); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const new_r3_addr{r1_r}; + auto const new_r3_size{r2_r - r1_r}; + auto const new_r3_type{r2->type}; + bool const new_r3_dflt{r2->dflt}; + + ret = this->add_range({new_r3_addr, new_r3_size, new_r3_type, new_r3_dflt}); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + r1.addr = bsl::ZERO_UMAX; + r1.size = bsl::ZERO_UMAX; + } + else { + auto const new_r1_addr{r2->addr}; + auto const new_r1_size{r1_l - r2_l}; + auto const new_r1_type{r2->type}; + bool const new_r1_dflt{r2->dflt}; + + ret = this->add_range({new_r1_addr, new_r1_size, new_r1_type, new_r1_dflt}); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const new_r2_addr{r1.addr}; + auto const new_r2_size{r2_r - r1_l}; + auto const new_r2_type{this->combine(r1, *r2)}; + bool const new_r2_dflt{false}; + + ret = this->add_range({new_r2_addr, new_r2_size, new_r2_type, new_r2_dflt}); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + r1.addr = r2_r; + r1.size = r1_r - r2_r; + } + + r2->addr = bsl::safe_uintmax::failure(); + r2->size = bsl::safe_uintmax::failure(); + r2->type = bsl::safe_uintmax::failure(); + r2->dflt = false; + --m_ranges_count; + + bsl::sort(m_ranges, &range_t_sort_cmp); + } + } + + return bsl::errc_success; + } + + /// + /// @brief Once all of the ranges have been added, we can compress + /// the range list to reduce the overall size of the list. + /// Compression is simple. If two adjacent ranges have the same + /// type, we can combine them into a single range. Basically this + /// means we need to modify one range to be bigger and remove + /// the other range. Continue this process until we have scanned + /// the entire range list. + /// + /// + /// + constexpr void + compress_ranges() noexcept + { + bsl::safe_uintmax i{bsl::ONE_UMAX}; + + if (m_ranges.size() == bsl::ONE_UMAX) { + return; + } + + while (i < m_ranges_count) { + auto *const r1{m_ranges.at_if(i - bsl::ONE_UMAX)}; + auto *const r2{m_ranges.at_if(i)}; + + if (r1->type == r2->type) { + r1->size += r2->size; + + r2->addr = bsl::safe_uintmax::failure(); + r2->size = bsl::safe_uintmax::failure(); + r2->type = bsl::safe_uintmax::failure(); + r2->dflt = false; + --m_ranges_count; + + bsl::sort(m_ranges, &range_t_sort_cmp); + } + else { + ++i; + } + } + } + + /// + /// @brief Adds the 64k Fixed Range MTRRs starting at 0x00000. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_ia32_mtrr_fix64k_00000(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax mtrr{}; + bsl::safe_uintmax shft{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRFIX64K_00000, mtrr); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < MTRR_FIX_MTRRS_PER_MSR; ++i) { + auto const size{MTRRFIX64K_00000_SIZE}; + auto const addr{MTRRFIX64K_00000_ADDR + (size * i)}; + auto const mask{MTRR_FIX_MASK << shft}; + auto const type{(mtrr & mask) >> shft}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + shft += MTRR_FIX_SHFT; + } + + return bsl::errc_success; + } + + /// + /// @brief Adds the 16k Fixed Range MTRRs starting at 0x80000. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_ia32_mtrr_fix16k_80000(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax mtrr{}; + bsl::safe_uintmax shft{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRFIX16K_80000, mtrr); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < MTRR_FIX_MTRRS_PER_MSR; ++i) { + auto const size{MTRRFIX16K_80000_SIZE}; + auto const addr{MTRRFIX16K_80000_ADDR + (size * i)}; + auto const mask{MTRR_FIX_MASK << shft}; + auto const type{(mtrr & mask) >> shft}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + shft += MTRR_FIX_SHFT; + } + + return bsl::errc_success; + } + + /// + /// @brief Adds the 16k Fixed Range MTRRs starting at 0xA0000. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_ia32_mtrr_fix16k_a0000(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax mtrr{}; + bsl::safe_uintmax shft{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRFIX16K_A0000, mtrr); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < MTRR_FIX_MTRRS_PER_MSR; ++i) { + auto const size{MTRRFIX16K_A0000_SIZE}; + auto const addr{MTRRFIX16K_A0000_ADDR + (size * i)}; + auto const mask{MTRR_FIX_MASK << shft}; + auto const type{(mtrr & mask) >> shft}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + shft += MTRR_FIX_SHFT; + } + + return bsl::errc_success; + } + + /// + /// @brief Adds the 4k Fixed Range MTRRs starting at 0xC0000. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_ia32_mtrr_fix4k_c0000(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax mtrr{}; + bsl::safe_uintmax shft{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRFIX4K_C0000, mtrr); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < MTRR_FIX_MTRRS_PER_MSR; ++i) { + auto const size{MTRRFIX4K_C0000_SIZE}; + auto const addr{MTRRFIX4K_C0000_ADDR + (size * i)}; + auto const mask{MTRR_FIX_MASK << shft}; + auto const type{(mtrr & mask) >> shft}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + shft += MTRR_FIX_SHFT; + } + + return bsl::errc_success; + } + + /// + /// @brief Adds the 4k Fixed Range MTRRs starting at 0xC8000. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_ia32_mtrr_fix4k_c8000(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax mtrr{}; + bsl::safe_uintmax shft{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRFIX4K_C8000, mtrr); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < MTRR_FIX_MTRRS_PER_MSR; ++i) { + auto const size{MTRRFIX4K_C8000_SIZE}; + auto const addr{MTRRFIX4K_C8000_ADDR + (size * i)}; + auto const mask{MTRR_FIX_MASK << shft}; + auto const type{(mtrr & mask) >> shft}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + shft += MTRR_FIX_SHFT; + } + + return bsl::errc_success; + } + + /// + /// @brief Adds the 4k Fixed Range MTRRs starting at 0xD0000. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_ia32_mtrr_fix4k_d0000(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax mtrr{}; + bsl::safe_uintmax shft{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRFIX4K_D0000, mtrr); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < MTRR_FIX_MTRRS_PER_MSR; ++i) { + auto const size{MTRRFIX4K_D0000_SIZE}; + auto const addr{MTRRFIX4K_D0000_ADDR + (size * i)}; + auto const mask{MTRR_FIX_MASK << shft}; + auto const type{(mtrr & mask) >> shft}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + shft += MTRR_FIX_SHFT; + } + + return bsl::errc_success; + } + + /// + /// @brief Adds the 4k Fixed Range MTRRs starting at 0xD8000. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_ia32_mtrr_fix4k_d8000(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax mtrr{}; + bsl::safe_uintmax shft{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRFIX4K_D8000, mtrr); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < MTRR_FIX_MTRRS_PER_MSR; ++i) { + auto const size{MTRRFIX4K_D8000_SIZE}; + auto const addr{MTRRFIX4K_D8000_ADDR + (size * i)}; + auto const mask{MTRR_FIX_MASK << shft}; + auto const type{(mtrr & mask) >> shft}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + shft += MTRR_FIX_SHFT; + } + + return bsl::errc_success; + } + + /// + /// @brief Adds the 4k Fixed Range MTRRs starting at 0xE0000. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_ia32_mtrr_fix4k_e0000(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax mtrr{}; + bsl::safe_uintmax shft{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRFIX4K_E0000, mtrr); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < MTRR_FIX_MTRRS_PER_MSR; ++i) { + auto const size{MTRRFIX4K_E0000_SIZE}; + auto const addr{MTRRFIX4K_E0000_ADDR + (size * i)}; + auto const mask{MTRR_FIX_MASK << shft}; + auto const type{(mtrr & mask) >> shft}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + shft += MTRR_FIX_SHFT; + } + + return bsl::errc_success; + } + + /// + /// @brief Adds the 4k Fixed Range MTRRs starting at 0xE8000. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_ia32_mtrr_fix4k_e8000(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax mtrr{}; + bsl::safe_uintmax shft{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRFIX4K_E8000, mtrr); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < MTRR_FIX_MTRRS_PER_MSR; ++i) { + auto const size{MTRRFIX4K_E8000_SIZE}; + auto const addr{MTRRFIX4K_E8000_ADDR + (size * i)}; + auto const mask{MTRR_FIX_MASK << shft}; + auto const type{(mtrr & mask) >> shft}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + shft += MTRR_FIX_SHFT; + } + + return bsl::errc_success; + } + + /// + /// @brief Adds the 4k Fixed Range MTRRs starting at 0xF0000. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_ia32_mtrr_fix4k_f0000(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax mtrr{}; + bsl::safe_uintmax shft{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRFIX4K_F0000, mtrr); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < MTRR_FIX_MTRRS_PER_MSR; ++i) { + auto const size{MTRRFIX4K_F0000_SIZE}; + auto const addr{MTRRFIX4K_F0000_ADDR + (size * i)}; + auto const mask{MTRR_FIX_MASK << shft}; + auto const type{(mtrr & mask) >> shft}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + shft += MTRR_FIX_SHFT; + } + + return bsl::errc_success; + } + + /// + /// @brief Adds the 4k Fixed Range MTRRs starting at 0xF8000. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_ia32_mtrr_fix4k_f8000(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax mtrr{}; + bsl::safe_uintmax shft{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRFIX4K_F8000, mtrr); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < MTRR_FIX_MTRRS_PER_MSR; ++i) { + auto const size{MTRRFIX4K_F8000_SIZE}; + auto const addr{MTRRFIX4K_F8000_ADDR + (size * i)}; + auto const mask{MTRR_FIX_MASK << shft}; + auto const type{(mtrr & mask) >> shft}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + shft += MTRR_FIX_SHFT; + } + + return bsl::errc_success; + } + + /// + /// @brief Returns the base address portion of physbase + /// + /// + /// @param physbase the physbase to convert + /// @return Returns the base address portion of physbase + /// + [[nodiscard]] static constexpr auto + physbase_to_addr(bsl::safe_uintmax const &physbase) noexcept -> bsl::safe_uintmax + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0xFFFFFFFFFFFFF000U)}; + return physbase & mask; + } + + /// + /// @brief Returns the size portion of physmask using the conversion + /// logic defined in the manual. + /// + /// + /// @param physmask the physmask to convert + /// @param pas the physical address size + /// @return Returns the size portion of physmask using the conversion + /// logic defined in the manual. + /// + [[nodiscard]] static constexpr auto + physmask_to_size( // -- + bsl::safe_uintmax const &physmask, // -- + bsl::safe_uintmax const &pas) noexcept -> bsl::safe_uintmax + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0xFFFFFFFFFFFFF000U)}; + return (~(physmask & mask) & ((bsl::ONE_UMAX << pas) - bsl::ONE_UMAX)) + bsl::ONE_UMAX; + } + + /// + /// @brief Returns the memory type portion of physbase + /// + /// + /// @param physbase the physbase to convert + /// @return Returns the memory type portion of physbase + /// + [[nodiscard]] static constexpr auto + physbase_to_type(bsl::safe_uintmax const &physbase) noexcept -> bsl::safe_uintmax + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0x00000000000000FFU)}; + return physbase & mask; + } + + /// + /// @brief Returns true if the valid bit is set in physmask, + /// false otherwise. + /// + /// + /// @param physmask the physmask to query + /// @return Returns true if the valid bit is set in physmask, + /// false otherwise. + /// + [[nodiscard]] static constexpr auto + physmask_to_valid(bsl::safe_uintmax const &physmask) noexcept -> bool + { + constexpr bsl::safe_uintmax mask{bsl::to_umax(0x0000000000000800U)}; + return (physmask & mask).is_pos(); + } + + /// + /// @brief Parses all of the variable range MTRRs and adds them + /// to the list. + /// + /// + /// @param handle the handle to use + /// @param vcnt the total number of supported variable range MTRRs + /// @param pas the physical address size + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + add_variable_range( + syscall::bf_handle_t &handle, + bsl::safe_uint32 const &vcnt, + bsl::safe_uintmax const &pas) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + bsl::safe_uintmax physbase{}; + bsl::safe_uintmax physmask{}; + + constexpr auto msrs_per_iteration{bsl::to_u32(2)}; + for (bsl::safe_uint32 i{}; i < (vcnt * msrs_per_iteration); i += msrs_per_iteration) { + auto ia32_mtrrphysbasen{IA32_MTRRPHYSBASE + i}; + auto ia32_mtrrphysmaskn{IA32_MTRRPHYSMASK + i}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, ia32_mtrrphysmaskn, physmask); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + if (!this->physmask_to_valid(physmask)) { + continue; + } + + ret = syscall::bf_intrinsic_op_rdmsr(handle, ia32_mtrrphysbasen, physbase); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const addr{this->physbase_to_addr(physbase)}; + auto const size{this->physmask_to_size(physmask, pas)}; + auto const type{this->physbase_to_type(physbase)}; + + ret = this->add_range(addr, size, type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + + return bsl::errc_success; + } + + public: + /// + /// @brief Parses the MTRRs and stores the ranges in a continuous + /// non-overlapping form. This ensures that every single physical + /// address can be looked up by this class and provide the MTRR's + /// opinion as to what the memory's type is. + /// + /// + /// @param handle the handle to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + [[nodiscard]] constexpr auto + parse(syscall::bf_handle_t &handle) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + bsl::safe_uintmax rax{}; + bsl::safe_uintmax rbx{}; + bsl::safe_uintmax rcx{}; + bsl::safe_uintmax rdx{}; + + /// NOTE: + /// - Before we start, we need to ensure that the ranges are + /// cleared and an invalid state. This will ensure that during + /// the sorting process, ranges that are not used are ordered + /// last in the list. + /// + + for (auto const elem : m_ranges) { + *elem.data = { + bsl::safe_uintmax::failure(), + bsl::safe_uintmax::failure(), + bsl::safe_uintmax::failure(), + false}; + } + + m_ranges_count = {}; + + /// NOTE: + /// - The first step is to get the total number of physical address + /// bits the hardware supports. This is needed to convert + /// the variable range registers. + /// + + rax = CPUID_LP_ADDRESS_SIZE; + rcx = {}; + intrinsic_cpuid(rax.data(), rbx.data(), rcx.data(), rdx.data()); + + auto const pas{rax & CPUID_LP_ADDRESS_SIZE_PHYS_ADDR_BITS}; + auto const pas_bytes{bsl::ONE_UMAX << pas}; + + /// NOTE: + /// - The next step is to make sure that MTRRs are supported. + /// If they aren't something really weird is going on, but in + /// general, that is ok as all we have to do is add a single + /// range that marks all of memory as WB. + /// + + rax = CPUID_FEATURE_IDENTIFIERS; + rcx = {}; + intrinsic_cpuid(rax.data(), rbx.data(), rcx.data(), rdx.data()); + + if ((rdx & CPUID_FEATURE_IDENTIFIERS_MTRR).is_zero()) { + ret = this->add_range({bsl::ZERO_UMAX, pas_bytes, MEMORY_TYPE_WB, false}); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// NOTE: + /// - The next step is to get the MTRR information from the MSRs. + /// We have to ask the kernel for this information. + /// + + bsl::safe_uintmax cap{}; + bsl::safe_uintmax deftype{}; + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRCAP, cap); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = syscall::bf_intrinsic_op_rdmsr(handle, IA32_MTRRDEFTYPE, deftype); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const cap_vcnt{bsl::to_u32(cap & IA32_MTRRCAP_VCNT)}; + auto const cap_fix{bsl::to_u32(cap & IA32_MTRRCAP_FIX)}; + + auto const deftype_type{deftype & IA32_MTRRDEFTYPE_TYPE}; + auto const deftype_fe{deftype & IA32_MTRRDEFTYPE_FE}; + auto const deftype_e{deftype & IA32_MTRRDEFTYPE_E}; + + /// NOTE: + /// - If the MTRRs are disabled, the default memory type is + /// uncacheable. + /// + + if (deftype_e.is_zero()) { + ret = this->add_range({bsl::ZERO_UMAX, pas_bytes, MEMORY_TYPE_UC, false}); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// NOTE: + /// - Next we need to add the default range to the list. This sets + /// all of memory to this memory type. All calls to add_range() + /// after this will split this default type up for each memory + /// type defined by BIOS. This ensures that when we are done, + /// every physical memory address has a type defined for it. + /// - It should be noted that the add_range() algorithm expects + /// that this initial range is added for it work properly. + /// + + ret = this->add_range({bsl::ZERO_UMAX, pas_bytes, deftype_type, true}); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + /// NOTE: + /// - Next, let's add the fixed range MTRRs. + /// + + if (cap_fix.is_pos()) { + if (deftype_fe.is_pos()) { + ret = this->add_ia32_mtrr_fix64k_00000(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = this->add_ia32_mtrr_fix16k_80000(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = this->add_ia32_mtrr_fix16k_a0000(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = this->add_ia32_mtrr_fix4k_c0000(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = this->add_ia32_mtrr_fix4k_c8000(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = this->add_ia32_mtrr_fix4k_d0000(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = this->add_ia32_mtrr_fix4k_d8000(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = this->add_ia32_mtrr_fix4k_e0000(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = this->add_ia32_mtrr_fix4k_e8000(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = this->add_ia32_mtrr_fix4k_f0000(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = this->add_ia32_mtrr_fix4k_f8000(handle); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + } + else { + bsl::touch(); + } + + ret = this->add_variable_range(handle, cap_vcnt, pas); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + this->compress_ranges(); + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Creates an identity map in the provided map using the + /// memory types contained in the MTRRs. The resulting identity + /// map will mimic the MTRRs given the range provided + /// + /// + /// @tparam MAP_T the type of map to use + /// @param map the map to create the identity map in + /// @param gpa the starting guest physical address + /// @param size the number of bytes from the provided gpa to map + /// @param flags the read/write/execute flags to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + template + [[nodiscard]] constexpr auto + identity_map_4k( + MAP_T &map, + bsl::safe_uintmax const &gpa, + bsl::safe_uintmax const &size, + bsl::safe_uintmax const &flags) noexcept -> bsl::errc_type + { + constexpr bsl::safe_uint64 page_size_4k{bsl::to_umax(0x001000U)}; + + bsl::errc_type ret{}; + bsl::safe_uintmax crsr{gpa}; + + if (bsl::unlikely(!gpa)) { + bsl::error() << "guest physical address is invalid: " // -- + << bsl::hex(gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_4k_aligned(gpa))) { + bsl::error() << "guest physical address is not 2m page aligned: " // -- + << bsl::hex(gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!size)) { + bsl::error() << "size is invalid: " // -- + << bsl::hex(size) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_4k_aligned(size))) { + bsl::error() << "size is not 2m page aligned: " // -- + << bsl::hex(size) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < m_ranges_count; ++i) { + auto *const range{m_ranges.at_if(i)}; + + if (range->addr + range->size < crsr) { + continue; + } + + while (crsr < range->addr + range->size) { + + if (!(crsr < gpa + size)) { + return bsl::errc_success; + } + + ret = map.map_4k_page(crsr, crsr, flags, range->type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + crsr += page_size_4k; + } + } + + bsl::error() << "identity map is out of bounds" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + /// + /// @brief Creates an identity map in the provided map using the + /// memory types contained in the MTRRs. The resulting identity + /// map will mimic the MTRRs given the range provided + /// + /// + /// @tparam MAP_T the type of map to use + /// @param map the map to create the identity map in + /// @param gpa the starting guest physical address + /// @param size the number of bytes from the provided gpa to map + /// @param flags the read/write/execute flags to use + /// @return Returns bsl::errc_success on success and bsl::errc_failure + /// on failure. + /// + template + [[nodiscard]] constexpr auto + identity_map_2m( + MAP_T &map, + bsl::safe_uintmax const &gpa, + bsl::safe_uintmax const &size, + bsl::safe_uintmax const &flags) noexcept -> bsl::errc_type + { + constexpr bsl::safe_uint64 page_size_4k{bsl::to_umax(0x001000U)}; + constexpr bsl::safe_uint64 page_size_2m{bsl::to_umax(0x200000U)}; + + bsl::errc_type ret{}; + bsl::safe_uintmax crsr{gpa}; + + if (bsl::unlikely(!gpa)) { + bsl::error() << "guest physical address is invalid: " // -- + << bsl::hex(gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_2m_aligned(gpa))) { + bsl::error() << "guest physical address is not 2m page aligned: " // -- + << bsl::hex(gpa) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!size)) { + bsl::error() << "size is invalid: " // -- + << bsl::hex(size) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->is_page_2m_aligned(size))) { + bsl::error() << "size is not 2m page aligned: " // -- + << bsl::hex(size) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + for (bsl::safe_uintmax i{}; i < m_ranges_count; ++i) { + auto *const range{m_ranges.at_if(i)}; + + if (range->addr + range->size < crsr) { + continue; + } + + while (crsr < range->addr + range->size) { + + if (!(crsr < gpa + size)) { + return bsl::errc_success; + } + + if (this->is_page_2m_aligned(crsr)) { + if (!(crsr + page_size_2m > range->addr + range->size)) { + + ret = map.map_2m_page(crsr, crsr, flags, range->type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + crsr += page_size_2m; + continue; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + ret = map.map_4k_page(crsr, crsr, flags, range->type); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + crsr += page_size_4k; + } + } + + if (crsr == gpa + size) { + return bsl::errc_success; + } + + bsl::error() << "identity map is out of bounds" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + /// + /// @brief Returns the max physical address in the MTRRs on success, + /// or bsl::safe_uintmax::failure() on failure. + /// + /// + /// @return Returns the max physical address in the MTRRs on success, + /// or bsl::safe_uintmax::failure() on failure. + /// + [[nodiscard]] constexpr auto + max_phys() noexcept -> bsl::safe_uintmax + { + if (m_ranges_count.is_zero()) { + bsl::error() << "mtrrs has not been parsed yet\n" << bsl::here(); + return bsl::safe_uintmax::failure(); + } + + auto const *const range{m_ranges.at_if(m_ranges_count - bsl::ONE_UMAX)}; + return range->addr + range->size; + } + + /// + /// @brief Outputs the contents of the MTRRs. + /// + constexpr void + dump() const noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + + bsl::print() << bsl::mag << "mtrrs dump: "; + bsl::print() << bsl::rst << bsl::endl; + + /// Header + /// + + bsl::print() << bsl::ylw << "+------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^19s", "start "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^19s", "end "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^5s", "type "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + /// MTRRs + /// + + for (bsl::safe_uintmax i{}; i < m_ranges_count; ++i) { + auto const *rowcolor{bsl::rst}; + auto const *const range{m_ranges.at_if(i)}; + + bsl::safe_uintmax const srt{range->addr}; + bsl::safe_uintmax const end{range->addr + range->size - bsl::ONE_UMAX}; + + if (MEMORY_TYPE_UC == range->type) { + rowcolor = bsl::blk; + } + else { + bsl::touch(); + } + + bsl::print() << bsl::ylw << "| "; + bsl::print() << rowcolor << bsl::hex(srt) << ' '; + bsl::print() << bsl::ylw << "| "; + bsl::print() << rowcolor << bsl::hex(end) << ' '; + bsl::print() << bsl::ylw << "| "; + + switch (range->type.get()) { + case MEMORY_TYPE_WC.get(): { + bsl::print() << rowcolor << bsl::fmt{"^5s", "wc"}; + break; + } + + case MEMORY_TYPE_WP.get(): { + bsl::print() << rowcolor << bsl::fmt{"^5s", "wp"}; + break; + } + + case MEMORY_TYPE_WT.get(): { + bsl::print() << rowcolor << bsl::fmt{"^5s", "wt"}; + break; + } + + case MEMORY_TYPE_WB.get(): { + bsl::print() << rowcolor << bsl::fmt{"^5s", "wb"}; + break; + } + + default: { + bsl::print() << rowcolor << bsl::fmt{"^5s", "uc"}; + break; + } + } + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + } + + /// Footer + /// + + bsl::print() << bsl::ylw << "+------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + } + }; +} + +#endif diff --git a/example/nested_paging/x64/range_t.hpp b/example/nested_paging/x64/range_t.hpp new file mode 100644 index 00000000..8d6db5b0 --- /dev/null +++ b/example/nested_paging/x64/range_t.hpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef RANGE_T_HPP +#define RANGE_T_HPP + +#include + +namespace example +{ + /// @struct example::range_t + /// + /// + /// @brief Defines a MTRR range used by the mtrr_t class. + /// + struct range_t final + { + /// @brief Defines the range's address + bsl::safe_uintmax addr; + /// @brief Defines the range's size in bytes + bsl::safe_uintmax size; + /// @brief Defines the range's memory type + bsl::safe_uintmax type; + /// @brief Defines if the range is the default range + bool dflt; + }; +} + +#endif diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index ec5140ed..f4e7544f 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -19,147 +19,237 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -include(${CMAKE_CURRENT_LIST_DIR}/../cmake/function/hypervisor_add_header_depends.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/function/hypervisor_target_source.cmake) add_executable(kernel) +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + target_include_directories(kernel PRIVATE + include src ) +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + target_include_directories(kernel PRIVATE + include/x64 + src/x64 + ) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") + target_include_directories(kernel PRIVATE + include/x64/amd + src/x64/amd + ) + endif() + + if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + target_include_directories(kernel PRIVATE + include/x64/intel + src/x64/intel + ) + endif() +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + target_include_directories(kernel PRIVATE + include/arm/aarch64 + src/arm/aarch64 + ) +endif() + +# ------------------------------------------------------------------------------ +# Headers +# ------------------------------------------------------------------------------ + list(APPEND HEADERS - ${CMAKE_CURRENT_LIST_DIR}/src/call_ext.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/alloc_huge_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/alloc_page_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/allocate_tags.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/allocated_status_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/call_ext.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/execution_status_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/get_current_tls.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/map_page_flags.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/page_pool_record_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/page_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/promote.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/return_to_mk.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/return_to_vmexit_loop.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/serial_write_c.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/serial_write_hex.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/vmexit_loop_entry.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/yield.hpp ${CMAKE_CURRENT_LIST_DIR}/src/debug_ring_write.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_callback_op.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_control_op.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_debug_op.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_handle_op.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_esr_page_fault.hpp ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_callback_op_failure.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_callback_op.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_control_op_failure.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_control_op.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_debug_op_failure.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_debug_op.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_failure.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_handle_op_failure.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_handle_op.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_mem_op_failure.hpp ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_mem_op.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_vm_op_failure.hpp ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_vm_op.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_vp_op_failure.hpp ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_vp_op.hpp ${CMAKE_CURRENT_LIST_DIR}/src/dispatch_syscall_vps_op.hpp ${CMAKE_CURRENT_LIST_DIR}/src/ext_pool_t.hpp ${CMAKE_CURRENT_LIST_DIR}/src/ext_t.hpp ${CMAKE_CURRENT_LIST_DIR}/src/fast_fail.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/get_current_tls.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/global_resources.hpp ${CMAKE_CURRENT_LIST_DIR}/src/huge_pool_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/mk_main.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/lock_guard_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/mk_main_t.hpp ${CMAKE_CURRENT_LIST_DIR}/src/page_pool_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/page_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/promote.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/return_to_mk.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/return_to_vmexit_loop.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/vmexit_loop_entry.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/vmexit_loop.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/serial_write.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/spinlock_t.hpp ${CMAKE_CURRENT_LIST_DIR}/src/vm_pool_t.hpp ${CMAKE_CURRENT_LIST_DIR}/src/vm_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/vmexit_loop.hpp ${CMAKE_CURRENT_LIST_DIR}/src/vp_pool_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/vps_pool_t.hpp ${CMAKE_CURRENT_LIST_DIR}/src/vp_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/vps_pool_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/bfelf/elf64_ehdr_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/bfelf/elf64_phdr_t.hpp ${CMAKE_CURRENT_LIST_DIR}/src/bsl/cstdio.hpp ${CMAKE_CURRENT_LIST_DIR}/src/bsl/details/print_thread_id.hpp ${CMAKE_CURRENT_LIST_DIR}/src/bsl/details/putc_stderr.hpp ${CMAKE_CURRENT_LIST_DIR}/src/bsl/details/putc_stdout.hpp ${CMAKE_CURRENT_LIST_DIR}/src/bsl/details/puts_stderr.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/bsl/details/puts_stdout.hpp -) + ${CMAKE_CURRENT_LIST_DIR}/src/bsl/details/puts_stdout.hpp) if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - target_include_directories(kernel PRIVATE - src/x64 - ) - list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/include/x64/general_purpose_regs_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/pdpt_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/pdpte_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/pdt_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/pdte_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/pml4t_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/pml4te_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/pt_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/pte_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/tls_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/vmexit_log_pp_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/vmexit_log_record_t.hpp ${CMAKE_CURRENT_LIST_DIR}/src/x64/dispatch_esr.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/dispatch_syscall_intrinsic_op.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/pdpt_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/pdt_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/pml4t_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/pt_t.hpp ${CMAKE_CURRENT_LIST_DIR}/src/x64/root_page_table_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/serial_write.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/smap_guard_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/tls_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/vmexit_log_t.hpp + ) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/include/x64/amd/vmcb_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/dispatch_esr_nmi.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/dispatch_syscall_intrinsic_op.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/intrinsic_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/vps_t.hpp + ) + endif() + + if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/include/x64/intel/invept_descriptor_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/intel/invvpid_descriptor_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/intel/vmcs_missing_registers_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/x64/intel/vmcs_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/dispatch_esr_nmi.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/dispatch_syscall_intrinsic_op.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/intrinsic_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/vps_t.hpp + ) + endif() +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/general_purpose_regs_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/l0t_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/l0te_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/l1t_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/l1te_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/l2t_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/l2te_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/l3t_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/l3te_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/tls_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/vmcb_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/vmexit_log_pp_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/arm/aarch64/vmexit_log_record_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/arm/aarch64/dispatch_esr.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/arm/aarch64/dispatch_syscall_intrinsic_op.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/arm/aarch64/intrinsic_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/arm/aarch64/root_page_table_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/arm/aarch64/vmexit_log_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/arm/aarch64/vps_t.hpp ) endif() -if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") - target_include_directories(kernel PRIVATE - src/x64/amd - ) - list(APPEND HEADERS - ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/dispatch_esr_nmi.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/intrinsic_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/vmcb_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/amd/vps_t.hpp - ) -elseif(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - target_include_directories(kernel PRIVATE - src/x64/intel - ) - list(APPEND HEADERS - ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/dispatch_esr_nmi.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/intrinsic_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/vmcs_missing_registers_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/vmcs_t.hpp - ${CMAKE_CURRENT_LIST_DIR}/src/x64/intel/vps_t.hpp - ) -else() - message(FATAL_ERROR "Unsupported HYPERVISOR_TARGET_ARCH: ${HYPERVISOR_TARGET_ARCH}") -endif() +# ------------------------------------------------------------------------------ +# Sources +# ------------------------------------------------------------------------------ -target_sources(kernel PRIVATE - src/dispatch_esr_trampoline.cpp - src/dispatch_syscall_trampoline.cpp - src/fast_fail_trampoline.cpp - src/mk_main_trampoline.cpp - src/msg_halt.cpp - src/msg_stack_chk_fail.cpp - src/vmexit_loop_trampoline.cpp -) - -hypervisor_add_header_depends(src/dispatch_esr_trampoline.cpp ${HEADERS}) -hypervisor_add_header_depends(src/dispatch_syscall_trampoline.cpp ${HEADERS}) -hypervisor_add_header_depends(src/fast_fail_trampoline.cpp ${HEADERS}) -hypervisor_add_header_depends(src/mk_main_trampoline.cpp ${HEADERS}) -hypervisor_add_header_depends(src/msg_halt.cpp ${HEADERS}) -hypervisor_add_header_depends(src/msg_stack_chk_fail.cpp ${HEADERS}) -hypervisor_add_header_depends(src/vmexit_loop_trampoline.cpp ${HEADERS}) +hypervisor_target_source(kernel src/main.cpp ${HEADERS}) +hypervisor_target_source(kernel src/msg_halt.cpp ${HEADERS}) +hypervisor_target_source(kernel src/msg_stack_chk_fail.cpp ${HEADERS}) if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - target_sources(kernel PRIVATE - src/x64/__stack_chk_fail.S - src/x64/call_ext.S - src/x64/dispatch_esr_entry.S - src/x64/dispatch_syscall_entry.S - src/x64/fast_fail_entry.S - src/x64/get_current_tls.S - src/x64/mk_main_entry.S - src/x64/return_to_current_fast_fail.S - src/x64/return_to_mk.S - src/x64/return_to_vmexit_loop.S - src/x64/serial_write.S - src/x64/set_esr.S - src/x64/smap_guard_t.S - src/x64/vmexit_loop_entry.S - ) + hypervisor_target_source(kernel src/x64/__stack_chk_fail.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/call_ext.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/dispatch_esr_entry.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/dispatch_syscall_entry.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/fast_fail_entry.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/get_current_tls.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/mk_main_entry.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/return_to_current_fast_fail.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/return_to_mk.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/return_to_vmexit_loop.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/serial_write_c.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/serial_write_hex.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/set_esr.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/vmexit_loop_entry.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/yield.S ${HEADERS}) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") + hypervisor_target_source(kernel src/x64/amd/intrinsic_t.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/amd/promote.S ${HEADERS}) + endif() + + if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + hypervisor_target_source(kernel src/x64/intel/intrinsic_t.S ${HEADERS}) + hypervisor_target_source(kernel src/x64/intel/promote.S ${HEADERS}) + endif() endif() -if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") - target_sources(kernel PRIVATE - src/x64/amd/intrinsic_t.S - src/x64/amd/promote.S - ) -elseif(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - target_sources(kernel PRIVATE - src/x64/intel/intrinsic_t.S - src/x64/intel/promote.S - ) -else() - message(FATAL_ERROR "Unsupported HYPERVISOR_TARGET_ARCH: ${HYPERVISOR_TARGET_ARCH}") -endif() +# if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") +# hypervisor_target_source(kernel src/arm/aarch64/__stack_chk_fail.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/call_ext.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/dispatch_esr_entry.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/dispatch_syscall_entry.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/fast_fail_entry.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/get_current_tls.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/intrinsic_t.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/mk_main_entry.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/promote.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/return_to_current_fast_fail.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/return_to_mk.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/return_to_vmexit_loop.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/serial_write_c.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/serial_write_hex.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/vmexit_loop_entry.S ${HEADERS}) +# hypervisor_target_source(kernel src/arm/aarch64/yield.S ${HEADERS}) +# endif() + +# ------------------------------------------------------------------------------ +# Libraries +# ------------------------------------------------------------------------------ target_link_libraries(kernel PRIVATE bsl @@ -168,4 +258,12 @@ target_link_libraries(kernel PRIVATE hypervisor ) +# ------------------------------------------------------------------------------ +# Install +# ------------------------------------------------------------------------------ + +if(CMAKE_BUILD_TYPE STREQUAL RELEASE OR CMAKE_BUILD_TYPE STREQUAL MINSIZEREL) + add_custom_command(TARGET kernel POST_BUILD COMMAND ${CMAKE_STRIP} kernel) +endif() + install(TARGETS kernel DESTINATION bin) diff --git a/kernel/include/alloc_huge_t.hpp b/kernel/include/alloc_huge_t.hpp new file mode 100644 index 00000000..19f61a0b --- /dev/null +++ b/kernel/include/alloc_huge_t.hpp @@ -0,0 +1,46 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef ALLOC_HUGE_T_HPP +#define ALLOC_HUGE_T_HPP + +#include + +namespace mk +{ + /// @struct mk::alloc_huge_t + /// + /// + /// @brief Defines a alloc_huge_t + /// + struct alloc_huge_t final + { + /// @brief stores the virtual address of the memory + bsl::safe_uintmax virt; + /// @brief stores the physical address of the memory + bsl::safe_uintmax phys; + }; +} + +#endif diff --git a/kernel/include/alloc_page_t.hpp b/kernel/include/alloc_page_t.hpp new file mode 100644 index 00000000..f5986d86 --- /dev/null +++ b/kernel/include/alloc_page_t.hpp @@ -0,0 +1,46 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef ALLOC_PAGE_T_HPP +#define ALLOC_PAGE_T_HPP + +#include + +namespace mk +{ + /// @struct mk::alloc_page_t + /// + /// + /// @brief Defines a alloc_page_t + /// + struct alloc_page_t final + { + /// @brief stores the virtual address of the page + bsl::safe_uintmax virt; + /// @brief stores the physical address of the page + bsl::safe_uintmax phys; + }; +} + +#endif diff --git a/kernel/include/allocate_tags.hpp b/kernel/include/allocate_tags.hpp new file mode 100644 index 00000000..2de23cb4 --- /dev/null +++ b/kernel/include/allocate_tags.hpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef ALLOCATE_TAGS_HPP +#define ALLOCATE_TAGS_HPP + +#include + +namespace mk +{ + /// @brief Defines the "bf_mem_op_alloc_page" tag + constexpr auto ALLOCATE_TAG_BF_MEM_OP_ALLOC_PAGE{"bf_mem_op_alloc_page"}; + /// @brief Defines the "bf_mem_op_alloc_huge" tag + constexpr auto ALLOCATE_TAG_BF_MEM_OP_ALLOC_HUGE{"bf_mem_op_alloc_huge"}; + /// @brief Defines the "bf_mem_op_alloc_heap" tag + constexpr auto ALLOCATE_TAG_BF_MEM_OP_ALLOC_HEAP{"bf_mem_op_alloc_heap"}; + /// @brief Defines the "extension stack memory" tag + constexpr auto ALLOCATE_TAG_EXT_STACK{"extension stack memory"}; + /// @brief Defines the "extension TLS memory" tag + constexpr auto ALLOCATE_TAG_EXT_TLS{"extension TLS memory"}; + /// @brief Defines the "extension ELF segments" tag + constexpr auto ALLOCATE_TAG_EXT_ELF{"extension ELF segments"}; + /// @brief Defines the "pml4ts" tag + constexpr auto ALLOCATE_TAG_PML4TS{"pml4ts"}; + /// @brief Defines the "pdpts" tag + constexpr auto ALLOCATE_TAG_PDPTS{"pdpts"}; + /// @brief Defines the "pdts" tag + constexpr auto ALLOCATE_TAG_PDTS{"pdts"}; + /// @brief Defines the "pts" tag + constexpr auto ALLOCATE_TAG_PTS{"pts"}; + /// @brief Defines the "guest vmcb" tag + constexpr auto ALLOCATE_TAG_GUEST_VMCB{"guest vmcb"}; + /// @brief Defines the "host vmcb" tag + constexpr auto ALLOCATE_TAG_HOST_VMCB{"host vmcb"}; + /// @brief Defines the "vmcs" tag + constexpr auto ALLOCATE_TAG_VMCS{"vmcs"}; +} + +#endif diff --git a/kernel/include/allocated_status_t.hpp b/kernel/include/allocated_status_t.hpp new file mode 100644 index 00000000..159abf6f --- /dev/null +++ b/kernel/include/allocated_status_t.hpp @@ -0,0 +1,46 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef ALLOCATED_STATUS_T_HPP +#define ALLOCATED_STATUS_T_HPP + +#include + +namespace mk +{ + /// + /// @brief Defines the layout of a page pool tag + /// + enum class allocated_status_t : bsl::uint8 + { + /// @brief defines the deallocated state for a resource + deallocated, + /// @brief defines the allocated state for a resource + allocated, + /// @brief defines the zombie state for a resource + zombie + }; +} + +#endif diff --git a/kernel/include/arm/aarch64/general_purpose_regs_t.hpp b/kernel/include/arm/aarch64/general_purpose_regs_t.hpp new file mode 100644 index 00000000..b741dd79 --- /dev/null +++ b/kernel/include/arm/aarch64/general_purpose_regs_t.hpp @@ -0,0 +1,79 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef GENERAL_PURPOSE_REGS_T_HPP +#define GENERAL_PURPOSE_REGS_T_HPP + +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @struct mk::general_purpose_regs_t + /// + /// + /// @brief Stores the state of the general purpose registers. Note + /// that this storage is only used when swapping from one VPS to + /// another. Otherwise, an extension's TLS block is used instead + /// to access the general purpose registers as they are faster. + /// + struct general_purpose_regs_t final + { + /// @brief stores the value of rax (0x000) + bsl::uintmax rax; + /// @brief stores the value of rbx (0x008) + bsl::uintmax rbx; + /// @brief stores the value of rcx (0x010) + bsl::uintmax rcx; + /// @brief stores the value of rdx (0x018) + bsl::uintmax rdx; + /// @brief stores the value of rbp (0x020) + bsl::uintmax rbp; + /// @brief stores the value of rsi (0x028) + bsl::uintmax rsi; + /// @brief stores the value of rdi (0x030) + bsl::uintmax rdi; + /// @brief stores the value of r8 (0x038) + bsl::uintmax r8; + /// @brief stores the value of r9 (0x040) + bsl::uintmax r9; + /// @brief stores the value of r10 (0x048) + bsl::uintmax r10; + /// @brief stores the value of r11 (0x050) + bsl::uintmax r11; + /// @brief stores the value of r12 (0x058) + bsl::uintmax r12; + /// @brief stores the value of r13 (0x060) + bsl::uintmax r13; + /// @brief stores the value of r14 (0x068) + bsl::uintmax r14; + /// @brief stores the value of r15 (0x070) + bsl::uintmax r15; + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/arm/aarch64/l0t_t.hpp b/kernel/include/arm/aarch64/l0t_t.hpp new file mode 100644 index 00000000..3c4e9f62 --- /dev/null +++ b/kernel/include/arm/aarch64/l0t_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef L0T_T_HPP +#define L0T_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @brief defines total number of entries in the L0T + constexpr auto NUM_L0T_ENTRIES{512_umax}; + + /// @struct mk::l0t_t + /// + /// + /// @brief Defines the layout of a level-0 table (L0T). + /// + struct l0t_t final + { + /** @brief stores the entries for this page table */ + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/arm/aarch64/l0te_t.hpp b/kernel/include/arm/aarch64/l0te_t.hpp new file mode 100644 index 00000000..680d3756 --- /dev/null +++ b/kernel/include/arm/aarch64/l0te_t.hpp @@ -0,0 +1,66 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef L0TE_T +#define L0TE_T + +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @struct mk::l0te_t + /// + /// + /// @brief Defines the layout of a level-0 table entry (L0TE). + /// + struct l0te_t final + { + /// @brief defines the "present" field in the page + bsl::uint64 p : static_cast(1); + /// @brief defines the "block/table" field in the page + bsl::uint64 bt : static_cast(1); + /// @brief defines our "aliased" field in the page + bsl::uint64 alias : static_cast(1); + /// @brief defines the "available to software" field in the page + bsl::uint64 available1 : static_cast(9); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(40); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(7); + /// @brief defines the "PXNTable" field in the page + bsl::uint64 pxntable : static_cast(1); + /// @brief defines the "XNTable" field in the page + bsl::uint64 xntable : static_cast(1); + /// @brief defines the "APTable" field in the page + bsl::uint64 aptable : static_cast(2); + /// @brief defines the "NSTable" field in the page + bsl::uint64 nstable : static_cast(1); + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/arm/aarch64/l1t_t.hpp b/kernel/include/arm/aarch64/l1t_t.hpp new file mode 100644 index 00000000..55217b71 --- /dev/null +++ b/kernel/include/arm/aarch64/l1t_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef L1T_T_HPP +#define L1T_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @brief defines total number of entries in the L1T + constexpr auto NUM_L1T_ENTRIES{512_umax}; + + /// @struct mk::l1t_t + /// + /// + /// @brief Defines the layout of a level-1 table (L1T). + /// + struct l1t_t final + { + /** @brief stores the entries for this page table */ + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/arm/aarch64/l1te_t.hpp b/kernel/include/arm/aarch64/l1te_t.hpp new file mode 100644 index 00000000..ce593315 --- /dev/null +++ b/kernel/include/arm/aarch64/l1te_t.hpp @@ -0,0 +1,64 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef L1TE_T +#define L1TE_T + +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @struct mk::l1te_t + /// + /// + /// @brief Defines the layout of a level-1 table entry (L1TE). + /// + struct l1te_t final + { + /// @brief defines the "present" field in the page + bsl::uint64 p : static_cast(1); + /// @brief defines the "block/table" field in the page + bsl::uint64 bt : static_cast(1); + /// @brief defines the "available to software" field in the page + bsl::uint64 available1 : static_cast(10); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(40); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(7); + /// @brief defines the "PXNTable" field in the page + bsl::uint64 pxntable : static_cast(1); + /// @brief defines the "XNTable" field in the page + bsl::uint64 xntable : static_cast(1); + /// @brief defines the "APTable" field in the page + bsl::uint64 aptable : static_cast(2); + /// @brief defines the "NSTable" field in the page + bsl::uint64 nstable : static_cast(1); + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/arm/aarch64/l2t_t.hpp b/kernel/include/arm/aarch64/l2t_t.hpp new file mode 100644 index 00000000..4e7c0192 --- /dev/null +++ b/kernel/include/arm/aarch64/l2t_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef L2T_T_HPP +#define L2T_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @brief defines total number of entries in the L2T + constexpr auto NUM_L2T_ENTRIES{512_umax}; + + /// @struct mk::l2t_t + /// + /// + /// @brief Defines the layout of a level-2 table (L2T). + /// + struct l2t_t final + { + /** @brief stores the entries for this page table */ + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/arm/aarch64/l2te_t.hpp b/kernel/include/arm/aarch64/l2te_t.hpp new file mode 100644 index 00000000..a3dbebd2 --- /dev/null +++ b/kernel/include/arm/aarch64/l2te_t.hpp @@ -0,0 +1,64 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef L2TE_T +#define L2TE_T + +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @struct mk::l2te_t + /// + /// + /// @brief Defines the layout of a level-2 table entry (L2TE). + /// + struct l2te_t final + { + /// @brief defines the "present" field in the page + bsl::uint64 p : static_cast(1); + /// @brief defines the "block/table" field in the page + bsl::uint64 bt : static_cast(1); + /// @brief defines the "available to software" field in the page + bsl::uint64 available1 : static_cast(10); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(40); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(7); + /// @brief defines the "PXNTable" field in the page + bsl::uint64 pxntable : static_cast(1); + /// @brief defines the "XNTable" field in the page + bsl::uint64 xntable : static_cast(1); + /// @brief defines the "APTable" field in the page + bsl::uint64 aptable : static_cast(2); + /// @brief defines the "NSTable" field in the page + bsl::uint64 nstable : static_cast(1); + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/arm/aarch64/l3t_t.hpp b/kernel/include/arm/aarch64/l3t_t.hpp new file mode 100644 index 00000000..3f817192 --- /dev/null +++ b/kernel/include/arm/aarch64/l3t_t.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef L3T_T_HPP +#define L3T_T_HPP + +#include + +#include +#include +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @brief defines total number of entries in the L3T + constexpr auto NUM_L3T_ENTRIES{512_umax}; + + /// @struct mk::l3t_t + /// + /// + /// @brief Defines the layout of a level-3 table (L3T). + /// + struct l3t_t final + { + /** @brief stores the entries for this page table */ + bsl::array entries; + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/arm/aarch64/l3te_t.hpp b/kernel/include/arm/aarch64/l3te_t.hpp new file mode 100644 index 00000000..286318d9 --- /dev/null +++ b/kernel/include/arm/aarch64/l3te_t.hpp @@ -0,0 +1,82 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef L3TE_T +#define L3TE_T + +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @struct mk::l3te_t + /// + /// + /// @brief Defines the layout of a level-3 table entry (L3TE). + /// + struct l3te_t final + { + /// @brief defines the "present" field in the page + bsl::uint64 p : static_cast(1); + /// @brief defines the "page" field in the page + bsl::uint64 page : static_cast(1); + /// @brief defines the "AttrIndx" field in the page + bsl::uint64 attr_indx : static_cast(3); + /// @brief defines the "NS" field in the page + bsl::uint64 ns : static_cast(1); + /// @brief defines the "AP" field in the page + bsl::uint64 ap : static_cast(2); + /// @brief defines the "SH" field in the page + bsl::uint64 sh : static_cast(2); + /// @brief defines the "AF" field in the page + bsl::uint64 af : static_cast(1); + /// @brief defines the "nG" field in the page + bsl::uint64 ng : static_cast(1); + /// @brief defines the "physical address" field in the page + bsl::uint64 phys : static_cast(38); + /// @brief defines the "GP" field in the page + bsl::uint64 gp : static_cast(1); + /// @brief defines the "DBM" field in the page + bsl::uint64 dbm : static_cast(1); + /// @brief defines the "Contiguous" field in the page + bsl::uint64 contiguous : static_cast(1); + /// @brief defines the "PXN" field in the page + bsl::uint64 pxn : static_cast(1); + /// @brief defines the "UXN or XN" field in the page + bsl::uint64 xn : static_cast(1); + /// @brief defines our "auto_release" field in the page + bsl::uint64 auto_release : static_cast(3); + /// @brief defines the "available to software" field in the page + bsl::uint64 available1 : static_cast(1); + /// @brief defines the "PBHA" field in the page + bsl::uint64 pbha : static_cast(4); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(1); + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/arm/aarch64/tls_t.hpp b/kernel/include/arm/aarch64/tls_t.hpp new file mode 100644 index 00000000..a9022d91 --- /dev/null +++ b/kernel/include/arm/aarch64/tls_t.hpp @@ -0,0 +1,393 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TLS_T_HPP +#define TLS_T_HPP + +#include + +#include +#include +#include +#include +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @brief defines the size of the reserved1 field in the tls_t + constexpr auto TLS_T_RESERVED1_SIZE{0x020_umax}; + /// @brief defines the size of the reserved2 field in the tls_t + constexpr auto TLS_T_RESERVED2_SIZE{0x008_umax}; + /// @brief defines the size of the reserved3 field in the tls_t + constexpr auto TLS_T_RESERVED3_SIZE{0x007_umax}; + /// @brief defines the size of the reserved4 field in the tls_t + constexpr auto TLS_T_RESERVED4_SIZE{0x040_umax}; + + /// IMPORTANT: + /// - If the size of the TLS is changed, the mk_main_entry will need to + /// be updated to reflect the new size. It might make sense to have a + /// header file that defines a constant that both this code and the + /// assembly logic can share + /// + + /// @brief defines the the total size of the TLS block + constexpr auto TLS_T_SIZE{0x400_umax}; + + /// @struct mk::tls_t + /// + /// + /// @brief Defines the layout of the microkernel's TLS block. This + /// should not be confused with the TLS blocks given to an extension, + /// for which there are two, the TLS block for thread_local and the + /// TLS block provided by the microkernel's ABI. + /// + struct tls_t final + { + /// -------------------------------------------------------------------- + /// Microkernel State + /// -------------------------------------------------------------------- + + /// @brief stores the value of x18 for the microkernel (0x000) + bsl::uintmax mk_x18; + /// @brief stores the value of x19 for the microkernel (0x008) + bsl::uintmax mk_x19; + /// @brief stores the value of x20 for the microkernel (0x010) + bsl::uintmax mk_x20; + /// @brief stores the value of x21 for the microkernel (0x018) + bsl::uintmax mk_x21; + /// @brief stores the value of x22 for the microkernel (0x020) + bsl::uintmax mk_x22; + /// @brief stores the value of x23 for the microkernel (0x028) + bsl::uintmax mk_x23; + /// @brief stores the value of x24 for the microkernel (0x030) + bsl::uintmax mk_x24; + /// @brief stores the value of x25 for the microkernel (0x038) + bsl::uintmax mk_x25; + /// @brief stores the value of x26 for the microkernel (0x040) + bsl::uintmax mk_x26; + /// @brief stores the value of x27 for the microkernel (0x048) + bsl::uintmax mk_x27; + /// @brief stores the value of x28 for the microkernel (0x050) + bsl::uintmax mk_x28; + /// @brief stores the value of x29 for the microkernel (0x058) + bsl::uintmax mk_x29; + /// @brief stores the value of x30 for the microkernel (0x060) + bsl::uintmax mk_x30; + + /// -------------------------------------------------------------------- + /// Extension State + /// -------------------------------------------------------------------- + + /// @brief x0, stores the extension's syscall (0x068) + bsl::uintmax ext_syscall; + /// @brief x1, stores the value of REG1 for the extension (0x070) + bsl::uintmax ext_reg0; + /// @brief x2, stores the value of REG1 for the extension (0x078) + bsl::uintmax ext_reg1; + /// @brief x3, stores the value of REG1 for the extension (0x080) + bsl::uintmax ext_reg2; + /// @brief x4, stores the value of REG1 for the extension (0x088) + bsl::uintmax ext_reg3; + /// @brief x5, stores the value of REG1 for the extension (0x090) + bsl::uintmax ext_reg4; + /// @brief x6, stores the value of REG1 for the extension (0x098) + bsl::uintmax ext_reg5; + /// @brief x7, stores the value of REG1 for the extension (0x0A0) + bsl::uintmax reserved_reg7; + /// @brief x8, stores the value of REG1 for the extension (0x0A8) + bsl::uintmax reserved_reg8; + /// @brief x9, stores the value of REG1 for the extension (0x0B0) + bsl::uintmax reserved_reg9; + /// @brief x10, stores the value of REG1 for the extension (0x0B8) + bsl::uintmax reserved_reg10; + /// @brief x11, stores the value of REG1 for the extension (0x0C0) + bsl::uintmax reserved_reg11; + /// @brief x12, stores the value of REG1 for the extension (0x0C8) + bsl::uintmax reserved_reg12; + /// @brief x13, stores the value of REG1 for the extension (0x0D0) + bsl::uintmax reserved_reg13; + /// @brief x14, stores the value of REG1 for the extension (0x0D8) + bsl::uintmax reserved_reg14; + /// @brief x15, stores the value of REG1 for the extension (0x0E0) + bsl::uintmax reserved_reg15; + /// @brief x16, stores the value of REG1 for the extension (0x0E8) + bsl::uintmax reserved_reg16; + /// @brief x17, stores the value of REG1 for the extension (0x0F0) + bsl::uintmax reserved_reg17; + /// @brief x18, stores the value of REG1 for the extension (0x0F8) + bsl::uintmax reserved_reg18; + /// @brief x19, stores the value of REG1 for the extension (0x100) + bsl::uintmax reserved_reg19; + /// @brief x20, stores the value of REG1 for the extension (0x108) + bsl::uintmax reserved_reg20; + /// @brief x21, stores the value of REG1 for the extension (0x110) + bsl::uintmax reserved_reg21; + /// @brief x22, stores the value of REG1 for the extension (0x118) + bsl::uintmax reserved_reg22; + /// @brief x23, stores the value of REG1 for the extension (0x120) + bsl::uintmax reserved_reg23; + /// @brief x24, stores the value of REG1 for the extension (0x128) + bsl::uintmax reserved_reg24; + /// @brief x25, stores the value of REG1 for the extension (0x130) + bsl::uintmax reserved_reg25; + /// @brief x26, stores the value of REG1 for the extension (0x138) + bsl::uintmax reserved_reg26; + /// @brief x27, stores the value of REG1 for the extension (0x140) + bsl::uintmax reserved_reg27; + /// @brief x28, stores the value of REG1 for the extension (0x148) + bsl::uintmax reserved_reg28; + /// @brief x29, stores the value of REG1 for the extension (0x150) + bsl::uintmax reserved_reg29; + /// @brief x30, stores the value of REG1 for the extension (0x158) + bsl::uintmax reserved_reg30; + + /// -------------------------------------------------------------------- + /// ESR State + /// -------------------------------------------------------------------- + + /// @brief stores the value of x0 for the ESR (0x160) + bsl::uintmax esr_x0; + /// @brief stores the value of x1 for the ESR (0x168) + bsl::uintmax esr_x1; + /// @brief stores the value of x2 for the ESR (0x170) + bsl::uintmax esr_x2; + /// @brief stores the value of x3 for the ESR (0x178) + bsl::uintmax esr_x3; + /// @brief stores the value of x4 for the ESR (0x180) + bsl::uintmax esr_x4; + /// @brief stores the value of x5 for the ESR (0x188) + bsl::uintmax esr_x5; + /// @brief stores the value of x6 for the ESR (0x190) + bsl::uintmax esr_x6; + /// @brief stores the value of x7 for the ESR (0x198) + bsl::uintmax esr_x7; + /// @brief stores the value of x8 for the ESR (0x1A0) + bsl::uintmax esr_x8; + /// @brief stores the value of x9 for the ESR (0x1A8) + bsl::uintmax esr_x9; + /// @brief stores the value of x10 for the ESR (0x1B0) + bsl::uintmax esr_x10; + /// @brief stores the value of x11 for the ESR (0x1B8) + bsl::uintmax esr_x11; + /// @brief stores the value of x12 for the ESR (0x1C0) + bsl::uintmax esr_x12; + /// @brief stores the value of x13 for the ESR (0x1C8) + bsl::uintmax esr_x13; + /// @brief stores the value of x14 for the ESR (0x1D0) + bsl::uintmax esr_x14; + /// @brief stores the value of x15 for the ESR (0x1D8) + bsl::uintmax esr_x15; + /// @brief stores the value of x16 for the ESR (0x1E0) + bsl::uintmax esr_x16; + /// @brief stores the value of x17 for the ESR (0x1E8) + bsl::uintmax esr_x17; + /// @brief stores the value of x18 for the ESR (0x1F0) + bsl::uintmax esr_x18; + /// @brief stores the value of x19 for the ESR (0x1F8) + bsl::uintmax esr_x19; + /// @brief stores the value of x20 for the ESR (0x200) + bsl::uintmax esr_x20; + /// @brief stores the value of x21 for the ESR (0x208) + bsl::uintmax esr_x21; + /// @brief stores the value of x22 for the ESR (0x210) + bsl::uintmax esr_x22; + /// @brief stores the value of x23 for the ESR (0x218) + bsl::uintmax esr_x23; + /// @brief stores the value of x24 for the ESR (0x220) + bsl::uintmax esr_x24; + /// @brief stores the value of x25 for the ESR (0x228) + bsl::uintmax esr_x25; + /// @brief stores the value of x26 for the ESR (0x230) + bsl::uintmax esr_x26; + /// @brief stores the value of x27 for the ESR (0x238) + bsl::uintmax esr_x27; + /// @brief stores the value of x28 for the ESR (0x240) + bsl::uintmax esr_x28; + /// @brief stores the value of x29 for the ESR (0x248) + bsl::uintmax esr_x29; + /// @brief stores the value of x30 for the ESR (0x250) + bsl::uintmax esr_x30; + + /// @brief stores the value of sp for the ESR (0x258) + bsl::uintmax esr_sp; + /// @brief stores the value of ip for the ESR (0x260) + bsl::uintmax esr_ip; + + /// @brief stores the value of the ESR vector (0x268) + bsl::uintmax esr_vector; + /// @brief stores the value of the ESR error code (0x270) + bsl::uintmax esr_error_code; + + /// @brief stores the value of far for the ESR (0x278) + bsl::uintmax esr_pf_addr; + /// @brief stores the value of esr for the ESR (0x280) + bsl::uintmax esr_esr; + + /// @brief stores the value of SPSR for the ESR (0x288) + bsl::uintmax esr_spsr; + + /// -------------------------------------------------------------------- + /// Fast Fail Information + /// -------------------------------------------------------------------- + + /// @brief stores the current fast fail address (0x290) + bsl::uintmax current_fast_fail_ip; + /// @brief stores the current fast fail stack (0x298) + bsl::uintmax current_fast_fail_sp; + + /// @brief stores the mk_main fast fail address (0x2A0) + bsl::uintmax mk_main_fast_fail_ip; + /// @brief stores the mk_main fast fail stack (0x2A8) + bsl::uintmax mk_main_fast_fail_sp; + + /// @brief stores the call_ext fast fail address (0x2B0) + bsl::uintmax call_ext_fast_fail_ip; + /// @brief stores the call_ext fast fail stack (0x2B8) + bsl::uintmax call_ext_fast_fail_sp; + + /// @brief stores the dispatch_syscall fast fail address (0x2C0) + bsl::uintmax dispatch_syscall_fast_fail_ip; + /// @brief stores the dispatch_syscall fast fail stack (0x2C8) + bsl::uintmax dispatch_syscall_fast_fail_sp; + + /// @brief stores the vmexit loop address (0x2D0) + bsl::uintmax vmexit_loop_ip; + /// @brief stores the vmexit loop stack (0x2D8) + bsl::uintmax vmexit_loop_sp; + + /// @brief reserve the rest of the TLS block for later use. + bsl::details::carray reserved1; + + /// -------------------------------------------------------------------- + /// Context Information + /// -------------------------------------------------------------------- + + /// @brief stores the virtual address of this TLS block (0x300) + tls_t *self; + + /// @brief stores the currently active VMID (0x308) + bsl::uint16 ppid; + /// @brief stores the total number of online PPs (0x30A) + bsl::uint16 online_pps; + /// @brief reserved (0x30C) + bsl::uint16 reserved_padding0; + /// @brief reserved (0x30E) + bsl::uint16 reserved_padding1; + + /// @brief stores the currently active extension (0x310) + void *ext; + /// @brief stores the extension registered for VMExits (0x318) + void *ext_vmexit; + /// @brief stores the extension registered for fast fail events (0x320) + void *ext_fail; + + /// @brief stores the loader provided state for the microkernel (0x328) + loader::state_save_t *mk_state; + /// @brief stores the loader provided state for the root VP (0x330) + loader::state_save_t *root_vp_state; + + /// @brief stores the currently active extension ID (0x338) + bsl::uint16 active_extid; + /// @brief stores the currently active VMID (0x33A) + bsl::uint16 active_vmid; + /// @brief stores the currently active VPID (0x33C) + bsl::uint16 active_vpid; + /// @brief stores the currently active VPSID (0x33E) + bsl::uint16 active_vpsid; + + /// @brief stores the sp used by extensions for callbacks (0x340) + bsl::uintmax sp; + /// @brief stores the tps used by extensions for callbacks (0x348) + bsl::uintmax tp; + + /// @brief used to store a return address for unsafe ops (0x350) + bsl::uintmax unsafe_rip; + + /// @brief reserved (0x358) + bsl::uintmax reserved_padding2; + /// @brief reserved (0x360) + bsl::uintmax reserved_padding3; + + /// @brief stores whether or not the first launch succeeded (0x368) + bsl::uintmax first_launch_succeeded; + + /// @brief stores the currently active root page table (0x370) + void *active_rpt; + + /// @brief reserve the rest of the TLS block for later use. + bsl::details::carray reserved2; + + /// -------------------------------------------------------------------- + /// Failure Handling + /// -------------------------------------------------------------------- + + /// @brief stores a whether or not state is changing (0x380) + bool state_reversal_required; + + /// @brief reserves the rest of the TLS block for later use. + bsl::details::carray reserved3; + + /// @brief stores the syscall return status (0x388) + bsl::uintmax syscall_ret_status; + + /// @brief logs an extid for state reversal if needed (0x390) + bsl::uint16 log_extid; + /// @brief logs a vmid for state reversal if needed (0x392) + bsl::uint16 log_vmid; + /// @brief logs a vpid for state reversal if needed (0x394) + bsl::uint16 log_vpid; + /// @brief logs a vpsid for state reversal if needed (0x396) + bsl::uint16 log_vpsid; + + /// @brief logs an ext for state reversal if needed (0x398) + void *log_ext; + /// @brief logs a vm for state reversal if needed (0x3A0) + void *log_vm; + /// @brief logs a vp for state reversal if needed (0x3A8) + void *log_vp; + /// @brief logs a vps for state reversal if needed (0x3B0) + void *log_vps; + + /// @brief reserve the rest of the TLS block for later use. + bsl::details::carray reserved4; + + /// -------------------------------------------------------------------- + /// Unit Test Specific + /// -------------------------------------------------------------------- + + /// @brief reserved for unit testing + bsl::errc_type test_ret; + /// @brief reserved + bsl::uint32 reserved_padding4; + }; + + /// @brief make sure the tls_t is the size of a page + static_assert(sizeof(tls_t) == TLS_T_SIZE); +} + +#pragma pack(pop) + +#endif diff --git a/kernel/src/x64/amd/vmcb_t.hpp b/kernel/include/arm/aarch64/vmcb_t.hpp similarity index 76% rename from kernel/src/x64/amd/vmcb_t.hpp rename to kernel/include/arm/aarch64/vmcb_t.hpp index fda0bc89..eb56ef51 100644 --- a/kernel/src/x64/amd/vmcb_t.hpp +++ b/kernel/include/arm/aarch64/vmcb_t.hpp @@ -25,46 +25,43 @@ #ifndef VMCB_HPP #define VMCB_HPP -#pragma pack(push, 1) - #include #include #include #include +#pragma pack(push, 1) + namespace mk { - namespace details - { - /// @brief defines the size of the reserved1 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED1_SIZE{bsl::to_umax(0x24U)}; - /// @brief defines the size of the reserved2 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED2_SIZE{bsl::to_umax(0x3U)}; - /// @brief defines the size of the reserved3 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED3_SIZE{bsl::to_umax(0x4U)}; - /// @brief defines the size of the reserved4 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED4_SIZE{bsl::to_umax(0x8U)}; - /// @brief defines the size of the reserved5 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED5_SIZE{bsl::to_umax(0x8U)}; - /// @brief defines the size of the reserved6 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED6_SIZE{bsl::to_umax(0x2F0U)}; - /// @brief defines the size of the reserved7 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED7_SIZE{bsl::to_umax(0x2BU)}; - /// @brief defines the size of the reserved8 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED8_SIZE{bsl::to_umax(0x4U)}; - /// @brief defines the size of the reserved9 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED9_SIZE{bsl::to_umax(0x70U)}; - /// @brief defines the size of the reserved10 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED10_SIZE{bsl::to_umax(0x58U)}; - /// @brief defines the size of the reserved11 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED11_SIZE{bsl::to_umax(0x18U)}; - /// @brief defines the size of the reserved12 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED12_SIZE{bsl::to_umax(0x20U)}; - /// @brief defines the size of the reserved13 field in the VMCB - constexpr bsl::safe_uintmax VMCB_RESERVED13_SIZE{bsl::to_umax(0x968U)}; - /// @brief defines the size of the reserved13 field in the VMCB - constexpr bsl::safe_uintmax VMCB_GIB_SIZE{bsl::to_umax(0xF)}; - } + /// @brief defines the size of the reserved1 field in the VMCB + constexpr auto VMCB_RESERVED1_SIZE{0x24_umax}; + /// @brief defines the size of the reserved2 field in the VMCB + constexpr auto VMCB_RESERVED2_SIZE{0x3_umax}; + /// @brief defines the size of the reserved3 field in the VMCB + constexpr auto VMCB_RESERVED3_SIZE{0x4_umax}; + /// @brief defines the size of the reserved4 field in the VMCB + constexpr auto VMCB_RESERVED4_SIZE{0x8_umax}; + /// @brief defines the size of the reserved5 field in the VMCB + constexpr auto VMCB_RESERVED5_SIZE{0x8_umax}; + /// @brief defines the size of the reserved6 field in the VMCB + constexpr auto VMCB_RESERVED6_SIZE{0x2F0_umax}; + /// @brief defines the size of the reserved7 field in the VMCB + constexpr auto VMCB_RESERVED7_SIZE{0x2B_umax}; + /// @brief defines the size of the reserved8 field in the VMCB + constexpr auto VMCB_RESERVED8_SIZE{0x4_umax}; + /// @brief defines the size of the reserved9 field in the VMCB + constexpr auto VMCB_RESERVED9_SIZE{0x70_umax}; + /// @brief defines the size of the reserved10 field in the VMCB + constexpr auto VMCB_RESERVED10_SIZE{0x58_umax}; + /// @brief defines the size of the reserved11 field in the VMCB + constexpr auto VMCB_RESERVED11_SIZE{0x18_umax}; + /// @brief defines the size of the reserved12 field in the VMCB + constexpr auto VMCB_RESERVED12_SIZE{0x20_umax}; + /// @brief defines the size of the reserved13 field in the VMCB + constexpr auto VMCB_RESERVED13_SIZE{0x968_umax}; + /// @brief defines the size of the reserved13 field in the VMCB + constexpr auto VMCB_GIB_SIZE{0xF_umax}; /// @struct mk::vmcb_t /// @@ -95,7 +92,7 @@ namespace mk /// @brief stores the VMCB field at offset (0x0014) bsl::uint32 intercept_instruction3; /// @brief stores the VMCB field at offset (0x0018) - bsl::details::carray reserved1; + bsl::details::carray reserved1; /// @brief stores the VMCB field at offset (0x003C) bsl::uint16 pause_filter_threshold; /// @brief stores the VMCB field at offset (0x003E) @@ -111,7 +108,7 @@ namespace mk /// @brief stores the VMCB field at offset (0x005C) bsl::uint8 tlb_control; /// @brief stores the VMCB field at offset (0x005D) - bsl::details::carray reserved2; + bsl::details::carray reserved2; /// @brief stores the VMCB field at offset (0x0060) bsl::uint64 virtual_interrupt_a; /// @brief stores the VMCB field at offset (0x0068) @@ -139,27 +136,27 @@ namespace mk /// @brief stores the VMCB field at offset (0x00C0) bsl::uint32 vmcb_clean_bits; /// @brief stores the VMCB field at offset (0x00C4) - bsl::details::carray reserved3; + bsl::details::carray reserved3; /// @brief stores the VMCB field at offset (0x00C8) bsl::uint64 nrip; /// @brief stores the VMCB field at offset (0x00D0) bsl::uint8 number_of_bytes_fetched; /// @brief stores the VMCB field at offset (0x00D1) - bsl::details::carray guest_instruction_bytes; + bsl::details::carray guest_instruction_bytes; /// @brief stores the VMCB field at offset (0x00E0) bsl::uint64 avic_apic_backing_page_ptr; /// @brief stores the VMCB field at offset (0x00E8) - bsl::details::carray reserved4; + bsl::details::carray reserved4; /// @brief stores the VMCB field at offset (0x00F0) bsl::uint64 avic_logical_table_ptr; /// @brief stores the VMCB field at offset (0x00F8) bsl::uint64 avic_physical_table_ptr; /// @brief stores the VMCB field at offset (0x0100) - bsl::details::carray reserved5; + bsl::details::carray reserved5; /// @brief stores the VMCB field at offset (0x0108) bsl::uint64 vmsa_ptr; /// @brief stores the VMCB field at offset (0x0110) - bsl::details::carray reserved6; + bsl::details::carray reserved6; // ------------------------------------------------------------------------- // State Save Area @@ -230,12 +227,16 @@ namespace mk /// @brief stores the VMCB field at offset (0x0478) bsl::uint64 ldtr_base; /// @brief stores the VMCB field at offset (0x0480) + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) bsl::uint16 idtr_selector; /// @brief stores the VMCB field at offset (0x0482) + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) bsl::uint16 idtr_attrib; /// @brief stores the VMCB field at offset (0x0484) + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) bsl::uint32 idtr_limit; /// @brief stores the VMCB field at offset (0x0488) + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) bsl::uint64 idtr_base; /// @brief stores the VMCB field at offset (0x0490) bsl::uint16 tr_selector; @@ -246,15 +247,15 @@ namespace mk /// @brief stores the VMCB field at offset (0x0498) bsl::uint64 tr_base; /// @brief stores the VMCB field at offset (0x04A0) - bsl::details::carray reserved7; + bsl::details::carray reserved7; /// @brief stores the VMCB field at offset (0x04CB) bsl::uint8 cpl; /// @brief stores the VMCB field at offset (0x04CC) - bsl::details::carray reserved8; + bsl::details::carray reserved8; /// @brief stores the VMCB field at offset (0x04D0) bsl::uint64 efer; /// @brief stores the VMCB field at offset (0x04D8) - bsl::details::carray reserved9; + bsl::details::carray reserved9; /// @brief stores the VMCB field at offset (0x0548) bsl::uint64 cr4; /// @brief stores the VMCB field at offset (0x0550) @@ -270,11 +271,11 @@ namespace mk /// @brief stores the VMCB field at offset (0x0578) bsl::uint64 rip; /// @brief stores the VMCB field at offset (0x0580) - bsl::details::carray reserved10; + bsl::details::carray reserved10; /// @brief stores the VMCB field at offset (0x05D8) bsl::uint64 rsp; /// @brief stores the VMCB field at offset (0x05E0) - bsl::details::carray reserved11; + bsl::details::carray reserved11; /// @brief stores the VMCB field at offset (0x05F8) bsl::uint64 rax; /// @brief stores the VMCB field at offset (0x0600) @@ -296,7 +297,7 @@ namespace mk /// @brief stores the VMCB field at offset (0x0640) bsl::uint64 cr2; /// @brief stores the VMCB field at offset (0x0648) - bsl::details::carray reserved12; + bsl::details::carray reserved12; /// @brief stores the VMCB field at offset (0x0668) bsl::uint64 g_pat; /// @brief stores the VMCB field at offset (0x0670) @@ -310,17 +311,8 @@ namespace mk /// @brief stores the VMCB field at offset (0x0690) bsl::uint64 lastexcpto; /// @brief stores the VMCB field at offset (0x0698) - bsl::details::carray reserved13; + bsl::details::carray reserved13; }; - - namespace details - { - /// @brief defined the expected size of the pdt_t struct - constexpr bsl::safe_uintmax EXPECTED_VMCB_T_SIZE{bsl::to_umax(HYPERVISOR_PAGE_SIZE)}; - - /// Check to make sure the pdt_t is the right size. - static_assert(sizeof(vmcb_t) == EXPECTED_VMCB_T_SIZE); - } } #pragma pack(pop) diff --git a/kernel/include/arm/aarch64/vmexit_log_pp_t.hpp b/kernel/include/arm/aarch64/vmexit_log_pp_t.hpp new file mode 100644 index 00000000..2c09e4e8 --- /dev/null +++ b/kernel/include/arm/aarch64/vmexit_log_pp_t.hpp @@ -0,0 +1,49 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_LOG_PP_T +#define VMEXIT_LOG_PP_T + +#include + +#include +#include + +namespace mk +{ + /// @class mk::vmexit_log_pp_t + /// + /// + /// @brief Stores information about each VMExit per PP + /// + struct vmexit_log_pp_t final + { + /// @brief stores the VMExit log + bsl::array log; + /// @brief stores the VMExit log circular cursor + bsl::safe_uintmax crsr; + }; +} + +#endif diff --git a/kernel/include/arm/aarch64/vmexit_log_record_t.hpp b/kernel/include/arm/aarch64/vmexit_log_record_t.hpp new file mode 100644 index 00000000..380b846c --- /dev/null +++ b/kernel/include/arm/aarch64/vmexit_log_record_t.hpp @@ -0,0 +1,90 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_LOG_RECORD_T +#define VMEXIT_LOG_RECORD_T + +#include + +namespace mk +{ + /// @struct mk::vmexit_log_record_t + /// + /// + /// @brief Stores information about each VMExit + /// + struct vmexit_log_record_t final + { + /// @brief stores the VMID that generated the exit + bsl::safe_uint16 vmid; + /// @brief stores the VPID that generated the exit + bsl::safe_uint16 vpid; + /// @brief stores the VPSID that generated the exit + bsl::safe_uint16 vpsid; + /// @brief stores the exit reason + bsl::safe_uintmax exit_reason; + /// @brief stores the exit qualification (Intel) or exit_info1 (AMD) + bsl::safe_uintmax ei1; + /// @brief stores the exit information (Intel) or exit_info2 (AMD) + bsl::safe_uintmax ei2; + /// @brief stores the exit input information (AMD) or ignored (Intel) + bsl::safe_uintmax ei3; + /// @brief stores rax + bsl::safe_uintmax rax; + /// @brief stores rbx + bsl::safe_uintmax rbx; + /// @brief stores rcx + bsl::safe_uintmax rcx; + /// @brief stores rdx + bsl::safe_uintmax rdx; + /// @brief stores rbp + bsl::safe_uintmax rbp; + /// @brief stores rsi + bsl::safe_uintmax rsi; + /// @brief stores rdi + bsl::safe_uintmax rdi; + /// @brief stores r8 + bsl::safe_uintmax r8; + /// @brief stores r9 + bsl::safe_uintmax r9; + /// @brief stores r10 + bsl::safe_uintmax r10; + /// @brief stores r11 + bsl::safe_uintmax r11; + /// @brief stores r12 + bsl::safe_uintmax r12; + /// @brief stores r13 + bsl::safe_uintmax r13; + /// @brief stores r14 + bsl::safe_uintmax r14; + /// @brief stores r15 + bsl::safe_uintmax r15; + /// @brief stores rsp + bsl::safe_uintmax rsp; + /// @brief stores rip + bsl::safe_uintmax rip; + }; +} + +#endif diff --git a/kernel/src/call_ext.hpp b/kernel/include/call_ext.hpp similarity index 100% rename from kernel/src/call_ext.hpp rename to kernel/include/call_ext.hpp diff --git a/kernel/include/execution_status_t.hpp b/kernel/include/execution_status_t.hpp new file mode 100644 index 00000000..532d31e4 --- /dev/null +++ b/kernel/include/execution_status_t.hpp @@ -0,0 +1,46 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef EXECUTION_STATUS_T_HPP +#define EXECUTION_STATUS_T_HPP + +#include + +namespace mk +{ + /// + /// @brief Defines which handler the current extension is executing + /// + enum class execution_status_t : bsl::uint8 + { + /// @brief defines that the _start handler is being executed + start_handler, + /// @brief defines that the bootstrap handler is being executed + bootstrap_handler, + /// @brief defines that the vmexit handler is being executed + vmexit_handler + }; +} + +#endif diff --git a/kernel/src/get_current_tls.hpp b/kernel/include/get_current_tls.hpp similarity index 100% rename from kernel/src/get_current_tls.hpp rename to kernel/include/get_current_tls.hpp diff --git a/kernel/include/map_page_flags.hpp b/kernel/include/map_page_flags.hpp new file mode 100644 index 00000000..325c1f7b --- /dev/null +++ b/kernel/include/map_page_flags.hpp @@ -0,0 +1,56 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MAP_PAGE_FLAGS_HPP +#define MAP_PAGE_FLAGS_HPP + +#include +#include + +namespace mk +{ + /// @brief Map a page with read permmissions (has no effect) + constexpr auto MAP_PAGE_READ{0x0000000000000001_umax}; + /// @brief Map a page with write permmissions + constexpr auto MAP_PAGE_WRITE{0x0000000000000002_umax}; + /// @brief Map a page with execute permmissions + constexpr auto MAP_PAGE_EXECUTE{0x0000000000000004_umax}; + + /// @brief Defines the auto release tag for no auto release + constexpr auto MAP_PAGE_NO_AUTO_RELEASE{0_i32}; + /// @brief Defines the auto release tag for alloc_page allocations + constexpr auto MAP_PAGE_AUTO_RELEASE_ALLOC_PAGE{1_i32}; + /// @brief Defines the auto release tag for alloc_huge allocations + constexpr auto MAP_PAGE_AUTO_RELEASE_ALLOC_HUGE{2_i32}; + /// @brief Defines the auto release tag for alloc_heap allocations + constexpr auto MAP_PAGE_AUTO_RELEASE_ALLOC_HEAP{3_i32}; + /// @brief Defines the auto release tag for stack allocations + constexpr auto MAP_PAGE_AUTO_RELEASE_STACK{4_i32}; + /// @brief Defines the auto release tag for tls allocations + constexpr auto MAP_PAGE_AUTO_RELEASE_TLS{5_i32}; + /// @brief Defines the auto release tag for ELF allocations + constexpr auto MAP_PAGE_AUTO_RELEASE_ELF{6_i32}; +} + +#endif diff --git a/kernel/include/page_pool_record_t.hpp b/kernel/include/page_pool_record_t.hpp new file mode 100644 index 00000000..8f8c11a5 --- /dev/null +++ b/kernel/include/page_pool_record_t.hpp @@ -0,0 +1,47 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef PAGE_POOL_RECORD_T_HPP +#define PAGE_POOL_RECORD_T_HPP + +#include +#include + +namespace mk +{ + /// @struct mk::page_pool_record_t + /// + /// + /// @brief Defines the layout of a page pool tag + /// + struct page_pool_record_t final + { + /// @brief stores the tag associated with this record + bsl::cstr_type tag; + /// @brief stores the number of bytes allocated with this record + bsl::safe_uintmax usd; + }; +} + +#endif diff --git a/kernel/src/page_t.hpp b/kernel/include/page_t.hpp similarity index 86% rename from kernel/src/page_t.hpp rename to kernel/include/page_t.hpp index 3f1a687a..77fe869b 100644 --- a/kernel/src/page_t.hpp +++ b/kernel/include/page_t.hpp @@ -25,7 +25,9 @@ #ifndef PAGE_T_HPP #define PAGE_T_HPP -#include +#include +#include +#include namespace mk { @@ -36,10 +38,8 @@ namespace mk /// struct page_t final { - /// @brief stores the virtual address of the page - bsl::safe_uintmax virt; - /// @brief stores the physical address of the page - bsl::safe_uintmax phys; + /// @brief stores the data in the page + bsl::details::carray data; }; } diff --git a/kernel/src/promote.hpp b/kernel/include/promote.hpp similarity index 100% rename from kernel/src/promote.hpp rename to kernel/include/promote.hpp diff --git a/kernel/src/return_to_mk.hpp b/kernel/include/return_to_mk.hpp similarity index 93% rename from kernel/src/return_to_mk.hpp rename to kernel/include/return_to_mk.hpp index 10ba0b96..ffd9ef61 100644 --- a/kernel/src/return_to_mk.hpp +++ b/kernel/include/return_to_mk.hpp @@ -33,7 +33,8 @@ namespace mk /// @brief Returns to the microkernel after the execution of call_ext. /// /// - /// @param status the status code to provide the microkernel on return + /// @param status the status code from the extension to forward to + /// the microkernel /// extern "C" void return_to_mk(bsl::exit_code const status) noexcept; } diff --git a/kernel/src/return_to_vmexit_loop.hpp b/kernel/include/return_to_vmexit_loop.hpp similarity index 100% rename from kernel/src/return_to_vmexit_loop.hpp rename to kernel/include/return_to_vmexit_loop.hpp diff --git a/kernel/include/serial_write_c.hpp b/kernel/include/serial_write_c.hpp new file mode 100644 index 00000000..079ce7ee --- /dev/null +++ b/kernel/include/serial_write_c.hpp @@ -0,0 +1,41 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef SERIAL_WRITE_C_HPP +#define SERIAL_WRITE_C_HPP + +#include + +namespace mk +{ + /// + /// @brief Writes a character "c" to the serial device. + /// + /// + /// @param c the character to write + /// + extern "C" void serial_write_c(bsl::char_type const c) noexcept; +} + +#endif diff --git a/kernel/include/serial_write_hex.hpp b/kernel/include/serial_write_hex.hpp new file mode 100644 index 00000000..16529f0a --- /dev/null +++ b/kernel/include/serial_write_hex.hpp @@ -0,0 +1,41 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef SERIAL_WRITE_HEX_HPP +#define SERIAL_WRITE_HEX_HPP + +#include + +namespace mk +{ + /// + /// @brief Writes a hexidecimal number "val" to the serial device. + /// + /// + /// @param val the hexidecimal number to write + /// + extern "C" void serial_write_hex(bsl::uint64 const val) noexcept; +} + +#endif diff --git a/kernel/src/vmexit_loop_entry.hpp b/kernel/include/vmexit_loop_entry.hpp similarity index 94% rename from kernel/src/vmexit_loop_entry.hpp rename to kernel/include/vmexit_loop_entry.hpp index f715d800..e6b8f459 100644 --- a/kernel/src/vmexit_loop_entry.hpp +++ b/kernel/include/vmexit_loop_entry.hpp @@ -31,6 +31,8 @@ namespace mk { /// /// @brief Executes the main VMExit loop + /// @return Returns bsl::exit_success on success, bsl::exit_failure + /// otherwise /// /// /// @return Returns bsl::exit_success on success and bsl::exit_failure diff --git a/kernel/include/x64/amd/vmcb_t.hpp b/kernel/include/x64/amd/vmcb_t.hpp new file mode 100644 index 00000000..eb56ef51 --- /dev/null +++ b/kernel/include/x64/amd/vmcb_t.hpp @@ -0,0 +1,320 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMCB_HPP +#define VMCB_HPP + +#include +#include +#include +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @brief defines the size of the reserved1 field in the VMCB + constexpr auto VMCB_RESERVED1_SIZE{0x24_umax}; + /// @brief defines the size of the reserved2 field in the VMCB + constexpr auto VMCB_RESERVED2_SIZE{0x3_umax}; + /// @brief defines the size of the reserved3 field in the VMCB + constexpr auto VMCB_RESERVED3_SIZE{0x4_umax}; + /// @brief defines the size of the reserved4 field in the VMCB + constexpr auto VMCB_RESERVED4_SIZE{0x8_umax}; + /// @brief defines the size of the reserved5 field in the VMCB + constexpr auto VMCB_RESERVED5_SIZE{0x8_umax}; + /// @brief defines the size of the reserved6 field in the VMCB + constexpr auto VMCB_RESERVED6_SIZE{0x2F0_umax}; + /// @brief defines the size of the reserved7 field in the VMCB + constexpr auto VMCB_RESERVED7_SIZE{0x2B_umax}; + /// @brief defines the size of the reserved8 field in the VMCB + constexpr auto VMCB_RESERVED8_SIZE{0x4_umax}; + /// @brief defines the size of the reserved9 field in the VMCB + constexpr auto VMCB_RESERVED9_SIZE{0x70_umax}; + /// @brief defines the size of the reserved10 field in the VMCB + constexpr auto VMCB_RESERVED10_SIZE{0x58_umax}; + /// @brief defines the size of the reserved11 field in the VMCB + constexpr auto VMCB_RESERVED11_SIZE{0x18_umax}; + /// @brief defines the size of the reserved12 field in the VMCB + constexpr auto VMCB_RESERVED12_SIZE{0x20_umax}; + /// @brief defines the size of the reserved13 field in the VMCB + constexpr auto VMCB_RESERVED13_SIZE{0x968_umax}; + /// @brief defines the size of the reserved13 field in the VMCB + constexpr auto VMCB_GIB_SIZE{0xF_umax}; + + /// @struct mk::vmcb_t + /// + /// + /// @brief The following defines the structure of the VMCB used by AMD's + /// hypervisor extensions. + /// + struct vmcb_t final + { + // ------------------------------------------------------------------------- + // Control Area + // ------------------------------------------------------------------------- + + /// @brief stores the VMCB field at offset (0x0000) + bsl::uint16 intercept_cr_read; + /// @brief stores the VMCB field at offset (0x0002) + bsl::uint16 intercept_cr_write; + /// @brief stores the VMCB field at offset (0x0004) + bsl::uint16 intercept_dr_read; + /// @brief stores the VMCB field at offset (0x0006) + bsl::uint16 intercept_dr_write; + /// @brief stores the VMCB field at offset (0x0008) + bsl::uint32 intercept_exception; + /// @brief stores the VMCB field at offset (0x000C) + bsl::uint32 intercept_instruction1; + /// @brief stores the VMCB field at offset (0x0010) + bsl::uint32 intercept_instruction2; + /// @brief stores the VMCB field at offset (0x0014) + bsl::uint32 intercept_instruction3; + /// @brief stores the VMCB field at offset (0x0018) + bsl::details::carray reserved1; + /// @brief stores the VMCB field at offset (0x003C) + bsl::uint16 pause_filter_threshold; + /// @brief stores the VMCB field at offset (0x003E) + bsl::uint16 pause_filter_count; + /// @brief stores the VMCB field at offset (0x0040) + bsl::uint64 iopm_base_pa; + /// @brief stores the VMCB field at offset (0x0048) + bsl::uint64 msrpm_base_pa; + /// @brief stores the VMCB field at offset (0x0050) + bsl::uint64 tsc_offset; + /// @brief stores the VMCB field at offset (0x0058) + bsl::uint32 guest_asid; + /// @brief stores the VMCB field at offset (0x005C) + bsl::uint8 tlb_control; + /// @brief stores the VMCB field at offset (0x005D) + bsl::details::carray reserved2; + /// @brief stores the VMCB field at offset (0x0060) + bsl::uint64 virtual_interrupt_a; + /// @brief stores the VMCB field at offset (0x0068) + bsl::uint64 virtual_interrupt_b; + /// @brief stores the VMCB field at offset (0x0070) + bsl::uint64 exitcode; + /// @brief stores the VMCB field at offset (0x0078) + bsl::uint64 exitinfo1; + /// @brief stores the VMCB field at offset (0x0080) + bsl::uint64 exitinfo2; + /// @brief stores the VMCB field at offset (0x0088) + bsl::uint64 exitininfo; + /// @brief stores the VMCB field at offset (0x0090) + bsl::uint64 ctls1; + /// @brief stores the VMCB field at offset (0x0098) + bsl::uint64 avic_apic_bar; + /// @brief stores the VMCB field at offset (0x00A0) + bsl::uint64 guest_pa_of_ghcb; + /// @brief stores the VMCB field at offset (0x00A8) + bsl::uint64 eventinj; + /// @brief stores the VMCB field at offset (0x00B0) + bsl::uint64 n_cr3; + /// @brief stores the VMCB field at offset (0x00B8) + bsl::uint64 ctls2; + /// @brief stores the VMCB field at offset (0x00C0) + bsl::uint32 vmcb_clean_bits; + /// @brief stores the VMCB field at offset (0x00C4) + bsl::details::carray reserved3; + /// @brief stores the VMCB field at offset (0x00C8) + bsl::uint64 nrip; + /// @brief stores the VMCB field at offset (0x00D0) + bsl::uint8 number_of_bytes_fetched; + /// @brief stores the VMCB field at offset (0x00D1) + bsl::details::carray guest_instruction_bytes; + /// @brief stores the VMCB field at offset (0x00E0) + bsl::uint64 avic_apic_backing_page_ptr; + /// @brief stores the VMCB field at offset (0x00E8) + bsl::details::carray reserved4; + /// @brief stores the VMCB field at offset (0x00F0) + bsl::uint64 avic_logical_table_ptr; + /// @brief stores the VMCB field at offset (0x00F8) + bsl::uint64 avic_physical_table_ptr; + /// @brief stores the VMCB field at offset (0x0100) + bsl::details::carray reserved5; + /// @brief stores the VMCB field at offset (0x0108) + bsl::uint64 vmsa_ptr; + /// @brief stores the VMCB field at offset (0x0110) + bsl::details::carray reserved6; + + // ------------------------------------------------------------------------- + // State Save Area + // ------------------------------------------------------------------------- + + /// @brief stores the VMCB field at offset (0x0400) + bsl::uint16 es_selector; + /// @brief stores the VMCB field at offset (0x0402) + bsl::uint16 es_attrib; + /// @brief stores the VMCB field at offset (0x0404) + bsl::uint32 es_limit; + /// @brief stores the VMCB field at offset (0x0408) + bsl::uint64 es_base; + /// @brief stores the VMCB field at offset (0x0410) + bsl::uint16 cs_selector; + /// @brief stores the VMCB field at offset (0x0412) + bsl::uint16 cs_attrib; + /// @brief stores the VMCB field at offset (0x0414) + bsl::uint32 cs_limit; + /// @brief stores the VMCB field at offset (0x0418) + bsl::uint64 cs_base; + /// @brief stores the VMCB field at offset (0x0420) + bsl::uint16 ss_selector; + /// @brief stores the VMCB field at offset (0x0422) + bsl::uint16 ss_attrib; + /// @brief stores the VMCB field at offset (0x0424) + bsl::uint32 ss_limit; + /// @brief stores the VMCB field at offset (0x0428) + bsl::uint64 ss_base; + /// @brief stores the VMCB field at offset (0x0430) + bsl::uint16 ds_selector; + /// @brief stores the VMCB field at offset (0x0432) + bsl::uint16 ds_attrib; + /// @brief stores the VMCB field at offset (0x0434) + bsl::uint32 ds_limit; + /// @brief stores the VMCB field at offset (0x0438) + bsl::uint64 ds_base; + /// @brief stores the VMCB field at offset (0x0440) + bsl::uint16 fs_selector; + /// @brief stores the VMCB field at offset (0x0442) + bsl::uint16 fs_attrib; + /// @brief stores the VMCB field at offset (0x0444) + bsl::uint32 fs_limit; + /// @brief stores the VMCB field at offset (0x0448) + bsl::uint64 fs_base; + /// @brief stores the VMCB field at offset (0x0450) + bsl::uint16 gs_selector; + /// @brief stores the VMCB field at offset (0x0452) + bsl::uint16 gs_attrib; + /// @brief stores the VMCB field at offset (0x0454) + bsl::uint32 gs_limit; + /// @brief stores the VMCB field at offset (0x0458) + bsl::uint64 gs_base; + /// @brief stores the VMCB field at offset (0x0460) + bsl::uint16 gdtr_selector; + /// @brief stores the VMCB field at offset (0x0462) + bsl::uint16 gdtr_attrib; + /// @brief stores the VMCB field at offset (0x0464) + bsl::uint32 gdtr_limit; + /// @brief stores the VMCB field at offset (0x0468) + bsl::uint64 gdtr_base; + /// @brief stores the VMCB field at offset (0x0470) + bsl::uint16 ldtr_selector; + /// @brief stores the VMCB field at offset (0x0472) + bsl::uint16 ldtr_attrib; + /// @brief stores the VMCB field at offset (0x0474) + bsl::uint32 ldtr_limit; + /// @brief stores the VMCB field at offset (0x0478) + bsl::uint64 ldtr_base; + /// @brief stores the VMCB field at offset (0x0480) + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) + bsl::uint16 idtr_selector; + /// @brief stores the VMCB field at offset (0x0482) + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) + bsl::uint16 idtr_attrib; + /// @brief stores the VMCB field at offset (0x0484) + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) + bsl::uint32 idtr_limit; + /// @brief stores the VMCB field at offset (0x0488) + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) + bsl::uint64 idtr_base; + /// @brief stores the VMCB field at offset (0x0490) + bsl::uint16 tr_selector; + /// @brief stores the VMCB field at offset (0x0492) + bsl::uint16 tr_attrib; + /// @brief stores the VMCB field at offset (0x0494) + bsl::uint32 tr_limit; + /// @brief stores the VMCB field at offset (0x0498) + bsl::uint64 tr_base; + /// @brief stores the VMCB field at offset (0x04A0) + bsl::details::carray reserved7; + /// @brief stores the VMCB field at offset (0x04CB) + bsl::uint8 cpl; + /// @brief stores the VMCB field at offset (0x04CC) + bsl::details::carray reserved8; + /// @brief stores the VMCB field at offset (0x04D0) + bsl::uint64 efer; + /// @brief stores the VMCB field at offset (0x04D8) + bsl::details::carray reserved9; + /// @brief stores the VMCB field at offset (0x0548) + bsl::uint64 cr4; + /// @brief stores the VMCB field at offset (0x0550) + bsl::uint64 cr3; + /// @brief stores the VMCB field at offset (0x0558) + bsl::uint64 cr0; + /// @brief stores the VMCB field at offset (0x0560) + bsl::uint64 dr7; + /// @brief stores the VMCB field at offset (0x0568) + bsl::uint64 dr6; + /// @brief stores the VMCB field at offset (0x0570) + bsl::uint64 rflags; + /// @brief stores the VMCB field at offset (0x0578) + bsl::uint64 rip; + /// @brief stores the VMCB field at offset (0x0580) + bsl::details::carray reserved10; + /// @brief stores the VMCB field at offset (0x05D8) + bsl::uint64 rsp; + /// @brief stores the VMCB field at offset (0x05E0) + bsl::details::carray reserved11; + /// @brief stores the VMCB field at offset (0x05F8) + bsl::uint64 rax; + /// @brief stores the VMCB field at offset (0x0600) + bsl::uint64 star; + /// @brief stores the VMCB field at offset (0x0608) + bsl::uint64 lstar; + /// @brief stores the VMCB field at offset (0x0610) + bsl::uint64 cstar; + /// @brief stores the VMCB field at offset (0x0618) + bsl::uint64 sfmask; + /// @brief stores the VMCB field at offset (0x0620) + bsl::uint64 kernel_gs_base; + /// @brief stores the VMCB field at offset (0x0628) + bsl::uint64 sysenter_cs; + /// @brief stores the VMCB field at offset (0x0630) + bsl::uint64 sysenter_esp; + /// @brief stores the VMCB field at offset (0x0638) + bsl::uint64 sysenter_eip; + /// @brief stores the VMCB field at offset (0x0640) + bsl::uint64 cr2; + /// @brief stores the VMCB field at offset (0x0648) + bsl::details::carray reserved12; + /// @brief stores the VMCB field at offset (0x0668) + bsl::uint64 g_pat; + /// @brief stores the VMCB field at offset (0x0670) + bsl::uint64 dbgctl; + /// @brief stores the VMCB field at offset (0x0678) + bsl::uint64 br_from; + /// @brief stores the VMCB field at offset (0x0680) + bsl::uint64 br_to; + /// @brief stores the VMCB field at offset (0x0688) + bsl::uint64 lastexcpfrom; + /// @brief stores the VMCB field at offset (0x0690) + bsl::uint64 lastexcpto; + /// @brief stores the VMCB field at offset (0x0698) + bsl::details::carray reserved13; + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/x64/general_purpose_regs_t.hpp b/kernel/include/x64/general_purpose_regs_t.hpp new file mode 100644 index 00000000..b741dd79 --- /dev/null +++ b/kernel/include/x64/general_purpose_regs_t.hpp @@ -0,0 +1,79 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef GENERAL_PURPOSE_REGS_T_HPP +#define GENERAL_PURPOSE_REGS_T_HPP + +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @struct mk::general_purpose_regs_t + /// + /// + /// @brief Stores the state of the general purpose registers. Note + /// that this storage is only used when swapping from one VPS to + /// another. Otherwise, an extension's TLS block is used instead + /// to access the general purpose registers as they are faster. + /// + struct general_purpose_regs_t final + { + /// @brief stores the value of rax (0x000) + bsl::uintmax rax; + /// @brief stores the value of rbx (0x008) + bsl::uintmax rbx; + /// @brief stores the value of rcx (0x010) + bsl::uintmax rcx; + /// @brief stores the value of rdx (0x018) + bsl::uintmax rdx; + /// @brief stores the value of rbp (0x020) + bsl::uintmax rbp; + /// @brief stores the value of rsi (0x028) + bsl::uintmax rsi; + /// @brief stores the value of rdi (0x030) + bsl::uintmax rdi; + /// @brief stores the value of r8 (0x038) + bsl::uintmax r8; + /// @brief stores the value of r9 (0x040) + bsl::uintmax r9; + /// @brief stores the value of r10 (0x048) + bsl::uintmax r10; + /// @brief stores the value of r11 (0x050) + bsl::uintmax r11; + /// @brief stores the value of r12 (0x058) + bsl::uintmax r12; + /// @brief stores the value of r13 (0x060) + bsl::uintmax r13; + /// @brief stores the value of r14 (0x068) + bsl::uintmax r14; + /// @brief stores the value of r15 (0x070) + bsl::uintmax r15; + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/x64/intel/invept_descriptor_t.hpp b/kernel/include/x64/intel/invept_descriptor_t.hpp new file mode 100644 index 00000000..68641dec --- /dev/null +++ b/kernel/include/x64/intel/invept_descriptor_t.hpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INVEPT_DESCRIPTOR_T +#define INVEPT_DESCRIPTOR_T + +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @struct mk::invept_descriptor_t + /// + /// + /// @brief Stores information needed to execute invept + /// + struct invept_descriptor_t final + { + /// @brief stores the eptp to invalidate + bsl::uintmax eptp; + /// @brief reserved + bsl::uintmax reserved; + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/include/x64/intel/invvpid_descriptor_t.hpp b/kernel/include/x64/intel/invvpid_descriptor_t.hpp new file mode 100644 index 00000000..de9b999d --- /dev/null +++ b/kernel/include/x64/intel/invvpid_descriptor_t.hpp @@ -0,0 +1,56 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INVVPID_DESCRIPTOR_T +#define INVVPID_DESCRIPTOR_T + +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @struct mk::invvpid_descriptor_t + /// + /// + /// @brief Stores information needed to execute invvpid + /// + struct invvpid_descriptor_t final + { + /// @brief stores the vpid to invalidate + bsl::uint16 vpid; + /// @brief reserved + bsl::uint16 reserved1; + /// @brief reserved + bsl::uint16 reserved2; + /// @brief reserved + bsl::uint16 reserved3; + /// @brief stores the address to invalidate + bsl::uintmax addr; + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/src/x64/intel/vmcs_missing_registers_t.hpp b/kernel/include/x64/intel/vmcs_missing_registers_t.hpp similarity index 59% rename from kernel/src/x64/intel/vmcs_missing_registers_t.hpp rename to kernel/include/x64/intel/vmcs_missing_registers_t.hpp index 0c5b00d1..3eb942bd 100644 --- a/kernel/src/x64/intel/vmcs_missing_registers_t.hpp +++ b/kernel/include/x64/intel/vmcs_missing_registers_t.hpp @@ -40,65 +40,34 @@ namespace mk /// struct vmcs_missing_registers_t final { - /// @brief TODO remove me - bsl::uintmax ignored_rax; - /// @brief TODO remove me - bsl::uintmax ignored_rbx; - /// @brief TODO remove me - bsl::uintmax ignored_rcx; - /// @brief TODO remove me - bsl::uintmax ignored_rdx; - /// @brief TODO remove me - bsl::uintmax ignored_rbp; - /// @brief TODO remove me - bsl::uintmax ignored_rsi; - /// @brief TODO remove me - bsl::uintmax ignored_rdi; - /// @brief TODO remove me - bsl::uintmax ignored_r8; - /// @brief TODO remove me - bsl::uintmax ignored_r9; - /// @brief TODO remove me - bsl::uintmax ignored_r10; - /// @brief TODO remove me - bsl::uintmax ignored_r11; - /// @brief TODO remove me - bsl::uintmax ignored_r12; - /// @brief TODO remove me - bsl::uintmax ignored_r13; - /// @brief TODO remove me - bsl::uintmax ignored_r14; - /// @brief TODO remove me - bsl::uintmax ignored_r15; - - /// @brief stores the value of cr2 (0x078) + /// @brief stores the value of cr2 (0x000) bsl::uintmax cr2; - /// @brief stores the value of dr6 (0x080) + /// @brief stores the value of dr6 (0x008) bsl::uintmax dr6; - /// @brief stores the guest value of ia32_star (0x088) + /// @brief stores the guest value of ia32_star (0x010) bsl::uintmax guest_ia32_star; - /// @brief stores the guest value of ia32_lstar (0x090) + /// @brief stores the guest value of ia32_lstar (0x018) bsl::uintmax guest_ia32_lstar; - /// @brief stores the guest value of ia32_cstar (0x098) + /// @brief stores the guest value of ia32_cstar (0x020) bsl::uintmax guest_ia32_cstar; - /// @brief stores the guest value of ia32_fmask (0x0A0) + /// @brief stores the guest value of ia32_fmask (0x028) bsl::uintmax guest_ia32_fmask; - /// @brief stores the guest value of ia32_kernel_gs_base (0x0A8) + /// @brief stores the guest value of ia32_kernel_gs_base (0x030) bsl::uintmax guest_ia32_kernel_gs_base; - /// @brief stores the host value of ia32_star (0x0B0) + /// @brief stores the host value of ia32_star (0x038) bsl::uintmax host_ia32_star; - /// @brief stores the host value of ia32_lstar (0x0B8) + /// @brief stores the host value of ia32_lstar (0x040) bsl::uintmax host_ia32_lstar; - /// @brief stores the host value of ia32_cstar (0x0C0) + /// @brief stores the host value of ia32_cstar (0x048) bsl::uintmax host_ia32_cstar; - /// @brief stores the host value of ia32_fmask (0x0C8) + /// @brief stores the host value of ia32_fmask (0x050) bsl::uintmax host_ia32_fmask; - /// @brief stores the host value of ia32_kernel_gs_base (0x0D0) + /// @brief stores the host value of ia32_kernel_gs_base (0x058) bsl::uintmax host_ia32_kernel_gs_base; - /// @brief stores the launch status of the hypervisor (0x0D8) + /// @brief stores the launch status of the hypervisor (0x060) bsl::uintmax launched; }; } diff --git a/kernel/include/x64/intel/vmcs_t.hpp b/kernel/include/x64/intel/vmcs_t.hpp new file mode 100644 index 00000000..95ae386d --- /dev/null +++ b/kernel/include/x64/intel/vmcs_t.hpp @@ -0,0 +1,392 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMCS_HPP +#define VMCS_HPP + +#include +#include +#include +#include + +#pragma pack(push, 1) + +namespace mk +{ + /// @brief the size of reserved field + constexpr auto RESERVED_SIZE{0xFFC_umax}; + + /// @brief defines an unusable segment descriptor + constexpr auto VMCS_UNUSABLE_SEGMENT{0x10000_u32}; + + /// @brief encoding for: virtual_processor_identifier + constexpr auto VMCS_VIRTUAL_PROCESSOR_IDENTIFIER{0x0000_umax}; + /// @brief encoding for: posted_interrupt_notification_vector + constexpr auto VMCS_POSTED_INTERRUPT_NOTIFICATION_VECTOR{0x0002_umax}; + /// @brief encoding for: eptp_index + constexpr auto VMCS_EPTP_INDEX{0x0004_umax}; + + /// @brief encoding for: guest_es_selector + constexpr auto VMCS_GUEST_ES_SELECTOR{0x0800_umax}; + /// @brief encoding for: guest_cs_selector + constexpr auto VMCS_GUEST_CS_SELECTOR{0x0802_umax}; + /// @brief encoding for: guest_ss_selector + constexpr auto VMCS_GUEST_SS_SELECTOR{0x0804_umax}; + /// @brief encoding for: guest_ds_selector + constexpr auto VMCS_GUEST_DS_SELECTOR{0x0806_umax}; + /// @brief encoding for: guest_fs_selector + constexpr auto VMCS_GUEST_FS_SELECTOR{0x0808_umax}; + /// @brief encoding for: guest_gs_selector + constexpr auto VMCS_GUEST_GS_SELECTOR{0x080A_umax}; + /// @brief encoding for: guest_ldtr_selector + constexpr auto VMCS_GUEST_LDTR_SELECTOR{0x080C_umax}; + /// @brief encoding for: guest_tr_selector + constexpr auto VMCS_GUEST_TR_SELECTOR{0x080E_umax}; + /// @brief encoding for: guest_interrupt_status + constexpr auto VMCS_GUEST_INTERRUPT_STATUS{0x0810_umax}; + /// @brief encoding for: pml_index + constexpr auto VMCS_PML_INDEX{0x0812_umax}; + + /// @brief encoding for: host_es_selector + constexpr auto VMCS_HOST_ES_SELECTOR{0x0C00_umax}; + /// @brief encoding for: host_cs_selector + constexpr auto VMCS_HOST_CS_SELECTOR{0x0C02_umax}; + /// @brief encoding for: host_ss_selector + constexpr auto VMCS_HOST_SS_SELECTOR{0x0C04_umax}; + /// @brief encoding for: host_ds_selector + constexpr auto VMCS_HOST_DS_SELECTOR{0x0C06_umax}; + /// @brief encoding for: host_fs_selector + constexpr auto VMCS_HOST_FS_SELECTOR{0x0C08_umax}; + /// @brief encoding for: host_gs_selector + constexpr auto VMCS_HOST_GS_SELECTOR{0x0C0A_umax}; + /// @brief encoding for: host_tr_selector + constexpr auto VMCS_HOST_TR_SELECTOR{0x0C0C_umax}; + + /// @brief encoding for: address_of_io_bitmap_a + constexpr auto VMCS_ADDRESS_OF_IO_BITMAP_A{0x2000_umax}; + /// @brief encoding for: address_of_io_bitmap_b + constexpr auto VMCS_ADDRESS_OF_IO_BITMAP_B{0x2002_umax}; + /// @brief encoding for: address_of_msr_bitmaps + constexpr auto VMCS_ADDRESS_OF_MSR_BITMAPS{0x2004_umax}; + /// @brief encoding for: vmexit_msr_store_address + constexpr auto VMCS_VMEXIT_MSR_STORE_ADDRESS{0x2006_umax}; + /// @brief encoding for: vmexit_msr_load_address + constexpr auto VMCS_VMEXIT_MSR_LOAD_ADDRESS{0x2008_umax}; + /// @brief encoding for: vmentry_msr_load_address + constexpr auto VMCS_VMENTRY_MSR_LOAD_ADDRESS{0x200A_umax}; + /// @brief encoding for: executive_vmcs_pointer + constexpr auto VMCS_EXECUTIVE_VMCS_POINTER{0x200C_umax}; + /// @brief encoding for: pml_address + constexpr auto VMCS_PML_ADDRESS{0x200E_umax}; + /// @brief encoding for: tsc_offset + constexpr auto VMCS_TSC_OFFSET{0x2010_umax}; + /// @brief encoding for: virtual_apic_address + constexpr auto VMCS_VIRTUAL_APIC_ADDRESS{0x2012_umax}; + /// @brief encoding for: apic_access_address + constexpr auto VMCS_APIC_ACCESS_ADDRESS{0x2014_umax}; + /// @brief encoding for: posted_interrupt_descriptor_address + constexpr auto VMCS_POSTED_INTERRUPT_DESCRIPTOR_ADDRESS{0x2016_umax}; + /// @brief encoding for: vm_function_controls + constexpr auto VMCS_VM_FUNCTION_CONTROLS{0x2018_umax}; + /// @brief encoding for: ept_pointer + constexpr auto VMCS_EPT_POINTER{0x201A_umax}; + /// @brief encoding for: eoi_exit_bitmap0 + constexpr auto VMCS_EOI_EXIT_BITMAP0{0x201C_umax}; + /// @brief encoding for: eoi_exit_bitmap1 + constexpr auto VMCS_EOI_EXIT_BITMAP1{0x201E_umax}; + /// @brief encoding for: eoi_exit_bitmap2 + constexpr auto VMCS_EOI_EXIT_BITMAP2{0x2020_umax}; + /// @brief encoding for: eoi_exit_bitmap3 + constexpr auto VMCS_EOI_EXIT_BITMAP3{0x2022_umax}; + /// @brief encoding for: eptp_list_address + constexpr auto VMCS_EPTP_LIST_ADDRESS{0x2024_umax}; + /// @brief encoding for: vmread_bitmap_address + constexpr auto VMCS_VMREAD_BITMAP_ADDRESS{0x2026_umax}; + /// @brief encoding for: vmwrite_bitmap_address + constexpr auto VMCS_VMWRITE_BITMAP_ADDRESS{0x2028_umax}; + /// @brief encoding for: virt_exception_information_address + constexpr auto VMCS_VIRT_EXCEPTION_INFORMATION_ADDRESS{0x202A_umax}; + /// @brief encoding for: xss_exiting_bitmap + constexpr auto VMCS_XSS_EXITING_BITMAP{0x202C_umax}; + /// @brief encoding for: encls_exiting_bitmap + constexpr auto VMCS_ENCLS_EXITING_BITMAP{0x202E_umax}; + /// @brief encoding for: sub_page_permission_table_pointer + constexpr auto VMCS_SUB_PAGE_PERMISSION_TABLE_POINTER{0x2030_umax}; + /// @brief encoding for: tls_multiplier + constexpr auto VMCS_TLS_MULTIPLIER{0x2032_umax}; + + /// @brief encoding for: guest_physical_address + constexpr auto VMCS_GUEST_PHYSICAL_ADDRESS{0x2400_umax}; + + /// @brief encoding for: vmcs_link_pointer + constexpr auto VMCS_VMCS_LINK_POINTER{0x2800_umax}; + /// @brief encoding for: guest_ia32_debugctl + constexpr auto VMCS_GUEST_IA32_DEBUGCTL{0x2802_umax}; + /// @brief encoding for: guest_ia32_pat + constexpr auto VMCS_GUEST_IA32_PAT{0x2804_umax}; + /// @brief encoding for: guest_ia32_efer + constexpr auto VMCS_GUEST_IA32_EFER{0x2806_umax}; + /// @brief encoding for: guest_ia32_perf_global_ctrl + constexpr auto VMCS_GUEST_IA32_PERF_GLOBAL_CTRL{0x2808_umax}; + /// @brief encoding for: guest_pdpte0 + constexpr auto VMCS_GUEST_PDPTE0{0x280A_umax}; + /// @brief encoding for: guest_pdpte1 + constexpr auto VMCS_GUEST_PDPTE1{0x280C_umax}; + /// @brief encoding for: guest_pdpte2 + constexpr auto VMCS_GUEST_PDPTE2{0x280E_umax}; + /// @brief encoding for: guest_pdpte3 + constexpr auto VMCS_GUEST_PDPTE3{0x2810_umax}; + /// @brief encoding for: guest_ia32_bndcfgs + constexpr auto VMCS_GUEST_IA32_BNDCFGS{0x2812_umax}; + /// @brief encoding for: guest_rtit_ctl + constexpr auto VMCS_GUEST_RTIT_CTL{0x2814_umax}; + + /// @brief encoding for: host_ia32_pat + constexpr auto VMCS_HOST_IA32_PAT{0x2C00_umax}; + /// @brief encoding for: host_ia32_efer + constexpr auto VMCS_HOST_IA32_EFER{0x2C02_umax}; + /// @brief encoding for: host_ia32_perf_global_ctrl + constexpr auto VMCS_HOST_IA32_PERF_GLOBAL_CTRL{0x2C04_umax}; + + /// @brief encoding for: pin_based_vm_execution_ctls + constexpr auto VMCS_PIN_BASED_VM_EXECUTION_CTLS{0x4000_umax}; + /// @brief encoding for: primary_proc_based_vm_execution_ctls + constexpr auto VMCS_PRIMARY_PROC_BASED_VM_EXECUTION_CTLS{0x4002_umax}; + /// @brief encoding for: exception_bitmap + constexpr auto VMCS_EXCEPTION_BITMAP{0x4004_umax}; + /// @brief encoding for: page_fault_error_code_mask + constexpr auto VMCS_PAGE_FAULT_ERROR_CODE_MASK{0x4006_umax}; + /// @brief encoding for: page_fault_error_code_match + constexpr auto VMCS_PAGE_FAULT_ERROR_CODE_MATCH{0x4008_umax}; + /// @brief encoding for: cr3_target_count + constexpr auto VMCS_CR3_TARGET_COUNT{0x400A_umax}; + /// @brief encoding for: vmexit_ctls + constexpr auto VMCS_VMEXIT_CTLS{0x400C_umax}; + /// @brief encoding for: vmexit_msr_store_count + constexpr auto VMCS_VMEXIT_MSR_STORE_COUNT{0x400E_umax}; + /// @brief encoding for: vmexit_msr_load_count + constexpr auto VMCS_VMEXIT_MSR_LOAD_COUNT{0x4010_umax}; + /// @brief encoding for: vmentry_ctls + constexpr auto VMCS_VMENTRY_CTLS{0x4012_umax}; + /// @brief encoding for: vmentry_msr_load_count + constexpr auto VMCS_VMENTRY_MSR_LOAD_COUNT{0x4014_umax}; + /// @brief encoding for: vmentry_interrupt_information_field + constexpr auto VMCS_VMENTRY_INTERRUPT_INFORMATION_FIELD{0x4016_umax}; + /// @brief encoding for: vmentry_exception_error_code + constexpr auto VMCS_VMENTRY_EXCEPTION_ERROR_CODE{0x4018_umax}; + /// @brief encoding for: vmentry_instruction_length + constexpr auto VMCS_VMENTRY_INSTRUCTION_LENGTH{0x401A_umax}; + /// @brief encoding for: tpr_threshold + constexpr auto VMCS_TPR_THRESHOLD{0x401C_umax}; + /// @brief encoding for: secondary_proc_based_vm_execution_ctls + constexpr auto VMCS_SECONDARY_PROC_BASED_VM_EXECUTION_CTLS{0x401E_umax}; + /// @brief encoding for: ple_gap + constexpr auto VMCS_PLE_GAP{0x4020_umax}; + /// @brief encoding for: ple_window + constexpr auto VMCS_PLE_WINDOW{0x4022_umax}; + + /// @brief encoding for: vm_instruction_error + constexpr auto VMCS_VM_INSTRUCTION_ERROR{0x4400_umax}; + /// @brief encoding for: exit_reason + constexpr auto VMCS_EXIT_REASON{0x4402_umax}; + /// @brief encoding for: vmexit_interruption_information + constexpr auto VMCS_VMEXIT_INTERRUPTION_INFORMATION{0x4404_umax}; + /// @brief encoding for: vmexit_interruption_error_code + constexpr auto VMCS_VMEXIT_INTERRUPTION_ERROR_CODE{0x4406_umax}; + /// @brief encoding for: idt_vectoring_information_field + constexpr auto VMCS_IDT_VECTORING_INFORMATION_FIELD{0x4408_umax}; + /// @brief encoding for: idt_vectoring_error_code + constexpr auto VMCS_IDT_VECTORING_ERROR_CODE{0x440A_umax}; + /// @brief encoding for: vmexit_instruction_length + constexpr auto VMCS_VMEXIT_INSTRUCTION_LENGTH{0x440C_umax}; + /// @brief encoding for: vmexit_instruction_information + constexpr auto VMCS_VMEXIT_INSTRUCTION_INFORMATION{0x440E_umax}; + + /// @brief encoding for: guest_es_limit + constexpr auto VMCS_GUEST_ES_LIMIT{0x4800_umax}; + /// @brief encoding for: guest_cs_limit + constexpr auto VMCS_GUEST_CS_LIMIT{0x4802_umax}; + /// @brief encoding for: guest_ss_limit + constexpr auto VMCS_GUEST_SS_LIMIT{0x4804_umax}; + /// @brief encoding for: guest_ds_limit + constexpr auto VMCS_GUEST_DS_LIMIT{0x4806_umax}; + /// @brief encoding for: guest_fs_limit + constexpr auto VMCS_GUEST_FS_LIMIT{0x4808_umax}; + /// @brief encoding for: guest_gs_limit + constexpr auto VMCS_GUEST_GS_LIMIT{0x480A_umax}; + /// @brief encoding for: guest_ldtr_limit + constexpr auto VMCS_GUEST_LDTR_LIMIT{0x480C_umax}; + /// @brief encoding for: guest_tr_limit + constexpr auto VMCS_GUEST_TR_LIMIT{0x480E_umax}; + /// @brief encoding for: guest_gdtr_limit + constexpr auto VMCS_GUEST_GDTR_LIMIT{0x4810_umax}; + /// @brief encoding for: guest_idtr_limit + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) + constexpr auto VMCS_GUEST_IDTR_LIMIT{0x4812_umax}; + /// @brief encoding for: guest_es_access_rights + constexpr auto VMCS_GUEST_ES_ACCESS_RIGHTS{0x4814_umax}; + /// @brief encoding for: guest_cs_access_rights + constexpr auto VMCS_GUEST_CS_ACCESS_RIGHTS{0x4816_umax}; + /// @brief encoding for: guest_ss_access_rights + constexpr auto VMCS_GUEST_SS_ACCESS_RIGHTS{0x4818_umax}; + /// @brief encoding for: guest_ds_access_rights + constexpr auto VMCS_GUEST_DS_ACCESS_RIGHTS{0x481A_umax}; + /// @brief encoding for: guest_fs_access_rights + constexpr auto VMCS_GUEST_FS_ACCESS_RIGHTS{0x481C_umax}; + /// @brief encoding for: guest_gs_access_rights + constexpr auto VMCS_GUEST_GS_ACCESS_RIGHTS{0x481E_umax}; + /// @brief encoding for: guest_ldtr_access_rights + constexpr auto VMCS_GUEST_LDTR_ACCESS_RIGHTS{0x4820_umax}; + /// @brief encoding for: guest_tr_access_rights + constexpr auto VMCS_GUEST_TR_ACCESS_RIGHTS{0x4822_umax}; + /// @brief encoding for: guest_interruptibility_state + constexpr auto VMCS_GUEST_INTERRUPTIBILITY_STATE{0x4824_umax}; + /// @brief encoding for: guest_activity_state + constexpr auto VMCS_GUEST_ACTIVITY_STATE{0x4826_umax}; + /// @brief encoding for: guest_smbase + constexpr auto VMCS_GUEST_SMBASE{0x4828_umax}; + /// @brief encoding for: guest_ia32_sysenter_cs + constexpr auto VMCS_GUEST_IA32_SYSENTER_CS{0x482A_umax}; + /// @brief encoding for: vmx_preemption_timer_value + constexpr auto VMCS_VMX_PREEMPTION_TIMER_VALUE{0x482E_umax}; + + /// @brief encoding for: host_ia32_sysenter_cs + constexpr auto VMCS_HOST_IA32_SYSENTER_CS{0x4C00_umax}; + + /// @brief encoding for: cr0_guest_host_mask + constexpr auto VMCS_CR0_GUEST_HOST_MASK{0x6000_umax}; + /// @brief encoding for: cr4_guest_host_mask + constexpr auto VMCS_CR4_GUEST_HOST_MASK{0x6002_umax}; + /// @brief encoding for: cr0_read_shadow + constexpr auto VMCS_CR0_READ_SHADOW{0x6004_umax}; + /// @brief encoding for: cr4_read_shadow + constexpr auto VMCS_CR4_READ_SHADOW{0x6006_umax}; + /// @brief encoding for: cr3_target_value0 + constexpr auto VMCS_CR3_TARGET_VALUE0{0x6008_umax}; + /// @brief encoding for: cr3_target_value1 + constexpr auto VMCS_CR3_TARGET_VALUE1{0x600A_umax}; + /// @brief encoding for: cr3_target_value2 + constexpr auto VMCS_CR3_TARGET_VALUE2{0x600C_umax}; + /// @brief encoding for: cr3_target_value3 + constexpr auto VMCS_CR3_TARGET_VALUE3{0x600E_umax}; + + /// @brief encoding for: exit_qualification + constexpr auto VMCS_EXIT_QUALIFICATION{0x6400_umax}; + /// @brief encoding for: io_rcx + constexpr auto VMCS_IO_RCX{0x6402_umax}; + /// @brief encoding for: io_rsi + constexpr auto VMCS_IO_RSI{0x6404_umax}; + /// @brief encoding for: io_rdi + constexpr auto VMCS_IO_RDI{0x6406_umax}; + /// @brief encoding for: io_rip + constexpr auto VMCS_IO_RIP{0x6408_umax}; + /// @brief encoding for: guest_linear_address + constexpr auto VMCS_GUEST_LINEAR_ADDRESS{0x640A_umax}; + + /// @brief encoding for: guest_cr0 + constexpr auto VMCS_GUEST_CR0{0x6800_umax}; + /// @brief encoding for: guest_cr3 + constexpr auto VMCS_GUEST_CR3{0x6802_umax}; + /// @brief encoding for: guest_cr4 + constexpr auto VMCS_GUEST_CR4{0x6804_umax}; + /// @brief encoding for: guest_es_base + constexpr auto VMCS_GUEST_ES_BASE{0x6806_umax}; + /// @brief encoding for: guest_cs_base + constexpr auto VMCS_GUEST_CS_BASE{0x6808_umax}; + /// @brief encoding for: guest_ss_base + constexpr auto VMCS_GUEST_SS_BASE{0x680A_umax}; + /// @brief encoding for: guest_ds_base + constexpr auto VMCS_GUEST_DS_BASE{0x680C_umax}; + /// @brief encoding for: guest_fs_base + constexpr auto VMCS_GUEST_FS_BASE{0x680E_umax}; + /// @brief encoding for: guest_gs_base + constexpr auto VMCS_GUEST_GS_BASE{0x6810_umax}; + /// @brief encoding for: guest_ldtr_base + constexpr auto VMCS_GUEST_LDTR_BASE{0x6812_umax}; + /// @brief encoding for: guest_tr_base + constexpr auto VMCS_GUEST_TR_BASE{0x6814_umax}; + /// @brief encoding for: guest_gdtr_base + constexpr auto VMCS_GUEST_GDTR_BASE{0x6816_umax}; + /// @brief encoding for: guest_idtr_base + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) + constexpr auto VMCS_GUEST_IDTR_BASE{0x6818_umax}; + /// @brief encoding for: guest_dr7 + constexpr auto VMCS_GUEST_DR7{0x681A_umax}; + /// @brief encoding for: guest_rsp + constexpr auto VMCS_GUEST_RSP{0x681C_umax}; + /// @brief encoding for: guest_rip + constexpr auto VMCS_GUEST_RIP{0x681E_umax}; + /// @brief encoding for: guest_rflags + constexpr auto VMCS_GUEST_RFLAGS{0x6820_umax}; + /// @brief encoding for: guest_pending_debug_exceptions + constexpr auto VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS{0x6822_umax}; + /// @brief encoding for: guest_ia32_sysenter_esp + constexpr auto VMCS_GUEST_IA32_SYSENTER_ESP{0x6824_umax}; + /// @brief encoding for: guest_ia32_sysenter_eip + constexpr auto VMCS_GUEST_IA32_SYSENTER_EIP{0x6826_umax}; + + /// @brief encoding for: host_cr0 + constexpr auto VMCS_HOST_CR0{0x6C00_umax}; + /// @brief encoding for: host_cr3 + constexpr auto VMCS_HOST_CR3{0x6C02_umax}; + /// @brief encoding for: host_cr4 + constexpr auto VMCS_HOST_CR4{0x6C04_umax}; + /// @brief encoding for: host_fs_base + constexpr auto VMCS_HOST_FS_BASE{0x6C06_umax}; + /// @brief encoding for: host_gs_base + constexpr auto VMCS_HOST_GS_BASE{0x6C08_umax}; + /// @brief encoding for: host_tr_baseD + constexpr auto VMCS_HOST_TR_BASE{0x6C0A_umax}; + /// @brief encoding for: host_gdtr_base + constexpr auto VMCS_HOST_GDTR_BASE{0x6C0C_umax}; + /// @brief encoding for: host_idtr_base + constexpr auto VMCS_HOST_IDTR_BASE{0x6C0E_umax}; + /// @brief encoding for: host_ia32_sysenter_esp + constexpr auto VMCS_HOST_IA32_SYSENTER_ESP{0x6C10_umax}; + /// @brief encoding for: host_ia32_sysenter_eip + constexpr auto VMCS_HOST_IA32_SYSENTER_EIP{0x6C12_umax}; + /// @brief encoding for: host_rsp + constexpr auto VMCS_HOST_RSP{0x6C14_umax}; + /// @brief encoding for: host_rip + constexpr auto VMCS_HOST_RIP{0x6C16_umax}; + + /// @struct mk::vmcs_t + /// + /// + /// @brief The following defines the structure of the VMCS used by + /// Intel's hypervisor extensions. + /// + struct vmcs_t final + { + /// @brief defines the revision ID + bsl::uint32 revision_id; + + /// @brief reserved + bsl::details::carray reserved; + }; +} + +#pragma pack(pop) + +#endif diff --git a/kernel/src/x64/pdpt_t.hpp b/kernel/include/x64/pdpt_t.hpp similarity index 73% rename from kernel/src/x64/pdpt_t.hpp rename to kernel/include/x64/pdpt_t.hpp index 8c799308..225e2b41 100644 --- a/kernel/src/x64/pdpt_t.hpp +++ b/kernel/include/x64/pdpt_t.hpp @@ -35,8 +35,8 @@ namespace mk { - /// @brief defined the expected size of the pdpt_t struct - constexpr bsl::safe_uintmax NUM_PDPT_ENTRIES{bsl::to_umax(512)}; + /// @brief defines total number of entries in the pdpt + constexpr auto NUM_PDPT_ENTRIES{512_umax}; /// @struct mk::pdpt_t /// @@ -45,18 +45,9 @@ namespace mk /// struct pdpt_t final { - /// @brief stores the entires in the table - bsl::array entries; + /// @brief stores the entries for this page table + bsl::array entries; }; - - namespace details - { - /// @brief defined the expected size of the pdpt_t struct - constexpr bsl::safe_uintmax EXPECTED_PDPT_T_SIZE{bsl::to_umax(HYPERVISOR_PAGE_SIZE)}; - - /// Check to make sure the pdpt_t is the right size. - static_assert(sizeof(pdpt_t) == EXPECTED_PDPT_T_SIZE); - } } #pragma pack(pop) diff --git a/loader/include/interface/cpp/x64/pdpte_t.hpp b/kernel/include/x64/pdpte_t.hpp similarity index 70% rename from loader/include/interface/cpp/x64/pdpte_t.hpp rename to kernel/include/x64/pdpte_t.hpp index af446528..d4114608 100644 --- a/loader/include/interface/cpp/x64/pdpte_t.hpp +++ b/kernel/include/x64/pdpte_t.hpp @@ -25,15 +25,13 @@ #ifndef PDPTE_T_HPP #define PDPTE_T_HPP +#include + #pragma pack(push, 1) -#include -#include -#include - -namespace loader +namespace mk { - /// @struct loader::pdpte_t + /// @struct mk::pdpte_t /// /// /// @brief Defines the layout of a page-directory-pointer table entry @@ -53,30 +51,21 @@ namespace loader bsl::uint64 pcd : static_cast(1); /// @brief defines the "accessed" field in the page bsl::uint64 a : static_cast(1); - /// @brief defines an ignored field in the page - bsl::uint64 ignored1 : static_cast(1); - /// @brief defines a field in the page that must be 0 - bsl::uint64 mbz1 : static_cast(1); - /// @brief defines an ignored field in the page - bsl::uint64 ignored2 : static_cast(1); + /// @brief defines the "dirty" field in the page (ignored) + bsl::uint64 d : static_cast(1); + /// @brief defines the "page size" field in the page (must be 0) + bsl::uint64 ps : static_cast(1); + /// @brief defines the "global" field in the page (must be 0) + bsl::uint64 g : static_cast(1); /// @brief defines the "available to software" field in the page - bsl::uint64 avl : static_cast(3); - /// @brief defines the physical address field in the page + bsl::uint64 available1 : static_cast(3); + /// @brief defines the "physical address" field in the page bsl::uint64 phys : static_cast(40); - /// @brief defines fields in the page available to the OS for use - bsl::uint64 available : static_cast(11); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(11); /// @brief defines the "no-execute" field in the page bsl::uint64 nx : static_cast(1); }; - - namespace details - { - /// @brief defined the expected size of the pdpte_t struct - constexpr bsl::safe_uintmax EXPECTED_PDPTE_T_SIZE{bsl::to_umax(8)}; - - /// Check to make sure the pdpte_t is the right size. - static_assert(sizeof(pdpte_t) == EXPECTED_PDPTE_T_SIZE); - } } #pragma pack(pop) diff --git a/kernel/src/x64/pdt_t.hpp b/kernel/include/x64/pdt_t.hpp similarity index 74% rename from kernel/src/x64/pdt_t.hpp rename to kernel/include/x64/pdt_t.hpp index 09a4dc26..9ece755e 100644 --- a/kernel/src/x64/pdt_t.hpp +++ b/kernel/include/x64/pdt_t.hpp @@ -35,8 +35,8 @@ namespace mk { - /// @brief defined the expected size of the pdt_t struct - constexpr bsl::safe_uintmax NUM_PDT_ENTRIES{bsl::to_umax(512)}; + /// @brief defines total number of entries in the pdt + constexpr auto NUM_PDT_ENTRIES{512_umax}; /// @struct mk::pdt_t /// @@ -45,18 +45,9 @@ namespace mk /// struct pdt_t final { - /// @brief stores the entires in the table - bsl::array entries; + /// @brief stores the entries for this page table + bsl::array entries; }; - - namespace details - { - /// @brief defined the expected size of the pdt_t struct - constexpr bsl::safe_uintmax EXPECTED_PDT_T_SIZE{bsl::to_umax(HYPERVISOR_PAGE_SIZE)}; - - /// Check to make sure the pdt_t is the right size. - static_assert(sizeof(pdt_t) == EXPECTED_PDT_T_SIZE); - } } #pragma pack(pop) diff --git a/loader/include/interface/cpp/x64/pdte_t.hpp b/kernel/include/x64/pdte_t.hpp similarity index 70% rename from loader/include/interface/cpp/x64/pdte_t.hpp rename to kernel/include/x64/pdte_t.hpp index 4703e2ab..9d9117ce 100644 --- a/loader/include/interface/cpp/x64/pdte_t.hpp +++ b/kernel/include/x64/pdte_t.hpp @@ -25,15 +25,13 @@ #ifndef PDTE_T_HPP #define PDTE_T_HPP +#include + #pragma pack(push, 1) -#include -#include -#include - -namespace loader +namespace mk { - /// @struct loader::pdte_t + /// @struct mk::pdte_t /// /// /// @brief Defines the layout of a page-directory table entry (PDTE). @@ -52,30 +50,21 @@ namespace loader bsl::uint64 pcd : static_cast(1); /// @brief defines the "accessed" field in the page bsl::uint64 a : static_cast(1); - /// @brief defines an ignored field in the page - bsl::uint64 ignored1 : static_cast(1); - /// @brief defines a field in the page that must be 0 - bsl::uint64 mbz1 : static_cast(1); - /// @brief defines an ignored field in the page - bsl::uint64 ignored2 : static_cast(1); + /// @brief defines the "dirty" field in the page (ignored) + bsl::uint64 d : static_cast(1); + /// @brief defines the "page size" field in the page (must be 0) + bsl::uint64 ps : static_cast(1); + /// @brief defines the "global" field in the page (must be 0) + bsl::uint64 g : static_cast(1); /// @brief defines the "available to software" field in the page - bsl::uint64 avl : static_cast(3); - /// @brief defines the physical address field in the page + bsl::uint64 available1 : static_cast(3); + /// @brief defines the "physical address" field in the page bsl::uint64 phys : static_cast(40); - /// @brief defines fields in the page available to the OS for use - bsl::uint64 available : static_cast(11); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(11); /// @brief defines the "no-execute" field in the page bsl::uint64 nx : static_cast(1); }; - - namespace details - { - /// @brief defined the expected size of the pdte_t struct - constexpr bsl::safe_uintmax EXPECTED_PDTE_T_SIZE{bsl::to_umax(8)}; - - /// Check to make sure the pdte_t is the right size. - static_assert(sizeof(pdte_t) == EXPECTED_PDTE_T_SIZE); - } } #pragma pack(pop) diff --git a/kernel/src/x64/pml4t_t.hpp b/kernel/include/x64/pml4t_t.hpp similarity index 73% rename from kernel/src/x64/pml4t_t.hpp rename to kernel/include/x64/pml4t_t.hpp index 9ad84aff..6ab44ebd 100644 --- a/kernel/src/x64/pml4t_t.hpp +++ b/kernel/include/x64/pml4t_t.hpp @@ -35,28 +35,19 @@ namespace mk { - /// @brief defined the expected size of the pml4t_t struct - constexpr bsl::safe_uintmax NUM_PML4T_ENTRIES{bsl::to_umax(512)}; + /// @brief defines total number of entries in the pml4t + constexpr auto NUM_PML4T_ENTRIES{512_umax}; /// @struct mk::pml4t_t /// /// - /// @brief Defines the layout of a page-map level-4 table (pml4). + /// @brief Defines the layout of a page-map level-4 table (pml4t). /// struct pml4t_t final { - /// @brief stores the entires in the table - bsl::array entries; + /// @brief stores the entries for this page table + bsl::array entries; }; - - namespace details - { - /// @brief defined the expected size of the pml4t_t struct - constexpr bsl::safe_uintmax EXPECTED_PML4T_T_SIZE{bsl::to_umax(HYPERVISOR_PAGE_SIZE)}; - - /// Check to make sure the pml4t_t is the right size. - static_assert(sizeof(pml4t_t) == EXPECTED_PML4T_T_SIZE); - } } #pragma pack(pop) diff --git a/loader/include/interface/cpp/x64/pml4te_t.hpp b/kernel/include/x64/pml4te_t.hpp similarity index 73% rename from loader/include/interface/cpp/x64/pml4te_t.hpp rename to kernel/include/x64/pml4te_t.hpp index 8c4166f8..511a9c94 100644 --- a/loader/include/interface/cpp/x64/pml4te_t.hpp +++ b/kernel/include/x64/pml4te_t.hpp @@ -25,15 +25,13 @@ #ifndef PML4TE_T_HPP #define PML4TE_T_HPP +#include + #pragma pack(push, 1) -#include -#include -#include - -namespace loader +namespace mk { - /// @struct loader::pml4te_t + /// @struct mk::pml4te_t /// /// /// @brief Defines the layout of a page-map level-4 table entry (PML4TE). @@ -52,30 +50,23 @@ namespace loader bsl::uint64 pcd : static_cast(1); /// @brief defines the "accessed" field in the page bsl::uint64 a : static_cast(1); - /// @brief defines an ignored field in the page - bsl::uint64 ignored1 : static_cast(1); - /// @brief defines a field in the page that must be 0 + /// @brief defines the "dirty" field in the page (ignored) + bsl::uint64 ignored : static_cast(1); + /// @brief defines the "page size" field in the page (must be 0) bsl::uint64 mbz1 : static_cast(1); - /// @brief defines a field in the page that must be 0 + /// @brief defines the "global" field in the page (must be 0) bsl::uint64 mbz2 : static_cast(1); + /// @brief defines our "aliased" field in the page + bsl::uint64 alias : static_cast(1); /// @brief defines the "available to software" field in the page - bsl::uint64 avl : static_cast(3); - /// @brief defines the physical address field in the page + bsl::uint64 available1 : static_cast(2); + /// @brief defines the "physical address" field in the page bsl::uint64 phys : static_cast(40); - /// @brief defines if this page is an alias (i.e., non-owning) - bsl::uint64 alias : static_cast(11); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(11); /// @brief defines the "no-execute" field in the page bsl::uint64 nx : static_cast(1); }; - - namespace details - { - /// @brief defined the expected size of the pml4te_t struct - constexpr bsl::safe_uintmax EXPECTED_PML4TE_T_SIZE{bsl::to_umax(8)}; - - /// Check to make sure the pml4te_t is the right size. - static_assert(sizeof(pml4te_t) == EXPECTED_PML4TE_T_SIZE); - } } #pragma pack(pop) diff --git a/kernel/src/x64/pt_t.hpp b/kernel/include/x64/pt_t.hpp similarity index 74% rename from kernel/src/x64/pt_t.hpp rename to kernel/include/x64/pt_t.hpp index 6eec0098..90d80a96 100644 --- a/kernel/src/x64/pt_t.hpp +++ b/kernel/include/x64/pt_t.hpp @@ -35,8 +35,8 @@ namespace mk { - /// @brief defined the expected size of the pt_t struct - constexpr bsl::safe_uintmax NUM_PT_ENTRIES{bsl::to_umax(512)}; + /// @brief defines total number of entries in the pt + constexpr auto NUM_PT_ENTRIES{512_umax}; /// @struct mk::pt_t /// @@ -45,18 +45,9 @@ namespace mk /// struct pt_t final { - /// @brief stores the entires in the table - bsl::array entries; + /// @brief stores the entries for this page table + bsl::array entries; }; - - namespace details - { - /// @brief defined the expected size of the pt_t struct - constexpr bsl::safe_uintmax EXPECTED_PT_T_SIZE{bsl::to_umax(HYPERVISOR_PAGE_SIZE)}; - - /// Check to make sure the pt_t is the right size. - static_assert(sizeof(pt_t) == EXPECTED_PT_T_SIZE); - } } #pragma pack(pop) diff --git a/loader/include/interface/cpp/x64/pte_t.hpp b/kernel/include/x64/pte_t.hpp similarity index 74% rename from loader/include/interface/cpp/x64/pte_t.hpp rename to kernel/include/x64/pte_t.hpp index 5eb69db3..778ebc35 100644 --- a/loader/include/interface/cpp/x64/pte_t.hpp +++ b/kernel/include/x64/pte_t.hpp @@ -25,15 +25,13 @@ #ifndef PTE_T_HPP #define PTE_T_HPP +#include + #pragma pack(push, 1) -#include -#include -#include - -namespace loader +namespace mk { - /// @struct loader::pte_t + /// @struct mk::pte_t /// /// @brief Defines the layout of a page table entry (PTE). /// @@ -51,32 +49,23 @@ namespace loader bsl::uint64 pcd : static_cast(1); /// @brief defines the "accessed" field in the page bsl::uint64 a : static_cast(1); - /// @brief defines the "dirty" field in the page + /// @brief defines the "dirty" field in the page (ignored) bsl::uint64 d : static_cast(1); - /// @brief defines the "page-attribute table" field in the page - bsl::uint64 pat : static_cast(1); - /// @brief defines the "global page" field in the page + /// @brief defines the "page size" field in the page (must be 0) + bsl::uint64 ps : static_cast(1); + /// @brief defines the "global" field in the page (must be 0) bsl::uint64 g : static_cast(1); - /// @brief defines the "available to software" field in the page - bsl::uint64 avl : static_cast(3); - /// @brief defines the physical addressfield in the page + /// @brief defines our "auto_release" field in the page + bsl::int32 auto_release : static_cast(3); + /// @brief defines the "physical address" field in the page bsl::uint64 phys : static_cast(40); - /// @brief defines whether or not the page can be auto released - bsl::uint64 auto_release : static_cast(7); + /// @brief defines the "available to software" field in the page + bsl::uint64 available2 : static_cast(7); /// @brief defines the "memory protection key" field in the page bsl::uint64 mpk : static_cast(4); /// @brief defines the "no-execute" field in the page bsl::uint64 nx : static_cast(1); }; - - namespace details - { - /// @brief defined the expected size of the pte_t struct - constexpr bsl::safe_uintmax EXPECTED_PTE_T_SIZE{bsl::to_umax(8)}; - - /// Check to make sure the pte_t is the right size. - static_assert(sizeof(pte_t) == EXPECTED_PTE_T_SIZE); - } } #pragma pack(pop) diff --git a/kernel/src/x64/tls_t.hpp b/kernel/include/x64/tls_t.hpp similarity index 59% rename from kernel/src/x64/tls_t.hpp rename to kernel/include/x64/tls_t.hpp index 83c2b1f6..89cfcc90 100644 --- a/kernel/src/x64/tls_t.hpp +++ b/kernel/include/x64/tls_t.hpp @@ -30,21 +30,31 @@ #include #include #include +#include #include #pragma pack(push, 1) namespace mk { - namespace details - { - /// @brief defines the size of the reserved1 field in the tls_t - constexpr bsl::safe_uintmax TLS_T_RESERVED1_SIZE{bsl::to_umax(0x030)}; - /// @brief defines the size of the reserved2 field in the tls_t - constexpr bsl::safe_uintmax TLS_T_RESERVED2_SIZE{bsl::to_umax(0x088)}; - /// @brief defines the the total size of the TLS block - constexpr bsl::safe_uintmax TLS_T_SIZE{bsl::to_umax(0x300)}; - } + /// @brief defines the size of the reserved1 field in the tls_t + constexpr auto TLS_T_RESERVED1_SIZE{0x030_umax}; + /// @brief defines the size of the reserved2 field in the tls_t + constexpr auto TLS_T_RESERVED2_SIZE{0x008_umax}; + /// @brief defines the size of the reserved3 field in the tls_t + constexpr auto TLS_T_RESERVED3_SIZE{0x007_umax}; + /// @brief defines the size of the reserved4 field in the tls_t + constexpr auto TLS_T_RESERVED4_SIZE{0x040_umax}; + + /// IMPORTANT: + /// - If the size of the TLS is changed, the mk_main_entry will need to + /// be updated to reflect the new size. It might make sense to have a + /// header file that defines a constant that both this code and the + /// assembly logic can share + /// + + /// @brief defines the the total size of the TLS block + constexpr auto TLS_T_SIZE{0x300_umax}; /// @struct mk::tls_t /// @@ -145,9 +155,9 @@ namespace mk /// @brief stores the value of r15 for the ESR (0x120) bsl::uintmax esr_r15; /// @brief stores the value of rip for the ESR (0x128) - bsl::uintmax esr_rip; + bsl::uintmax esr_ip; /// @brief stores the value of rsp for the ESR (0x130) - bsl::uintmax esr_rsp; + bsl::uintmax esr_sp; /// @brief stores the value of the ESR vector (0x138) bsl::uintmax esr_vector; @@ -157,7 +167,7 @@ namespace mk /// @brief stores the value of cr0 for the ESR (0x148) bsl::uintmax esr_cr0; /// @brief stores the value of cr2 for the ESR (0x150) - bsl::uintmax esr_cr2; + bsl::uintmax esr_pf_addr; /// @brief stores the value of cr3 for the ESR (0x158) bsl::uintmax esr_cr3; /// @brief stores the value of cr4 for the ESR (0x160) @@ -175,45 +185,51 @@ namespace mk /// Fast Fail Information /// -------------------------------------------------------------------- - /// @brief stores the current fast fail address (0x180). + /// @brief stores the current fast fail address (0x180) bsl::uintmax current_fast_fail_ip; - /// @brief stores the current fast fail stack (0x188). + /// @brief stores the current fast fail stack (0x188) bsl::uintmax current_fast_fail_sp; - /// @brief stores the mk_main fast fail address (0x190). + /// @brief stores the mk_main fast fail address (0x190) bsl::uintmax mk_main_fast_fail_ip; - /// @brief stores the mk_main fast fail stack (0x198). + /// @brief stores the mk_main fast fail stack (0x198) bsl::uintmax mk_main_fast_fail_sp; - /// @brief stores the call_ext fast fail address (0x1A0). + /// @brief stores the call_ext fast fail address (0x1A0) bsl::uintmax call_ext_fast_fail_ip; - /// @brief stores the call_ext fast fail stack (0x1A8). + /// @brief stores the call_ext fast fail stack (0x1A8) bsl::uintmax call_ext_fast_fail_sp; - /// @brief stores the dispatch_syscall fast fail address (0x1B0). + /// @brief stores the dispatch_syscall fast fail address (0x1B0) bsl::uintmax dispatch_syscall_fast_fail_ip; - /// @brief stores the dispatch_syscall fast fail stack (0x1B8). + /// @brief stores the dispatch_syscall fast fail stack (0x1B8) bsl::uintmax dispatch_syscall_fast_fail_sp; - /// @brief stores the vmexit loop address (0x1C0). + /// @brief stores the vmexit loop address (0x1C0) bsl::uintmax vmexit_loop_ip; - /// @brief stores the vmexit loop stack (0x1C8). + /// @brief stores the vmexit loop stack (0x1C8) bsl::uintmax vmexit_loop_sp; /// @brief reserve the rest of the TLS block for later use. - bsl::details::carray reserved1; + bsl::details::carray reserved1; /// -------------------------------------------------------------------- /// Context Information /// -------------------------------------------------------------------- - /// @brief stores the virtual address of this TLS block (0x200). + /// @brief stores the virtual address of this TLS block (0x200) tls_t *self; - /// @brief stores the thread ID for this TLS block (0x208). - bsl::uintmax thread_id; + /// @brief stores the currently active VMID (0x208) + bsl::uint16 ppid; + /// @brief stores the total number of online PPs (0x20A) + bsl::uint16 online_pps; + /// @brief stores the VPSID whose VMCS is loaded on Intel (0x20C) + bsl::uint16 loaded_vpsid; + /// @brief reserved (0x20E) + bsl::uint16 reserved_padding0; - /// @brief stores the currently running extension (0x210) + /// @brief stores the currently active extension (0x210) void *ext; /// @brief stores the extension registered for VMExits (0x218) void *ext_vmexit; @@ -225,164 +241,83 @@ namespace mk /// @brief stores the loader provided state for the root VP (0x230) loader::state_save_t *root_vp_state; - /// @brief stores the ID of the active VPS (0x238) + /// @brief stores the currently active extension ID (0x238) + bsl::uint16 active_extid; + /// @brief stores the currently active VMID (0x23A) + bsl::uint16 active_vmid; + /// @brief stores the currently active VPID (0x23C) + bsl::uint16 active_vpid; + /// @brief stores the currently active VPSID (0x23E) bsl::uint16 active_vpsid; - /// @brief reserved. - bsl::uint16 reserved_id1; - /// @brief reserved. - bsl::uint16 reserved_id2; - /// @brief reserved. - bsl::uint16 reserved_id3; - /// @brief stores the sp used by extensions for callbacks (0x240). + /// @brief stores the sp used by extensions for callbacks (0x240) bsl::uintmax sp; - /// @brief stores the tps used by extensions for callbacks (0x248). + /// @brief stores the tps used by extensions for callbacks (0x248) bsl::uintmax tp; - /// @brief used to store a return address for unsafe ops (0x250). + /// @brief used to store a return address for unsafe ops (0x250) bsl::uintmax unsafe_rip; - /// @brief used to signal NMIs are not safe (0x258). + /// @brief used to signal NMIs are not safe (0x258) bsl::uintmax nmi_lock; - /// @brief used to singal an NMI has fired (0x260). + /// @brief used to singal an NMI has fired (0x260) bsl::uintmax nmi_pending; - /// @brief on Intel, stores the currently loaded VPS (0x268). - void *loaded_vps; - - /// @brief stores whether or not the first launch succeeded (0x270). + /// @brief stores whether or not the first launch succeeded (0x268) bsl::uintmax first_launch_succeeded; + /// @brief stores the currently active root page table (0x270) + void *active_rpt; + /// @brief reserve the rest of the TLS block for later use. - bsl::details::carray reserved2; + bsl::details::carray reserved2; /// -------------------------------------------------------------------- - /// Helpers + /// Failure Handling /// -------------------------------------------------------------------- - /// - /// @brief Returns the extension ID - /// - /// - /// @return Returns the extension ID - /// - [[nodiscard]] constexpr auto - extid() const noexcept -> bsl::safe_uint16 - { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0xFFFF000000000000U)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(48)}; + /// @brief stores a whether or not state is changing (0x280) + bool state_reversal_required; - return bsl::to_u16((thread_id & mask) >> shift); - } + /// @brief reserves the rest of the TLS block for later use. + bsl::details::carray reserved3; - /// - /// @brief Returns the virtual machine ID - /// - /// - /// @return Returns the virtual machine ID - /// - [[nodiscard]] constexpr auto - vmid() const noexcept -> bsl::safe_uint16 - { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0x0000FFFF00000000U)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(32)}; + /// @brief stores the syscall return status (0x288) + bsl::uintmax syscall_ret_status; - return bsl::to_u16((thread_id & mask) >> shift); - } + /// @brief logs an extid for state reversal if needed (0x290) + bsl::uint16 log_extid; + /// @brief logs a vmid for state reversal if needed (0x292) + bsl::uint16 log_vmid; + /// @brief logs a vpid for state reversal if needed (0x294) + bsl::uint16 log_vpid; + /// @brief logs a vpsid for state reversal if needed (0x296) + bsl::uint16 log_vpsid; - /// - /// @brief Returns the virtual processor ID - /// - /// - /// @return Returns the virtual processor ID - /// - [[nodiscard]] constexpr auto - vpid() const noexcept -> bsl::safe_uint16 - { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0x00000000FFFF0000U)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(16)}; + /// @brief logs an ext for state reversal if needed (0x298) + void *log_ext; + /// @brief logs a vm for state reversal if needed (0x2A0) + void *log_vm; + /// @brief logs a vp for state reversal if needed (0x2A8) + void *log_vp; + /// @brief logs a vps for state reversal if needed (0x2B0) + void *log_vps; - return bsl::to_u16((thread_id & mask) >> shift); - } + /// @brief reserve the rest of the TLS block for later use. + bsl::details::carray reserved4; - /// - /// @brief Returns the physical processor ID - /// - /// - /// @return Returns the physical processor ID - /// - [[nodiscard]] constexpr auto - ppid() const noexcept -> bsl::safe_uint16 - { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0x000000000000FFFFU)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(0)}; + /// -------------------------------------------------------------------- + /// Unit Test Specific + /// -------------------------------------------------------------------- - return bsl::to_u16((thread_id & mask) >> shift); - } - - /// - /// @brief Sets the current extension ID - /// - /// - /// @param val the value to set the current extension ID to - /// - constexpr void - set_extid(bsl::safe_uint16 const &val) noexcept - { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0x0000FFFFFFFFFFFFU)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(48)}; - - thread_id = ((thread_id & mask) | (bsl::to_umax(val) << shift)).get(); - } - - /// - /// @brief Sets the current virtual machine ID - /// - /// - /// @param val the value to set the current virtual machine ID to - /// - constexpr void - set_vmid(bsl::safe_uint16 const &val) noexcept - { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0xFFFF0000FFFFFFFFU)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(32)}; - - thread_id = ((thread_id & mask) | (bsl::to_umax(val) << shift)).get(); - } - - /// - /// @brief Sets the current virtual processor ID - /// - /// - /// @param val the value to set the current virtual processor ID to - /// - constexpr void - set_vpid(bsl::safe_uint16 const &val) noexcept - { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0xFFFFFFFF0000FFFFU)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(16)}; - - thread_id = ((thread_id & mask) | (bsl::to_umax(val) << shift)).get(); - } - - /// - /// @brief Sets the current physical processor ID - /// - /// - /// @param val the value to set the current physical processor ID to - /// - constexpr void - set_ppid(bsl::safe_uint16 const &val) noexcept - { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0xFFFFFFFFFFFF0000U)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(0)}; - - thread_id = ((thread_id & mask) | (bsl::to_umax(val) << shift)).get(); - } + /// @brief reserved for unit testing + bsl::errc_type test_ret; + /// @brief reserved + bsl::uint32 reserved_padding1; }; /// @brief make sure the tls_t is the size of a page - static_assert(sizeof(tls_t) == details::TLS_T_SIZE); + static_assert(sizeof(tls_t) == TLS_T_SIZE); } #pragma pack(pop) diff --git a/kernel/include/x64/vmexit_log_pp_t.hpp b/kernel/include/x64/vmexit_log_pp_t.hpp new file mode 100644 index 00000000..55bf51a6 --- /dev/null +++ b/kernel/include/x64/vmexit_log_pp_t.hpp @@ -0,0 +1,49 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_LOG_PP_T +#define VMEXIT_LOG_PP_T + +#include + +#include +#include + +namespace mk +{ + /// @class mk::vmexit_log_pp_t + /// + /// + /// @brief Stores information about each VMExit per PP + /// + struct vmexit_log_pp_t final + { + /// @brief stores the VMExit log + bsl::array log; + /// @brief stores the VMExit log circular cursor + bsl::safe_uintmax crsr; + }; +} + +#endif diff --git a/kernel/include/x64/vmexit_log_record_t.hpp b/kernel/include/x64/vmexit_log_record_t.hpp new file mode 100644 index 00000000..380b846c --- /dev/null +++ b/kernel/include/x64/vmexit_log_record_t.hpp @@ -0,0 +1,90 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_LOG_RECORD_T +#define VMEXIT_LOG_RECORD_T + +#include + +namespace mk +{ + /// @struct mk::vmexit_log_record_t + /// + /// + /// @brief Stores information about each VMExit + /// + struct vmexit_log_record_t final + { + /// @brief stores the VMID that generated the exit + bsl::safe_uint16 vmid; + /// @brief stores the VPID that generated the exit + bsl::safe_uint16 vpid; + /// @brief stores the VPSID that generated the exit + bsl::safe_uint16 vpsid; + /// @brief stores the exit reason + bsl::safe_uintmax exit_reason; + /// @brief stores the exit qualification (Intel) or exit_info1 (AMD) + bsl::safe_uintmax ei1; + /// @brief stores the exit information (Intel) or exit_info2 (AMD) + bsl::safe_uintmax ei2; + /// @brief stores the exit input information (AMD) or ignored (Intel) + bsl::safe_uintmax ei3; + /// @brief stores rax + bsl::safe_uintmax rax; + /// @brief stores rbx + bsl::safe_uintmax rbx; + /// @brief stores rcx + bsl::safe_uintmax rcx; + /// @brief stores rdx + bsl::safe_uintmax rdx; + /// @brief stores rbp + bsl::safe_uintmax rbp; + /// @brief stores rsi + bsl::safe_uintmax rsi; + /// @brief stores rdi + bsl::safe_uintmax rdi; + /// @brief stores r8 + bsl::safe_uintmax r8; + /// @brief stores r9 + bsl::safe_uintmax r9; + /// @brief stores r10 + bsl::safe_uintmax r10; + /// @brief stores r11 + bsl::safe_uintmax r11; + /// @brief stores r12 + bsl::safe_uintmax r12; + /// @brief stores r13 + bsl::safe_uintmax r13; + /// @brief stores r14 + bsl::safe_uintmax r14; + /// @brief stores r15 + bsl::safe_uintmax r15; + /// @brief stores rsp + bsl::safe_uintmax rsp; + /// @brief stores rip + bsl::safe_uintmax rip; + }; +} + +#endif diff --git a/kernel/include/yield.hpp b/kernel/include/yield.hpp new file mode 100644 index 00000000..7bdda45d --- /dev/null +++ b/kernel/include/yield.hpp @@ -0,0 +1,38 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef YIELD_HPP +#define YIELD_HPP + +namespace mk +{ + /// + /// @brief Used by endless loops as an optimization. This might + /// call an instruction like the pause on x64, or it might call + /// yield in a unit test. + /// + extern "C" void yield() noexcept; +} + +#endif diff --git a/kernel/integration/CMakeLists.txt b/kernel/integration/CMakeLists.txt new file mode 100644 index 00000000..4d6e6e7e --- /dev/null +++ b/kernel/integration/CMakeLists.txt @@ -0,0 +1,52 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +include(${CMAKE_CURRENT_LIST_DIR}/../../cmake/function/hypervisor_add_integration.cmake) + +list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/integration_utils.hpp +) + +# hypervisor_add_integration(bf_callback_op_register_bootstrap HEADERS) +# hypervisor_add_integration(bf_callback_op_register_fail HEADERS) +# hypervisor_add_integration(bf_callback_op_register_vmexit HEADERS) +# hypervisor_add_integration(bf_handle_op_close_handle HEADERS) +# hypervisor_add_integration(bf_handle_op_open_handle HEADERS) +# hypervisor_add_integration(bf_vm_op_create_vm HEADERS) +# hypervisor_add_integration(bf_vm_op_destroy_vm HEADERS) +# hypervisor_add_integration(bf_vp_op_create_vp HEADERS) +# hypervisor_add_integration(bf_vp_op_destroy_vp HEADERS) +# hypervisor_add_integration(bf_vps_op_create_vps HEADERS) +# hypervisor_add_integration(bf_vps_op_destroy_vps HEADERS) +hypervisor_add_integration(fast_fail_exit_from_bootstrap_with_no_syscall HEADERS) +hypervisor_add_integration(fast_fail_exit_from_bootstrap_with_segfault HEADERS) +hypervisor_add_integration(fast_fail_exit_from_bootstrap_with_wait HEADERS) +hypervisor_add_integration(fast_fail_exit_from_bootstrap HEADERS) +hypervisor_add_integration(fast_fail_exit_from_main_with_no_syscall HEADERS) +hypervisor_add_integration(fast_fail_exit_from_main_with_segfault HEADERS) +hypervisor_add_integration(fast_fail_exit_from_main HEADERS) +hypervisor_add_integration(fast_fail_exit_from_vmexit_with_no_syscall HEADERS) +hypervisor_add_integration(fast_fail_exit_from_vmexit_with_segfault HEADERS) +hypervisor_add_integration(fast_fail_exit_from_vmexit_with_wait HEADERS) +hypervisor_add_integration(fast_fail_exit_from_vmexit HEADERS) +hypervisor_add_integration(fast_fail_wait_no_bootstrap HEADERS) +hypervisor_add_integration(fast_fail_wait_no_fail HEADERS) +hypervisor_add_integration(fast_fail_wait_no_vmexit HEADERS) diff --git a/kernel/integration/bf_callback_op_register_bootstrap.cpp b/kernel/integration/bf_callback_op_register_bootstrap.cpp new file mode 100644 index 00000000..ba36bbdc --- /dev/null +++ b/kernel/integration/bf_callback_op_register_bootstrap.cpp @@ -0,0 +1,86 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include + +#include +#include +#include +#include + +namespace integration +{ + /// @brief stores the handle the extension will use + constinit inline syscall::bf_handle_t g_handle{}; + + /// + /// @brief Implements the bootstrap entry function. + /// + /// + /// @param ppid the physical process to bootstrap + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + bootstrap_entry(bsl::uint16 const ppid) noexcept + { + bsl::discard(ppid); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_bootstrap(g_handle, nullptr); + integration::verify(bsl::errc_failure == ret); + + ret = syscall::bf_callback_op_register_bootstrap(g_handle, &bootstrap_entry); + integration::verify(bsl::errc_success == ret); + + ret = syscall::bf_callback_op_register_bootstrap(g_handle, &bootstrap_entry); + integration::verify(bsl::errc_failure == ret); + + return integration::early(); + } +} diff --git a/kernel/integration/bf_callback_op_register_fail.cpp b/kernel/integration/bf_callback_op_register_fail.cpp new file mode 100644 index 00000000..ecd23746 --- /dev/null +++ b/kernel/integration/bf_callback_op_register_fail.cpp @@ -0,0 +1,92 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include + +#include +#include +#include +#include + +namespace integration +{ + /// @brief stores the handle the extension will use + constinit inline syscall::bf_handle_t g_handle{}; + + /// + /// @brief Implements the fast fail entry function. + /// + /// + /// @param fail_reason the exit reason associated with the fail + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + fail_entry(syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(fail_reason); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_fail(g_handle, nullptr); + integration::verify(bsl::errc_failure == ret); + + ret = syscall::bf_callback_op_register_fail(g_handle, &fail_entry); + integration::verify(bsl::errc_success == ret); + + ret = syscall::bf_callback_op_register_fail(g_handle, &fail_entry); + integration::verify(bsl::errc_failure == ret); + + /// TODO: + /// - When multiple extensions are supported, an extra test needs + /// to be added for when two extensions try to register for this + /// callback as that is not allowed + /// + + return integration::early(); + } +} diff --git a/kernel/integration/bf_callback_op_register_vmexit.cpp b/kernel/integration/bf_callback_op_register_vmexit.cpp new file mode 100644 index 00000000..c45b862d --- /dev/null +++ b/kernel/integration/bf_callback_op_register_vmexit.cpp @@ -0,0 +1,95 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include + +#include +#include +#include +#include + +namespace integration +{ + /// @brief stores the handle the extension will use + constinit inline syscall::bf_handle_t g_handle{}; + + /// + /// @brief Implements the VMExit entry function. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + vmexit_entry(bsl::uint16 const vpsid, bsl::uint64 const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_vmexit(g_handle, nullptr); + integration::verify(bsl::errc_failure == ret); + + ret = syscall::bf_callback_op_register_vmexit(g_handle, &vmexit_entry); + integration::verify(bsl::errc_success == ret); + + ret = syscall::bf_callback_op_register_vmexit(g_handle, &vmexit_entry); + integration::verify(bsl::errc_failure == ret); + + /// TODO: + /// - When multiple extensions are supported, an extra test needs + /// to be added for when two extensions try to register for this + /// callback as that is not allowed + /// + + return integration::early(); + } +} diff --git a/kernel/integration/bf_handle_op_close_handle.cpp b/kernel/integration/bf_handle_op_close_handle.cpp new file mode 100644 index 00000000..7ed12907 --- /dev/null +++ b/kernel/integration/bf_handle_op_close_handle.cpp @@ -0,0 +1,70 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include + +#include +#include +#include +#include + +namespace integration +{ + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + syscall::bf_handle_t handle{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_close_handle(handle); + integration::verify(bsl::errc_failure == ret); + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, handle); + integration::verify(bsl::errc_success == ret); + + ret = syscall::bf_handle_op_close_handle(handle); + integration::verify(bsl::errc_success == ret); + + ret = syscall::bf_handle_op_close_handle(handle); + integration::verify(bsl::errc_failure == ret); + + return integration::early(); + } +} diff --git a/kernel/integration/bf_handle_op_open_handle.cpp b/kernel/integration/bf_handle_op_open_handle.cpp new file mode 100644 index 00000000..cbfbf0f3 --- /dev/null +++ b/kernel/integration/bf_handle_op_open_handle.cpp @@ -0,0 +1,68 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include + +#include +#include +#include +#include + +namespace integration +{ + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + syscall::bf_handle_t handle{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + constexpr auto invalid_spec_id{0x42_u32}; + ret = syscall::bf_handle_op_open_handle(invalid_spec_id, handle); + integration::verify(bsl::errc_failure == ret); + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, handle); + integration::verify(bsl::errc_success == ret); + + ret = syscall::bf_handle_op_open_handle(version, handle); + integration::verify(bsl::errc_failure == ret); + + return integration::early(); + } +} diff --git a/kernel/integration/bf_vm_op_create_vm.cpp b/kernel/integration/bf_vm_op_create_vm.cpp new file mode 100644 index 00000000..be9b9759 --- /dev/null +++ b/kernel/integration/bf_vm_op_create_vm.cpp @@ -0,0 +1,143 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include + +#include +#include +#include +#include + +namespace integration +{ + /// @brief stores the handle the extension will use + constinit inline syscall::bf_handle_t g_handle{}; + + /// + /// @brief Implements the VMExit entry function. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + vmexit_entry(bsl::uint16 const vpsid, bsl::uint64 const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. + /// + /// + /// @param fail_reason the exit reason associated with the fail + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + fail_entry(syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(fail_reason); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the bootstrap entry function. + /// + /// + /// @param ppid the physical process to bootstrap + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + bootstrap_entry(bsl::uint16 const ppid) noexcept + { + bsl::discard(ppid); + + bsl::errc_type ret{}; + bsl::safe_uint16 vmid{}; + + /// NOTE: + /// - The max number of VMs an extension can create is one less than + /// the provided max because the microkernel creates the Root VM + /// automatically for the extension as it cannot be deleted. + /// + + constexpr auto one{1_umax}; + auto const max_vms{HYPERVISOR_MAX_VMS - one}; + + // create with invalid handle + ret = syscall::bf_vm_op_create_vm({}, vmid); + integration::verify(bsl::errc_failure == ret); + + // create all and prove that creating one more will fail + for (bsl::safe_uintmax i{}; i < max_vms; ++i) { + ret = syscall::bf_vm_op_create_vm(g_handle, vmid); + integration::verify(bsl::errc_success == ret); + } + + ret = syscall::bf_vm_op_create_vm(g_handle, vmid); + integration::verify(bsl::errc_failure == ret); + + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_bootstrap(g_handle, &bootstrap_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_vmexit(g_handle, &vmexit_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_fail(g_handle, &fail_entry); + integration::require_success(ret); + + syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/bf_vm_op_destroy_vm.cpp b/kernel/integration/bf_vm_op_destroy_vm.cpp new file mode 100644 index 00000000..e0b92813 --- /dev/null +++ b/kernel/integration/bf_vm_op_destroy_vm.cpp @@ -0,0 +1,223 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include +#include +#include +#include + +namespace integration +{ + /// @brief stores the handle the extension will use + constinit inline syscall::bf_handle_t g_handle{}; + + /// + /// @brief Implements the VMExit entry function. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + vmexit_entry(bsl::uint16 const vpsid, bsl::uint64 const exit_reason) noexcept + { + bsl::errc_type ret{}; + + bsl::discard(vpsid); + bsl::discard(exit_reason); + + // --------------------------------------------------------------------- + // VMExit Tests + // --------------------------------------------------------------------- + + // destroy assigned VM (turns VM into zombie) + ret = syscall::bf_vm_op_destroy_vm(g_handle, syscall::bf_tls_vmid(g_handle)); + integration::verify(bsl::errc_failure == ret); + + // destroy zombie + ret = syscall::bf_vm_op_destroy_vm(g_handle, syscall::bf_tls_vmid(g_handle)); + integration::verify(bsl::errc_failure == ret); + + // --------------------------------------------------------------------- + // Done + // --------------------------------------------------------------------- + + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. + /// + /// + /// @param fail_reason the exit reason associated with the fail + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + fail_entry(syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(fail_reason); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the bootstrap entry function. + /// + /// + /// @param ppid the physical process to bootstrap + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + bootstrap_entry(bsl::uint16 const ppid) noexcept + { + bsl::errc_type ret{}; + + bsl::safe_uint16 vmid{}; + bsl::safe_uint16 vpid{}; + bsl::safe_uint16 vpsid{}; + + /// NOTE: + /// - The max number of VMs an extension can create is one less than + /// the provided max because the microkernel creates the Root VM + /// automatically for the extension as it cannot be deleted. + /// + + // --------------------------------------------------------------------- + // Setup + // --------------------------------------------------------------------- + + ret = syscall::bf_vm_op_create_vm(g_handle, vmid); + integration::require_success(ret); + + // --------------------------------------------------------------------- + // Bootstrap Tests + // --------------------------------------------------------------------- + + // destroy with invalid handle + ret = syscall::bf_vm_op_destroy_vm({}, vmid); + integration::verify(bsl::errc_failure == ret); + + // destroy root VM + ret = syscall::bf_vm_op_destroy_vm(g_handle, syscall::BF_ROOT_VMID); + integration::verify(bsl::errc_failure == ret); + + // destroy with invalid ID + ret = syscall::bf_vm_op_destroy_vm(g_handle, syscall::BF_INVALID_ID); + integration::verify(bsl::errc_failure == ret); + + // destroy with ID that is greater than or equal to MAX_VMS + ret = syscall::bf_vm_op_destroy_vm(g_handle, bsl::to_u16(HYPERVISOR_MAX_VMS)); + integration::verify(bsl::errc_failure == ret); + + // destroy with VM that has not been created + constexpr auto invalid_vmid{2_u16}; + ret = syscall::bf_vm_op_destroy_vm(g_handle, invalid_vmid); + integration::verify(bsl::errc_failure == ret); + + // destroy success + ret = syscall::bf_vm_op_destroy_vm(g_handle, vmid); + integration::verify(bsl::errc_success == ret); + + // destroy same VM twice (double free bug) + ret = syscall::bf_vm_op_destroy_vm(g_handle, vmid); + integration::verify(bsl::errc_failure == ret); + + // create all, then destroy all, prove that we can still create + constexpr auto one{1_umax}; + for (bsl::safe_uintmax i{one}; i < HYPERVISOR_MAX_VMS; ++i) { + ret = syscall::bf_vm_op_create_vm(g_handle, vmid); + integration::require_success(ret); + } + + for (bsl::safe_uintmax i{HYPERVISOR_MAX_VMS}; i > one; --i) { + ret = syscall::bf_vm_op_destroy_vm(g_handle, bsl::to_u16(i - one)); + integration::verify(bsl::errc_success == ret); + } + + ret = syscall::bf_vm_op_create_vm(g_handle, vmid); + integration::require_success(ret); + integration::require(vmid == bsl::to_u16(one)); + + // --------------------------------------------------------------------- + // The following is needed to setup the remaining tests + // --------------------------------------------------------------------- + + ret = syscall::bf_vp_op_create_vp(g_handle, vmid, ppid, vpid); + integration::require_success(ret); + + ret = syscall::bf_vps_op_create_vps(g_handle, vpid, ppid, vpsid); + integration::require_success(ret); + + ret = syscall::bf_vps_op_init_as_root(g_handle, vpsid); + integration::require_success(ret); + + ret = init_vps(g_handle, vpsid); + integration::require_success(ret); + + ret = syscall::bf_vps_op_run(g_handle, vmid, vpid, vpsid); + integration::require_success(ret); + + bsl::print() << bsl::here(); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_bootstrap(g_handle, &bootstrap_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_vmexit(g_handle, &vmexit_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_fail(g_handle, &fail_entry); + integration::require_success(ret); + + syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/bf_vp_op_create_vp.cpp b/kernel/integration/bf_vp_op_create_vp.cpp new file mode 100644 index 00000000..a00d4c32 --- /dev/null +++ b/kernel/integration/bf_vp_op_create_vp.cpp @@ -0,0 +1,151 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include + +#include +#include +#include +#include + +namespace integration +{ + /// @brief stores the handle the extension will use + constinit inline syscall::bf_handle_t g_handle{}; + + /// + /// @brief Implements the VMExit entry function. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + vmexit_entry(bsl::uint16 const vpsid, bsl::uint64 const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. + /// + /// + /// @param fail_reason the exit reason associated with the fail + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + fail_entry(syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(fail_reason); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the bootstrap entry function. + /// + /// + /// @param ppid the physical process to bootstrap + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + bootstrap_entry(bsl::uint16 const ppid) noexcept + { + bsl::errc_type ret{}; + bsl::safe_uint16 vpid{}; + + // create with invalid handle + ret = syscall::bf_vp_op_create_vp({}, syscall::BF_ROOT_VMID, ppid, vpid); + integration::verify(bsl::errc_failure == ret); + + // create with invalid vmid + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_INVALID_ID, ppid, vpid); + integration::verify(bsl::errc_failure == ret); + + // create with vmid that has not been created + constexpr auto invalid_vpid{2_u16}; + ret = syscall::bf_vp_op_create_vp(g_handle, invalid_vpid, ppid, vpid); + integration::verify(bsl::errc_failure == ret); + + // create with invalid ppid + ret = syscall::bf_vp_op_create_vp( + g_handle, syscall::BF_ROOT_VMID, syscall::BF_INVALID_ID, vpid); + integration::verify(bsl::errc_failure == ret); + + // create with ppid that is create than the total number of online pps + ret = syscall::bf_vp_op_create_vp( + g_handle, syscall::BF_ROOT_VMID, syscall::bf_tls_online_pps(g_handle), vpid); + integration::verify(bsl::errc_failure == ret); + + // create all and prove that creating one more will fail + for (bsl::safe_uintmax i{}; i < HYPERVISOR_MAX_VPS; ++i) { + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_ROOT_VMID, ppid, vpid); + integration::verify(bsl::errc_success == ret); + } + + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_ROOT_VMID, ppid, vpid); + integration::verify(bsl::errc_failure == ret); + + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_bootstrap(g_handle, &bootstrap_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_vmexit(g_handle, &vmexit_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_fail(g_handle, &fail_entry); + integration::require_success(ret); + + syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/bf_vp_op_destroy_vp.cpp b/kernel/integration/bf_vp_op_destroy_vp.cpp new file mode 100644 index 00000000..8c74e13e --- /dev/null +++ b/kernel/integration/bf_vp_op_destroy_vp.cpp @@ -0,0 +1,214 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include +#include +#include +#include + +namespace integration +{ + /// @brief stores the handle the extension will use + constinit inline syscall::bf_handle_t g_handle{}; + + /// + /// @brief Implements the VPExit entry function. + /// + /// + /// @param vpsid the ID of the VPS that generated the VPExit + /// @param exit_reason the exit reason associated with the VPExit + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + vmexit_entry(bsl::uint16 const vpsid, bsl::uint64 const exit_reason) noexcept + { + bsl::errc_type ret{}; + + bsl::discard(vpsid); + bsl::discard(exit_reason); + + // --------------------------------------------------------------------- + // VMExit Tests + // --------------------------------------------------------------------- + + // destroy assigned VP (turns VP into zombie) + ret = syscall::bf_vp_op_destroy_vp(g_handle, syscall::bf_tls_vpid(g_handle)); + integration::verify(bsl::errc_failure == ret); + + // destroy zombie + ret = syscall::bf_vp_op_destroy_vp(g_handle, syscall::bf_tls_vpid(g_handle)); + integration::verify(bsl::errc_failure == ret); + + // --------------------------------------------------------------------- + // Done + // --------------------------------------------------------------------- + + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. + /// + /// + /// @param fail_reason the exit reason associated with the fail + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + fail_entry(syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(fail_reason); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the bootstrap entry function. + /// + /// + /// @param ppid the physical process to bootstrap + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + bootstrap_entry(bsl::uint16 const ppid) noexcept + { + bsl::errc_type ret{}; + + bsl::safe_uint16 vpid{}; + bsl::safe_uint16 vpsid{}; + + /// NOTE: + /// - The max number of VPs an extension can create is one less than + /// the provided max because the microkernel creates the Root VP + /// automatically for the extension as it cannot be deleted. + /// + + // --------------------------------------------------------------------- + // Setup + // --------------------------------------------------------------------- + + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_ROOT_VMID, ppid, vpid); + integration::require_success(ret); + + // --------------------------------------------------------------------- + // Bootstrap Tests + // --------------------------------------------------------------------- + + // destroy with invalid handle + ret = syscall::bf_vp_op_destroy_vp({}, vpid); + integration::verify(bsl::errc_failure == ret); + + // destroy with invalid ID + ret = syscall::bf_vp_op_destroy_vp(g_handle, syscall::BF_INVALID_ID); + integration::verify(bsl::errc_failure == ret); + + // destroy with ID that is greater than or equal to MAX_VPS + ret = syscall::bf_vp_op_destroy_vp(g_handle, bsl::to_u16(HYPERVISOR_MAX_VPS)); + integration::verify(bsl::errc_failure == ret); + + // destroy with VP that has not been created + constexpr auto invalid_vpid{2_u16}; + ret = syscall::bf_vp_op_destroy_vp(g_handle, invalid_vpid); + integration::verify(bsl::errc_failure == ret); + + // destroy success + ret = syscall::bf_vp_op_destroy_vp(g_handle, vpid); + integration::verify(bsl::errc_success == ret); + + // destroy same VP twice (double free bug) + ret = syscall::bf_vp_op_destroy_vp(g_handle, vpid); + integration::verify(bsl::errc_failure == ret); + + // create all, then destroy all, prove that we can still create + for (bsl::safe_uintmax i{}; i < HYPERVISOR_MAX_VPS; ++i) { + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_ROOT_VMID, ppid, vpid); + integration::require_success(ret); + } + + for (bsl::safe_uintmax i{}; i < HYPERVISOR_MAX_VPS; ++i) { + ret = syscall::bf_vp_op_destroy_vp(g_handle, bsl::to_u16(i)); + integration::verify(bsl::errc_success == ret); + } + + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_ROOT_VMID, ppid, vpid); + integration::require_success(ret); + integration::require(vpid.is_zero()); + + // --------------------------------------------------------------------- + // The following is needed to setup the remaining tests + // --------------------------------------------------------------------- + + ret = syscall::bf_vps_op_create_vps(g_handle, vpid, ppid, vpsid); + integration::require_success(ret); + + ret = syscall::bf_vps_op_init_as_root(g_handle, vpsid); + integration::require_success(ret); + + ret = init_vps(g_handle, vpsid); + integration::require_success(ret); + + ret = syscall::bf_vps_op_run(g_handle, vpid, vpid, vpsid); + integration::require_success(ret); + + bsl::print() << bsl::here(); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_bootstrap(g_handle, &bootstrap_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_vmexit(g_handle, &vmexit_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_fail(g_handle, &fail_entry); + integration::require_success(ret); + + syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/bf_vps_op_create_vps.cpp b/kernel/integration/bf_vps_op_create_vps.cpp new file mode 100644 index 00000000..d786edd5 --- /dev/null +++ b/kernel/integration/bf_vps_op_create_vps.cpp @@ -0,0 +1,164 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include + +#include +#include +#include +#include + +namespace integration +{ + /// @brief stores the handle the extension will use + constinit inline syscall::bf_handle_t g_handle{}; + + /// + /// @brief Implements the VMExit entry function. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + vmexit_entry(bsl::uint16 const vpsid, bsl::uint64 const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. + /// + /// + /// @param fail_reason the exit reason associated with the fail + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + fail_entry(syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(fail_reason); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the bootstrap entry function. + /// + /// + /// @param ppid the physical process to bootstrap + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + bootstrap_entry(bsl::uint16 const ppid) noexcept + { + bsl::errc_type ret{}; + + bsl::safe_uint16 vpid{}; + bsl::safe_uint16 vpsid{}; + + // --------------------------------------------------------------------- + // Setup + // --------------------------------------------------------------------- + + // create with invalid handle + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_ROOT_VMID, ppid, vpid); + integration::require_success(ret); + + // --------------------------------------------------------------------- + // Bootstrap Tests + // --------------------------------------------------------------------- + + // create with invalid handle + ret = syscall::bf_vps_op_create_vps({}, vpid, ppid, vpsid); + integration::verify(bsl::errc_failure == ret); + + // create with invalid vmid + ret = syscall::bf_vps_op_create_vps(g_handle, syscall::BF_INVALID_ID, ppid, vpsid); + integration::verify(bsl::errc_failure == ret); + + // create with vmid that has not been created + constexpr auto invalid_vpsid{2_u16}; + ret = syscall::bf_vps_op_create_vps(g_handle, invalid_vpsid, ppid, vpsid); + integration::verify(bsl::errc_failure == ret); + + // create with invalid ppid + ret = syscall::bf_vps_op_create_vps(g_handle, vpid, syscall::BF_INVALID_ID, vpsid); + integration::verify(bsl::errc_failure == ret); + + // create with ppid that is create than the total number of online pps + ret = syscall::bf_vps_op_create_vps( + g_handle, vpid, syscall::bf_tls_online_pps(g_handle), vpsid); + integration::verify(bsl::errc_failure == ret); + + // create all and prove that creating one more will fail + for (bsl::safe_uintmax i{}; i < HYPERVISOR_MAX_VPSS; ++i) { + ret = syscall::bf_vps_op_create_vps(g_handle, vpid, ppid, vpsid); + integration::verify(bsl::errc_success == ret); + } + + ret = syscall::bf_vps_op_create_vps(g_handle, vpid, ppid, vpsid); + integration::verify(bsl::errc_failure == ret); + + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_bootstrap(g_handle, &bootstrap_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_vmexit(g_handle, &vmexit_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_fail(g_handle, &fail_entry); + integration::require_success(ret); + + syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/bf_vps_op_destroy_vps.cpp b/kernel/integration/bf_vps_op_destroy_vps.cpp new file mode 100644 index 00000000..8c74e13e --- /dev/null +++ b/kernel/integration/bf_vps_op_destroy_vps.cpp @@ -0,0 +1,214 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include +#include +#include +#include + +namespace integration +{ + /// @brief stores the handle the extension will use + constinit inline syscall::bf_handle_t g_handle{}; + + /// + /// @brief Implements the VPExit entry function. + /// + /// + /// @param vpsid the ID of the VPS that generated the VPExit + /// @param exit_reason the exit reason associated with the VPExit + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + vmexit_entry(bsl::uint16 const vpsid, bsl::uint64 const exit_reason) noexcept + { + bsl::errc_type ret{}; + + bsl::discard(vpsid); + bsl::discard(exit_reason); + + // --------------------------------------------------------------------- + // VMExit Tests + // --------------------------------------------------------------------- + + // destroy assigned VP (turns VP into zombie) + ret = syscall::bf_vp_op_destroy_vp(g_handle, syscall::bf_tls_vpid(g_handle)); + integration::verify(bsl::errc_failure == ret); + + // destroy zombie + ret = syscall::bf_vp_op_destroy_vp(g_handle, syscall::bf_tls_vpid(g_handle)); + integration::verify(bsl::errc_failure == ret); + + // --------------------------------------------------------------------- + // Done + // --------------------------------------------------------------------- + + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. + /// + /// + /// @param fail_reason the exit reason associated with the fail + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + fail_entry(syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(fail_reason); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the bootstrap entry function. + /// + /// + /// @param ppid the physical process to bootstrap + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + bootstrap_entry(bsl::uint16 const ppid) noexcept + { + bsl::errc_type ret{}; + + bsl::safe_uint16 vpid{}; + bsl::safe_uint16 vpsid{}; + + /// NOTE: + /// - The max number of VPs an extension can create is one less than + /// the provided max because the microkernel creates the Root VP + /// automatically for the extension as it cannot be deleted. + /// + + // --------------------------------------------------------------------- + // Setup + // --------------------------------------------------------------------- + + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_ROOT_VMID, ppid, vpid); + integration::require_success(ret); + + // --------------------------------------------------------------------- + // Bootstrap Tests + // --------------------------------------------------------------------- + + // destroy with invalid handle + ret = syscall::bf_vp_op_destroy_vp({}, vpid); + integration::verify(bsl::errc_failure == ret); + + // destroy with invalid ID + ret = syscall::bf_vp_op_destroy_vp(g_handle, syscall::BF_INVALID_ID); + integration::verify(bsl::errc_failure == ret); + + // destroy with ID that is greater than or equal to MAX_VPS + ret = syscall::bf_vp_op_destroy_vp(g_handle, bsl::to_u16(HYPERVISOR_MAX_VPS)); + integration::verify(bsl::errc_failure == ret); + + // destroy with VP that has not been created + constexpr auto invalid_vpid{2_u16}; + ret = syscall::bf_vp_op_destroy_vp(g_handle, invalid_vpid); + integration::verify(bsl::errc_failure == ret); + + // destroy success + ret = syscall::bf_vp_op_destroy_vp(g_handle, vpid); + integration::verify(bsl::errc_success == ret); + + // destroy same VP twice (double free bug) + ret = syscall::bf_vp_op_destroy_vp(g_handle, vpid); + integration::verify(bsl::errc_failure == ret); + + // create all, then destroy all, prove that we can still create + for (bsl::safe_uintmax i{}; i < HYPERVISOR_MAX_VPS; ++i) { + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_ROOT_VMID, ppid, vpid); + integration::require_success(ret); + } + + for (bsl::safe_uintmax i{}; i < HYPERVISOR_MAX_VPS; ++i) { + ret = syscall::bf_vp_op_destroy_vp(g_handle, bsl::to_u16(i)); + integration::verify(bsl::errc_success == ret); + } + + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_ROOT_VMID, ppid, vpid); + integration::require_success(ret); + integration::require(vpid.is_zero()); + + // --------------------------------------------------------------------- + // The following is needed to setup the remaining tests + // --------------------------------------------------------------------- + + ret = syscall::bf_vps_op_create_vps(g_handle, vpid, ppid, vpsid); + integration::require_success(ret); + + ret = syscall::bf_vps_op_init_as_root(g_handle, vpsid); + integration::require_success(ret); + + ret = init_vps(g_handle, vpsid); + integration::require_success(ret); + + ret = syscall::bf_vps_op_run(g_handle, vpid, vpid, vpsid); + integration::require_success(ret); + + bsl::print() << bsl::here(); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_bootstrap(g_handle, &bootstrap_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_vmexit(g_handle, &vmexit_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_fail(g_handle, &fail_entry); + integration::require_success(ret); + + syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/bf_vps_op_init_as_root.cpp b/kernel/integration/bf_vps_op_init_as_root.cpp new file mode 100644 index 00000000..af51ffe6 --- /dev/null +++ b/kernel/integration/bf_vps_op_init_as_root.cpp @@ -0,0 +1,179 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include +#include +#include +#include + +namespace integration +{ + /// @brief stores the handle the extension will use + constinit inline syscall::bf_handle_t g_handle{}; + + /// + /// @brief Implements the VPExit entry function. + /// + /// + /// @param vpsid the ID of the VPS that generated the VPExit + /// @param exit_reason the exit reason associated with the VPExit + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + vmexit_entry(bsl::uint16 const vpsid, bsl::uint64 const exit_reason) noexcept + { + bsl::errc_type ret{}; + + bsl::discard(vpsid); + bsl::discard(exit_reason); + + // --------------------------------------------------------------------- + // VMExit Tests + // --------------------------------------------------------------------- + + // destroy assigned VP (turns VP into zombie) + ret = syscall::bf_vps_op_destroy_vps(g_handle, syscall::bf_tls_vpsid()); + integration::verify(bsl::errc_failure == ret); + + // destroy zombie + ret = syscall::bf_vps_op_destroy_vps(g_handle, syscall::bf_tls_vpsid()); + integration::verify(bsl::errc_failure == ret); + + // --------------------------------------------------------------------- + // Done + // --------------------------------------------------------------------- + + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. + /// + /// + /// @param fail_reason the exit reason associated with the fail + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + fail_entry(syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(fail_reason); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the bootstrap entry function. + /// + /// + /// @param ppid the physical process to bootstrap + /// + void + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + bootstrap_entry(bsl::uint16 const ppid) noexcept + { + bsl::errc_type ret{}; + + bsl::safe_uint16 vpid{}; + bsl::safe_uint16 vpsid{}; + + // --------------------------------------------------------------------- + // Setup + // --------------------------------------------------------------------- + + ret = syscall::bf_vp_op_create_vp(g_handle, syscall::BF_ROOT_VMID, ppid, vpid); + integration::require_success(ret); + + ret = syscall::bf_vps_op_create_vps(g_handle, vpid, ppid, vpsid); + integration::require_success(ret); + + // --------------------------------------------------------------------- + // Bootstrap Tests + // --------------------------------------------------------------------- + + // init with invalid handle + ret = syscall::bf_vps_op_init_as_root({}, vpsid); + integration::require_success(ret); + + // destroy with invalid ID + ret = syscall::bf_vps_op_init_as_root({}, syscall::BF_INVALID_ID); + integration::require_success(ret); + + // --------------------------------------------------------------------- + // The following is needed to setup the remaining tests + // --------------------------------------------------------------------- + + ret = syscall::bf_vps_op_create_vps(g_handle, vpid, ppid, vpsid); + integration::require_success(ret); + + ret = syscall::bf_vps_op_init_as_root(g_handle, vpsid); + integration::require_success(ret); + + ret = init_vps(g_handle, vpsid); + integration::require_success(ret); + + ret = syscall::bf_vps_op_run(g_handle, syscall::BF_ROOT_VMID, vpid, vpsid); + integration::require_success(ret); + + bsl::print() << bsl::here(); + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this integration + /// test + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle(syscall::BF_SPEC_ID1_VAL, g_handle); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_bootstrap(g_handle, &bootstrap_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_vmexit(g_handle, &vmexit_entry); + integration::require_success(ret); + + ret = syscall::bf_callback_op_register_fail(g_handle, &fail_entry); + integration::require_success(ret); + + syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/fast_fail_exit_from_bootstrap.cpp b/kernel/integration/fast_fail_exit_from_bootstrap.cpp new file mode 100644 index 00000000..2f228115 --- /dev/null +++ b/kernel/integration/fast_fail_exit_from_bootstrap.cpp @@ -0,0 +1,107 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include + +namespace integration +{ + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::discard(ppid); + + bsl::error() << "extension purposely exiting early\n"; + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + integration::require_success( + g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry)); + + return syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/fast_fail_exit_from_bootstrap_with_no_syscall.cpp b/kernel/integration/fast_fail_exit_from_bootstrap_with_no_syscall.cpp new file mode 100644 index 00000000..1a55f8f6 --- /dev/null +++ b/kernel/integration/fast_fail_exit_from_bootstrap_with_no_syscall.cpp @@ -0,0 +1,105 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include + +namespace integration +{ + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::discard(ppid); + bsl::error() << "extension purposely not calling exit syscall. fault expected\n"; + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + integration::require_success( + g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry)); + + return syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/fast_fail_exit_from_bootstrap_with_segfault.cpp b/kernel/integration/fast_fail_exit_from_bootstrap_with_segfault.cpp new file mode 100644 index 00000000..c6df4420 --- /dev/null +++ b/kernel/integration/fast_fail_exit_from_bootstrap_with_segfault.cpp @@ -0,0 +1,110 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include + +namespace integration +{ + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::discard(ppid); + + bsl::error() << "extension purposely dereferencing nullptr. fault expected\n"; + bool *i{}; + // This is intentional as it is what we are testing. + // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) + *i = true; + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + integration::require_success( + g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry)); + + return syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/fast_fail_exit_from_bootstrap_with_wait.cpp b/kernel/integration/fast_fail_exit_from_bootstrap_with_wait.cpp new file mode 100644 index 00000000..470d34cd --- /dev/null +++ b/kernel/integration/fast_fail_exit_from_bootstrap_with_wait.cpp @@ -0,0 +1,107 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include + +namespace integration +{ + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::discard(ppid); + + bsl::error() << "extension purposely exiting early using the wrong ABI\n"; + syscall::bf_control_op_wait(); + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + integration::require_success( + g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry)); + + return syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/fast_fail_exit_from_main.cpp b/kernel/integration/fast_fail_exit_from_main.cpp new file mode 100644 index 00000000..ea7a03c4 --- /dev/null +++ b/kernel/integration/fast_fail_exit_from_main.cpp @@ -0,0 +1,106 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include + +namespace integration +{ + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::discard(ppid); + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + integration::require_success( + g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry)); + + bsl::error() << "extension purposely exiting early\n"; + syscall::bf_control_op_exit(); + } +} diff --git a/kernel/integration/fast_fail_exit_from_main_with_no_syscall.cpp b/kernel/integration/fast_fail_exit_from_main_with_no_syscall.cpp new file mode 100644 index 00000000..1ce6db07 --- /dev/null +++ b/kernel/integration/fast_fail_exit_from_main_with_no_syscall.cpp @@ -0,0 +1,105 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include + +namespace integration +{ + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::discard(ppid); + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + integration::require_success( + g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry)); + + bsl::error() << "extension purposely not calling exit syscall. fault expected\n"; + } +} diff --git a/kernel/integration/fast_fail_exit_from_main_with_segfault.cpp b/kernel/integration/fast_fail_exit_from_main_with_segfault.cpp new file mode 100644 index 00000000..d32d1b32 --- /dev/null +++ b/kernel/integration/fast_fail_exit_from_main_with_segfault.cpp @@ -0,0 +1,109 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include + +namespace integration +{ + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::discard(ppid); + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + integration::require_success( + g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry)); + + bsl::error() << "extension purposely dereferencing nullptr. fault expected\n"; + bool *i{}; + // This is intentional as it is what we are testing. + // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) + *i = true; + } +} diff --git a/kernel/integration/fast_fail_exit_from_vmexit.cpp b/kernel/integration/fast_fail_exit_from_vmexit.cpp new file mode 100644 index 00000000..797f5106 --- /dev/null +++ b/kernel/integration/fast_fail_exit_from_vmexit.cpp @@ -0,0 +1,156 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace integration +{ + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + /// @brief stores the intrinsic_t that this code will use + constinit intrinsic_t g_intrinsic{}; + + /// @brief stores the pool of VPs that we will use + constinit vp_pool_t g_vp_pool{}; + /// @brief stores the pool of VPSs that we will use + constinit vps_pool_t g_vps_pool{}; + + /// @brief stores the bootstrap_t that this code will use + constinit bootstrap_t g_bootstrap{}; + + /// @brief stores the Global Storage for this extension + constinit gs_t g_gs{}; + /// @brief stores the Thread Local Storage for this extension on this PP + thread_local tls_t g_tls{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::errc_type ret{}; + + ret = g_bootstrap.dispatch( // -- + g_gs, // -- + g_tls, // -- + g_sys, // -- + g_intrinsic, // -- + g_vp_pool, // -- + g_vps_pool, // -- + ppid); + + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + bsl::error() << "extension purposely exiting early\n"; + syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + ret = g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry); + integration::require_success(ret); + + ret = g_intrinsic.initialize(g_gs, g_tls); + integration::require_success(ret); + + ret = g_vp_pool.initialize(g_gs, g_tls, g_sys, g_intrinsic); + integration::require_success(ret); + + ret = g_vps_pool.initialize(g_gs, g_tls, g_sys, g_intrinsic); + integration::require_success(ret); + + ret = g_bootstrap.initialize(g_gs, g_tls, g_sys, g_intrinsic, g_vp_pool, g_vps_pool); + integration::require_success(ret); + + return syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/fast_fail_exit_from_vmexit_with_no_syscall.cpp b/kernel/integration/fast_fail_exit_from_vmexit_with_no_syscall.cpp new file mode 100644 index 00000000..3f73bbb3 --- /dev/null +++ b/kernel/integration/fast_fail_exit_from_vmexit_with_no_syscall.cpp @@ -0,0 +1,155 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace integration +{ + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + /// @brief stores the intrinsic_t that this code will use + constinit intrinsic_t g_intrinsic{}; + + /// @brief stores the pool of VPs that we will use + constinit vp_pool_t g_vp_pool{}; + /// @brief stores the pool of VPSs that we will use + constinit vps_pool_t g_vps_pool{}; + + /// @brief stores the bootstrap_t that this code will use + constinit bootstrap_t g_bootstrap{}; + + /// @brief stores the Global Storage for this extension + constinit gs_t g_gs{}; + /// @brief stores the Thread Local Storage for this extension on this PP + thread_local tls_t g_tls{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::errc_type ret{}; + + ret = g_bootstrap.dispatch( // -- + g_gs, // -- + g_tls, // -- + g_sys, // -- + g_intrinsic, // -- + g_vp_pool, // -- + g_vps_pool, // -- + ppid); + + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + bsl::error() << "extension purposely not calling exit syscall. fault expected\n"; + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + ret = g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry); + integration::require_success(ret); + + ret = g_intrinsic.initialize(g_gs, g_tls); + integration::require_success(ret); + + ret = g_vp_pool.initialize(g_gs, g_tls, g_sys, g_intrinsic); + integration::require_success(ret); + + ret = g_vps_pool.initialize(g_gs, g_tls, g_sys, g_intrinsic); + integration::require_success(ret); + + ret = g_bootstrap.initialize(g_gs, g_tls, g_sys, g_intrinsic, g_vp_pool, g_vps_pool); + integration::require_success(ret); + + return syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/fast_fail_exit_from_vmexit_with_segfault.cpp b/kernel/integration/fast_fail_exit_from_vmexit_with_segfault.cpp new file mode 100644 index 00000000..5a48f31c --- /dev/null +++ b/kernel/integration/fast_fail_exit_from_vmexit_with_segfault.cpp @@ -0,0 +1,159 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace integration +{ + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + /// @brief stores the intrinsic_t that this code will use + constinit intrinsic_t g_intrinsic{}; + + /// @brief stores the pool of VPs that we will use + constinit vp_pool_t g_vp_pool{}; + /// @brief stores the pool of VPSs that we will use + constinit vps_pool_t g_vps_pool{}; + + /// @brief stores the bootstrap_t that this code will use + constinit bootstrap_t g_bootstrap{}; + + /// @brief stores the Global Storage for this extension + constinit gs_t g_gs{}; + /// @brief stores the Thread Local Storage for this extension on this PP + thread_local tls_t g_tls{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::errc_type ret{}; + + ret = g_bootstrap.dispatch( // -- + g_gs, // -- + g_tls, // -- + g_sys, // -- + g_intrinsic, // -- + g_vp_pool, // -- + g_vps_pool, // -- + ppid); + + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + bsl::error() << "extension purposely dereferencing nullptr. fault expected\n"; + bool *i{}; + // This is intentional as it is what we are testing. + // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) + *i = true; + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + ret = g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry); + integration::require_success(ret); + + ret = g_intrinsic.initialize(g_gs, g_tls); + integration::require_success(ret); + + ret = g_vp_pool.initialize(g_gs, g_tls, g_sys, g_intrinsic); + integration::require_success(ret); + + ret = g_vps_pool.initialize(g_gs, g_tls, g_sys, g_intrinsic); + integration::require_success(ret); + + ret = g_bootstrap.initialize(g_gs, g_tls, g_sys, g_intrinsic, g_vp_pool, g_vps_pool); + integration::require_success(ret); + + return syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/fast_fail_exit_from_vmexit_with_wait.cpp b/kernel/integration/fast_fail_exit_from_vmexit_with_wait.cpp new file mode 100644 index 00000000..4fc79ff2 --- /dev/null +++ b/kernel/integration/fast_fail_exit_from_vmexit_with_wait.cpp @@ -0,0 +1,156 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace integration +{ + /// @brief stores the bf_syscall_t that this code will use + constinit syscall::bf_syscall_t g_sys{}; + /// @brief stores the intrinsic_t that this code will use + constinit intrinsic_t g_intrinsic{}; + + /// @brief stores the pool of VPs that we will use + constinit vp_pool_t g_vp_pool{}; + /// @brief stores the pool of VPSs that we will use + constinit vps_pool_t g_vps_pool{}; + + /// @brief stores the bootstrap_t that this code will use + constinit bootstrap_t g_bootstrap{}; + + /// @brief stores the Global Storage for this extension + constinit gs_t g_gs{}; + /// @brief stores the Thread Local Storage for this extension on this PP + thread_local tls_t g_tls{}; + + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::errc_type ret{}; + + ret = g_bootstrap.dispatch( // -- + g_gs, // -- + g_tls, // -- + g_sys, // -- + g_intrinsic, // -- + g_vp_pool, // -- + g_vps_pool, // -- + ppid); + + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return syscall::bf_control_op_exit(); + } + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + bsl::error() << "extension purposely exiting early using the wrong ABI\n"; + syscall::bf_control_op_wait(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::errc_type ret{}; + + ret = g_sys.initialize(version, &bootstrap_entry, &vmexit_entry, &fail_entry); + integration::require_success(ret); + + ret = g_intrinsic.initialize(g_gs, g_tls); + integration::require_success(ret); + + ret = g_vp_pool.initialize(g_gs, g_tls, g_sys, g_intrinsic); + integration::require_success(ret); + + ret = g_vps_pool.initialize(g_gs, g_tls, g_sys, g_intrinsic); + integration::require_success(ret); + + ret = g_bootstrap.initialize(g_gs, g_tls, g_sys, g_intrinsic, g_vp_pool, g_vps_pool); + integration::require_success(ret); + + return syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/fast_fail_wait_no_bootstrap.cpp b/kernel/integration/fast_fail_wait_no_bootstrap.cpp new file mode 100644 index 00000000..be48e18d --- /dev/null +++ b/kernel/integration/fast_fail_wait_no_bootstrap.cpp @@ -0,0 +1,102 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include + +namespace integration +{ + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::safe_uintmax hndl{}; + syscall::bf_status_t ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle_impl(syscall::BF_SPEC_ID1_VAL.get(), hndl.data()); + integration::require(ret == syscall::BF_STATUS_SUCCESS); + + ret = syscall::bf_callback_op_register_vmexit_impl(hndl.get(), &vmexit_entry); + integration::require(ret == syscall::BF_STATUS_SUCCESS); + + ret = syscall::bf_callback_op_register_fail_impl(hndl.get(), &fail_entry); + integration::require(ret == syscall::BF_STATUS_SUCCESS); + + return syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/fast_fail_wait_no_fail.cpp b/kernel/integration/fast_fail_wait_no_fail.cpp new file mode 100644 index 00000000..5324ac9a --- /dev/null +++ b/kernel/integration/fast_fail_wait_no_fail.cpp @@ -0,0 +1,97 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include + +namespace integration +{ + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::discard(ppid); + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the VMExit entry function. This is registered + /// by the main function to execute whenever a VMExit occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" void + vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::safe_uintmax hndl{}; + syscall::bf_status_t ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle_impl(syscall::BF_SPEC_ID1_VAL.get(), hndl.data()); + integration::require(ret == syscall::BF_STATUS_SUCCESS); + + ret = syscall::bf_callback_op_register_bootstrap_impl(hndl.get(), &bootstrap_entry); + integration::require(ret == syscall::BF_STATUS_SUCCESS); + + ret = syscall::bf_callback_op_register_vmexit_impl(hndl.get(), &vmexit_entry); + integration::require(ret == syscall::BF_STATUS_SUCCESS); + + return syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/fast_fail_wait_no_vmexit.cpp b/kernel/integration/fast_fail_wait_no_vmexit.cpp new file mode 100644 index 00000000..a44d6f2c --- /dev/null +++ b/kernel/integration/fast_fail_wait_no_vmexit.cpp @@ -0,0 +1,97 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "integration_utils.hpp" + +#include +#include + +#include + +namespace integration +{ + /// + /// @brief Implements the bootstrap entry function. This function is + /// called on each PP while the hypervisor is being bootstrapped. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" void + bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::discard(ppid); + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the fast fail entry function. This is registered + /// by the main function to execute whenever a fast fail occurs. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" void + fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + + return syscall::bf_control_op_exit(); + } + + /// + /// @brief Implements the main entry function for this example + /// + /// + /// @param version the version of the spec implemented by the + /// microkernel. This can be used to ensure the extension and the + /// microkernel speak the same ABI. + /// + extern "C" void + ext_main_entry(bsl::uint32 const version) noexcept + { + bsl::safe_uintmax hndl{}; + syscall::bf_status_t ret{}; + + if (bsl::unlikely(!syscall::bf_is_spec1_supported(version))) { + bsl::error() << "integration test not supported\n" << bsl::here(); + return syscall::bf_control_op_exit(); + } + + ret = syscall::bf_handle_op_open_handle_impl(syscall::BF_SPEC_ID1_VAL.get(), hndl.data()); + integration::require(ret == syscall::BF_STATUS_SUCCESS); + + ret = syscall::bf_callback_op_register_bootstrap_impl(hndl.get(), &bootstrap_entry); + integration::require(ret == syscall::BF_STATUS_SUCCESS); + + ret = syscall::bf_callback_op_register_fail_impl(hndl.get(), &fail_entry); + integration::require(ret == syscall::BF_STATUS_SUCCESS); + + return syscall::bf_control_op_wait(); + } +} diff --git a/kernel/integration/integration_targets.cmake b/kernel/integration/integration_targets.cmake new file mode 100644 index 00000000..fa3d6e45 --- /dev/null +++ b/kernel/integration/integration_targets.cmake @@ -0,0 +1,48 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +include(${CMAKE_CURRENT_LIST_DIR}/../../cmake/function/hypervisor_add_integration_target.cmake) + +hypervisor_add_integration_target(bf_callback_op_register_bootstrap) +hypervisor_add_integration_target(bf_callback_op_register_fail) +hypervisor_add_integration_target(bf_callback_op_register_vmexit) +hypervisor_add_integration_target(bf_handle_op_close_handle) +hypervisor_add_integration_target(bf_handle_op_open_handle) +hypervisor_add_integration_target(bf_vm_op_create_vm) +hypervisor_add_integration_target(bf_vm_op_destroy_vm) +hypervisor_add_integration_target(bf_vp_op_create_vp) +hypervisor_add_integration_target(bf_vp_op_destroy_vp) +hypervisor_add_integration_target(bf_vps_op_create_vps) +hypervisor_add_integration_target(bf_vps_op_destroy_vps) +hypervisor_add_integration_target(fast_fail_exit_from_bootstrap_with_no_syscall) +hypervisor_add_integration_target(fast_fail_exit_from_bootstrap_with_segfault) +hypervisor_add_integration_target(fast_fail_exit_from_bootstrap_with_wait) +hypervisor_add_integration_target(fast_fail_exit_from_bootstrap) +hypervisor_add_integration_target(fast_fail_exit_from_main_with_no_syscall) +hypervisor_add_integration_target(fast_fail_exit_from_main_with_segfault) +hypervisor_add_integration_target(fast_fail_exit_from_main) +hypervisor_add_integration_target(fast_fail_exit_from_vmexit_with_no_syscall) +hypervisor_add_integration_target(fast_fail_exit_from_vmexit_with_segfault) +hypervisor_add_integration_target(fast_fail_exit_from_vmexit_with_wait) +hypervisor_add_integration_target(fast_fail_exit_from_vmexit) +hypervisor_add_integration_target(fast_fail_wait_no_bootstrap) +hypervisor_add_integration_target(fast_fail_wait_no_fail) +hypervisor_add_integration_target(fast_fail_wait_no_vmexit) diff --git a/kernel/integration/integration_utils.hpp b/kernel/integration/integration_utils.hpp new file mode 100644 index 00000000..b4789290 --- /dev/null +++ b/kernel/integration/integration_utils.hpp @@ -0,0 +1,121 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INTEGRATION_UTILS_HPP +#define INTEGRATION_UTILS_HPP + +#include + +#include +#include +#include +#include + +namespace integration +{ + /// + /// @brief Reports passed/failed so that a script can detect if the + /// failed text shows up in the log. + /// + /// + /// @param test the results to query + /// @param sloc used to identify the location in the integration test + /// where a check failed. + /// + constexpr void + verify(bool const test, bsl::source_location const &sloc = bsl::here()) noexcept + { + if (bsl::unlikely(!test)) { + bsl::print() << bsl::red << "integration test failed"; + bsl::print() << bsl::rst << sloc; + } + else { + bsl::touch(); + } + } + + /// + /// @brief Reports passed/failed so that a script can detect if the + /// failed text shows up in the log. If the test fails, this + /// function will abort. + /// + /// + /// @param test the results to query + /// @param sloc used to identify the location in the integration test + /// where a check failed. + /// + constexpr void + require(bool const test, bsl::source_location const &sloc = bsl::here()) noexcept + { + if (bsl::unlikely(!test)) { + bsl::print() << bsl::red << "integration test failed"; + bsl::print() << bsl::rst << sloc; + syscall::bf_control_op_exit(); + } + else { + bsl::touch(); + } + } + + /// + /// @brief Reports passed/failed so that a script can detect if the + /// failed text shows up in the log. If the test fails, this + /// function will abort. + /// + /// + /// @param ec the results to query + /// @param sloc used to identify the location in the integration test + /// where a check failed. + /// + constexpr void + require_success( + bsl::errc_type const ec, bsl::source_location const &sloc = bsl::here()) noexcept + { + if (bsl::unlikely(!ec.success())) { + bsl::print() << bsl::red << "integration test failed"; + bsl::print() << bsl::rst << sloc; + syscall::bf_control_op_exit(); + } + else { + bsl::touch(); + } + } + + /// + /// @brief Exits early. This is done by sending an error code, so the + /// microkernel will actually report and error, but this is intended + /// so that we can return back and try the next integration test. + /// + constexpr void + early() noexcept + { + bsl::print() << bsl::rst << bsl::endl; + bsl::print() << bsl::mag << "return early backlog:"; + bsl::print() << bsl::rst << bsl::endl; + + return syscall::bf_control_op_exit(); + } +} + +#endif diff --git a/kernel/integration/support/arm/aarch64/gs_t.hpp b/kernel/integration/support/arm/aarch64/gs_t.hpp new file mode 100644 index 00000000..1fd3f40e --- /dev/null +++ b/kernel/integration/support/arm/aarch64/gs_t.hpp @@ -0,0 +1,41 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef GS_T_HPP +#define GS_T_HPP + +#include + +namespace integration +{ + /// @class integration::gs_t + /// + /// + /// @brief Defines the extension's Global Storage (GS). + /// + struct gs_t final + {}; +} + +#endif diff --git a/kernel/integration/support/arm/aarch64/intrinsic_t.hpp b/kernel/integration/support/arm/aarch64/intrinsic_t.hpp new file mode 100644 index 00000000..a35b8f01 --- /dev/null +++ b/kernel/integration/support/arm/aarch64/intrinsic_t.hpp @@ -0,0 +1,79 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INTRINSIC_HPP +#define INTRINSIC_HPP + +#include +#include + +#include +#include +#include + +namespace integration +{ + /// @class integration::intrinsic_t + /// + /// + /// @brief Provides raw access to intrinsics. + /// + class intrinsic_t final + { + public: + /// + /// @brief Initializes this intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize(gs_t &gs, tls_t &tls) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + + return bsl::errc_success; + } + + /// + /// @brief Release the intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + } + }; +} + +#endif diff --git a/kernel/integration/support/arm/aarch64/tls_t.hpp b/kernel/integration/support/arm/aarch64/tls_t.hpp new file mode 100644 index 00000000..4e1d080a --- /dev/null +++ b/kernel/integration/support/arm/aarch64/tls_t.hpp @@ -0,0 +1,48 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TLS_T_HPP +#define TLS_T_HPP + +#include +#include + +namespace integration +{ + /// @class integration::tls_t + /// + /// + /// @brief Defines the extension's Thread Local Storage (TLS). + /// + struct tls_t final + {}; + + /// @brief defines the max size supported for the TLS block + constexpr auto MAX_TLS_SIZE{HYPERVISOR_PAGE_SIZE}; + + /// @brief ensure that the tls_t does not exceed the max supported size + static_assert(!(sizeof(tls_t) > MAX_TLS_SIZE)); +} + +#endif diff --git a/kernel/integration/support/arm/aarch64/vmexit_t.hpp b/kernel/integration/support/arm/aarch64/vmexit_t.hpp new file mode 100644 index 00000000..4f745251 --- /dev/null +++ b/kernel/integration/support/arm/aarch64/vmexit_t.hpp @@ -0,0 +1,153 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_T_HPP +#define VMEXIT_T_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace integration +{ + /// @class integration::vmexit_t + /// + /// + /// @brief Defines the extension's VMExit handler + /// + class vmexit_t final + { + public: + /// + /// @brief Initializes this vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + return bsl::errc_success; + } + + /// + /// @brief Release the vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + } + + /// + /// @brief Dispatches the VMExit. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint64 const &exit_reason) noexcept -> bsl::errc_type + { + switch (exit_reason.get()) { + default: { + break; + } + } + + bsl::error() << "unsupported vmexit " // -- + << bsl::hex(exit_reason) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + }; +} + +#endif diff --git a/kernel/integration/support/arm/aarch64/vps_t.hpp b/kernel/integration/support/arm/aarch64/vps_t.hpp new file mode 100644 index 00000000..5e48d111 --- /dev/null +++ b/kernel/integration/support/arm/aarch64/vps_t.hpp @@ -0,0 +1,143 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VPS_T_HPP +#define VPS_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace integration +{ + /// @class integration::vps_t + /// + /// + /// @brief Defines the extension's notion of a VPS + /// + class vps_t final + { + /// @brief stores the ID associated with this vps_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + + public: + /// + /// @brief Initializes this vps_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param i the ID for this vps_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + m_id = i; + return bsl::errc_success; + } + + /// + /// @brief Release the vps_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + m_id = bsl::safe_uint16::failure(); + } + + /// + /// @brief Allocates a vps_t and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vpid the ID of the VP to assign the vps_t to + /// @param ppid the ID of the PP to assign the vps_t to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(vpid); + bsl::discard(ppid); + + ret = sys.bf_vps_op_init_as_root(m_id); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return bsl::errc_success; + } + }; +} + +#endif diff --git a/kernel/integration/support/bootstrap_t.hpp b/kernel/integration/support/bootstrap_t.hpp new file mode 100644 index 00000000..7b49bad1 --- /dev/null +++ b/kernel/integration/support/bootstrap_t.hpp @@ -0,0 +1,157 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef BOOTSTRAP_T_HPP +#define BOOTSTRAP_T_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace integration +{ + /// @class integration::bootstrap_t + /// + /// + /// @brief Defines the extension's bootstrap handler + /// + class bootstrap_t final + { + public: + /// + /// @brief Initializes this bootstrap_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + return bsl::errc_success; + } + + /// + /// @brief Release the bootstrap_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + } + + /// + /// @brief Dispatches the bootstrap process as needed. Note that + /// the bootstrap callback is only called when starting the + /// hypervisor on root VPs. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param ppid the ID of the PP to bootstrap + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + auto const vmid{syscall::BF_ROOT_VMID}; + + auto const vpid{vp_pool.allocate(gs, tls, sys, intrinsic, vmid, ppid)}; + if (bsl::unlikely_assert(!vpid)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + auto const vpsid{vps_pool.allocate(gs, tls, sys, intrinsic, vpid, ppid)}; + if (bsl::unlikely_assert(!vpsid)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + return sys.bf_vps_op_run(vmid, vpid, vpsid); + } + }; +} + +#endif diff --git a/kernel/integration/support/vp_pool_t.hpp b/kernel/integration/support/vp_pool_t.hpp new file mode 100644 index 00000000..d11c4986 --- /dev/null +++ b/kernel/integration/support/vp_pool_t.hpp @@ -0,0 +1,170 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VP_POOL_T_HPP +#define VP_POOL_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace integration +{ + /// @class integration::vp_pool_t + /// + /// + /// @brief Defines the extension's VP pool + /// + class vp_pool_t final + { + /// @brief stores the pool of VPs + bsl::array m_pool{}; + + public: + /// + /// @brief Initializes this vp_pool_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + -> bsl::errc_type + { + bsl::finally_assert release_on_error{ + [this, &gs, &tls, &sys, &intrinsic]() noexcept -> void { + this->release(gs, tls, sys, intrinsic); + }}; + + bsl::errc_type ret{}; + for (bsl::safe_uintmax i{}; i < m_pool.size(); ++i) { + ret = m_pool.at_if(i)->initialize(gs, tls, sys, intrinsic, bsl::to_u16(i)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + + release_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Release the vp_pool_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + for (bsl::safe_uintmax i{}; i < m_pool.size(); ++i) { + m_pool.at_if(i)->release(gs, tls, sys, intrinsic); + } + } + + /// + /// @brief Allocates a VP and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vmid the ID of the VM to assign the newly created VP to + /// @param ppid the ID of the PP to assign the newly created VP to + /// @return Returns the ID of the newly created VP on + /// success, or bsl::safe_uint16::failure() on failure. + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vmid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::safe_uint16 + { + bsl::errc_type ret{}; + bsl::safe_uint16 vpid{}; + + vpid = sys.bf_vp_op_create_vp(vmid, ppid); + if (bsl::unlikely_assert(!vpid)) { + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); + } + + bsl::finally destroy_vp_on_error{[&sys, &vpid]() noexcept -> void { + bsl::discard(sys.bf_vp_op_destroy_vp(vpid)); + }}; + + auto *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() << "vpid " // -- + << bsl::hex(vpid) // -- + << " provided by the microkernel is invalid" // -- + << " or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + ret = vp->allocate(gs, tls, sys, intrinsic, vmid, ppid); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); + } + + destroy_vp_on_error.ignore(); + return vpid; + } + }; +} + +#endif diff --git a/kernel/integration/support/vp_t.hpp b/kernel/integration/support/vp_t.hpp new file mode 100644 index 00000000..06b58f83 --- /dev/null +++ b/kernel/integration/support/vp_t.hpp @@ -0,0 +1,130 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VP_T_HPP +#define VP_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace integration +{ + /// @class integration::vp_t + /// + /// + /// @brief Defines the extension's notion of a VP + /// + class vp_t final + { + public: + /// + /// @brief Initializes this vp_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param i the ID for this vp_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(i); + + return bsl::errc_success; + } + + /// + /// @brief Release the vp_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + } + + /// + /// @brief Allocates a vp_t and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vmid the ID of the VM to assign the vp_t to + /// @param ppid the ID of the PP to assign the vp_t to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vmid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vmid); + bsl::discard(ppid); + + return bsl::errc_success; + } + }; +} + +#endif diff --git a/kernel/integration/support/vps_pool_t.hpp b/kernel/integration/support/vps_pool_t.hpp new file mode 100644 index 00000000..02a2dac2 --- /dev/null +++ b/kernel/integration/support/vps_pool_t.hpp @@ -0,0 +1,170 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VPS_POOL_T_HPP +#define VPS_POOL_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace integration +{ + /// @class integration::vps_pool_t + /// + /// + /// @brief Defines the extension's VPS pool + /// + class vps_pool_t final + { + /// @brief stores the pool of VPSs + bsl::array m_pool{}; + + public: + /// + /// @brief Initializes this vps_pool_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + -> bsl::errc_type + { + bsl::finally_assert release_on_error{ + [this, &gs, &tls, &sys, &intrinsic]() noexcept -> void { + this->release(gs, tls, sys, intrinsic); + }}; + + bsl::errc_type ret{}; + for (bsl::safe_uintmax i{}; i < m_pool.size(); ++i) { + ret = m_pool.at_if(i)->initialize(gs, tls, sys, intrinsic, bsl::to_u16(i)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + + release_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Release the vps_pool_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + for (bsl::safe_uintmax i{}; i < m_pool.size(); ++i) { + m_pool.at_if(i)->release(gs, tls, sys, intrinsic); + } + } + + /// + /// @brief Allocates a VPS and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vpid the ID of the VP to assign the newly created VPS to + /// @param ppid the ID of the PP to assign the newly created VPS to + /// @return Returns the ID of the newly created VPS on + /// success, or bsl::safe_uint16::failure() on failure. + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::safe_uint16 + { + bsl::errc_type ret{}; + bsl::safe_uint16 vpsid{}; + + vpsid = sys.bf_vps_op_create_vps(vpid, ppid); + if (bsl::unlikely_assert(!vpsid)) { + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); + } + + bsl::finally destroy_vps_on_error{[&sys, &vpsid]() noexcept -> void { + bsl::discard(sys.bf_vps_op_destroy_vps(vpsid)); + }}; + + auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " provided by the microkernel is invalid" // -- + << " or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + ret = vps->allocate(gs, tls, sys, intrinsic, vpid, ppid); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); + } + + destroy_vps_on_error.ignore(); + return vpsid; + } + }; +} + +#endif diff --git a/kernel/integration/support/x64/amd/gs_t.hpp b/kernel/integration/support/x64/amd/gs_t.hpp new file mode 100644 index 00000000..1fd3f40e --- /dev/null +++ b/kernel/integration/support/x64/amd/gs_t.hpp @@ -0,0 +1,41 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef GS_T_HPP +#define GS_T_HPP + +#include + +namespace integration +{ + /// @class integration::gs_t + /// + /// + /// @brief Defines the extension's Global Storage (GS). + /// + struct gs_t final + {}; +} + +#endif diff --git a/kernel/integration/support/x64/amd/intrinsic_t.hpp b/kernel/integration/support/x64/amd/intrinsic_t.hpp new file mode 100644 index 00000000..09a7e4c2 --- /dev/null +++ b/kernel/integration/support/x64/amd/intrinsic_t.hpp @@ -0,0 +1,100 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INTRINSIC_HPP +#define INTRINSIC_HPP + +#include +#include +#include + +#include +#include +#include + +namespace integration +{ + /// @class integration::intrinsic_t + /// + /// + /// @brief Provides raw access to intrinsics. + /// + class intrinsic_t final + { + public: + /// + /// @brief Initializes this intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize(gs_t &gs, tls_t &tls) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + + return bsl::errc_success; + } + + /// + /// @brief Release the intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + } + + /// + /// @brief Executes the CPUID instruction given the provided + /// EAX and ECX and returns the results. + /// + /// + /// @param rax the index used by CPUID, returns resulting rax + /// @param rbx returns resulting rbx + /// @param rcx the subindex used by CPUID, returns the resulting rcx + /// @param rdx returns resulting rdx + /// + static constexpr void + cpuid( + bsl::safe_uint64 &rax, + bsl::safe_uint64 &rbx, + bsl::safe_uint64 &rcx, + bsl::safe_uint64 &rdx) noexcept + { + intrinsic_cpuid_impl(rax.data(), rbx.data(), rcx.data(), rdx.data()); + } + }; +} + +#endif diff --git a/kernel/integration/support/x64/amd/tls_t.hpp b/kernel/integration/support/x64/amd/tls_t.hpp new file mode 100644 index 00000000..4e1d080a --- /dev/null +++ b/kernel/integration/support/x64/amd/tls_t.hpp @@ -0,0 +1,48 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TLS_T_HPP +#define TLS_T_HPP + +#include +#include + +namespace integration +{ + /// @class integration::tls_t + /// + /// + /// @brief Defines the extension's Thread Local Storage (TLS). + /// + struct tls_t final + {}; + + /// @brief defines the max size supported for the TLS block + constexpr auto MAX_TLS_SIZE{HYPERVISOR_PAGE_SIZE}; + + /// @brief ensure that the tls_t does not exceed the max supported size + static_assert(!(sizeof(tls_t) > MAX_TLS_SIZE)); +} + +#endif diff --git a/kernel/integration/support/x64/amd/vmexit_t.hpp b/kernel/integration/support/x64/amd/vmexit_t.hpp new file mode 100644 index 00000000..6f5de70f --- /dev/null +++ b/kernel/integration/support/x64/amd/vmexit_t.hpp @@ -0,0 +1,242 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_T_HPP +#define VMEXIT_T_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace example +{ + /// @class example::vmexit_t + /// + /// + /// @brief Defines the extension's VMExit handler + /// + class vmexit_t final + { + public: + /// + /// @brief Initializes this vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + return bsl::errc_success; + } + + /// + /// @brief Release the vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + } + + /// + /// @brief Handles the CPUID VMexit + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + handle_cpuid( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + bsl::errc_type ret{}; + + auto rax{sys.bf_tls_rax()}; + auto rbx{sys.bf_tls_rbx()}; + auto rcx{sys.bf_tls_rcx()}; + auto rdx{sys.bf_tls_rdx()}; + + if (loader::CPUID_COMMAND_EAX == bsl::to_u32_unsafe(rax)) { + switch (bsl::to_u32_unsafe(rcx).get()) { + case loader::CPUID_COMMAND_ECX_STOP.get(): { + sys.bf_tls_set_rax(loader::CPUID_COMMAND_RAX_SUCCESS); + + ret = sys.bf_vps_op_advance_ip(vpsid); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return sys.bf_vps_op_promote(vpsid); + } + + case loader::CPUID_COMMAND_ECX_REPORT_ON.get(): { + break; + } + + case loader::CPUID_COMMAND_ECX_REPORT_OFF.get(): { + break; + } + + default: { + bsl::error() << "unsupported cpuid command " // -- + << bsl::hex(rcx) // -- + << bsl::endl // -- + << bsl::here(); // -- + + break; + } + } + + return sys.bf_vps_op_advance_ip_and_run_current(); + } + + intrinsic.cpuid(rax, rbx, rcx, rdx); + + sys.bf_tls_set_rax(rax); + sys.bf_tls_set_rbx(rbx); + sys.bf_tls_set_rcx(rcx); + sys.bf_tls_set_rdx(rdx); + + return sys.bf_vps_op_advance_ip_and_run_current(); + } + + /// + /// @brief Dispatches the VMExit. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint64 const &exit_reason) noexcept -> bsl::errc_type + { + constexpr auto exit_reason_cpuid{0x72_u64}; + + switch (exit_reason.get()) { + case exit_reason_cpuid.get(): { + return handle_cpuid(gs, tls, sys, intrinsic, vp_pool, vps_pool, vpsid); + } + + default: { + break; + } + } + + bsl::error() << "unsupported vmexit " // -- + << bsl::hex(exit_reason) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + }; +} + +#endif diff --git a/kernel/integration/support/x64/amd/vps_t.hpp b/kernel/integration/support/x64/amd/vps_t.hpp new file mode 100644 index 00000000..8cdb7e07 --- /dev/null +++ b/kernel/integration/support/x64/amd/vps_t.hpp @@ -0,0 +1,169 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VPS_T_HPP +#define VPS_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace integration +{ + /// @class integration::vps_t + /// + /// + /// @brief Defines the extension's notion of a VPS + /// + class vps_t final + { + /// @brief stores the ID associated with this vps_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + + public: + /// + /// @brief Initializes this vps_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param i the ID for this vps_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + m_id = i; + return bsl::errc_success; + } + + /// + /// @brief Release the vps_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + m_id = bsl::safe_uint16::failure(); + } + + /// + /// @brief Allocates a vps_t and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vpid the ID of the VP to assign the vps_t to + /// @param ppid the ID of the PP to assign the vps_t to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(vpid); + bsl::discard(ppid); + + ret = sys.bf_vps_op_init_as_root(m_id); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + constexpr auto guest_asid_idx{0x0058_u64}; + constexpr auto guest_asid_val{0x1_u32}; + + ret = sys.bf_vps_op_write32(m_id, guest_asid_idx, guest_asid_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + constexpr auto intercept_instr1_idx{0x000C_u64}; + constexpr auto intercept_instr1_val{0x00040000_u32}; + constexpr auto intercept_instr2_idx{0x0010_u64}; + constexpr auto intercept_instr2_val{0x00000001_u32}; + + ret = sys.bf_vps_op_write32(m_id, intercept_instr1_idx, intercept_instr1_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + ret = sys.bf_vps_op_write32(m_id, intercept_instr2_idx, intercept_instr2_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return bsl::errc_success; + } + }; +} + +#endif diff --git a/kernel/integration/support/x64/intel/gs_t.hpp b/kernel/integration/support/x64/intel/gs_t.hpp new file mode 100644 index 00000000..3765b18f --- /dev/null +++ b/kernel/integration/support/x64/intel/gs_t.hpp @@ -0,0 +1,46 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef GS_T_HPP +#define GS_T_HPP + +#include + +namespace integration +{ + /// @class integration::gs_t + /// + /// + /// @brief Defines the extension's Global Storage (GS). + /// + struct gs_t final + { + /// @brief stores the MSR bitmap used by this vps_t + void *msr_bitmap{}; + /// @brief stores the physical address of the MSR bitmap above + bsl::safe_uintmax msr_bitmap_phys{}; + }; +} + +#endif diff --git a/kernel/integration/support/x64/intel/intrinsic_t.hpp b/kernel/integration/support/x64/intel/intrinsic_t.hpp new file mode 100644 index 00000000..09a7e4c2 --- /dev/null +++ b/kernel/integration/support/x64/intel/intrinsic_t.hpp @@ -0,0 +1,100 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INTRINSIC_HPP +#define INTRINSIC_HPP + +#include +#include +#include + +#include +#include +#include + +namespace integration +{ + /// @class integration::intrinsic_t + /// + /// + /// @brief Provides raw access to intrinsics. + /// + class intrinsic_t final + { + public: + /// + /// @brief Initializes this intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize(gs_t &gs, tls_t &tls) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + + return bsl::errc_success; + } + + /// + /// @brief Release the intrinsic_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// + static constexpr void + release(gs_t &gs, tls_t &tls) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + } + + /// + /// @brief Executes the CPUID instruction given the provided + /// EAX and ECX and returns the results. + /// + /// + /// @param rax the index used by CPUID, returns resulting rax + /// @param rbx returns resulting rbx + /// @param rcx the subindex used by CPUID, returns the resulting rcx + /// @param rdx returns resulting rdx + /// + static constexpr void + cpuid( + bsl::safe_uint64 &rax, + bsl::safe_uint64 &rbx, + bsl::safe_uint64 &rcx, + bsl::safe_uint64 &rdx) noexcept + { + intrinsic_cpuid_impl(rax.data(), rbx.data(), rcx.data(), rdx.data()); + } + }; +} + +#endif diff --git a/kernel/integration/support/x64/intel/tls_t.hpp b/kernel/integration/support/x64/intel/tls_t.hpp new file mode 100644 index 00000000..4e1d080a --- /dev/null +++ b/kernel/integration/support/x64/intel/tls_t.hpp @@ -0,0 +1,48 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TLS_T_HPP +#define TLS_T_HPP + +#include +#include + +namespace integration +{ + /// @class integration::tls_t + /// + /// + /// @brief Defines the extension's Thread Local Storage (TLS). + /// + struct tls_t final + {}; + + /// @brief defines the max size supported for the TLS block + constexpr auto MAX_TLS_SIZE{HYPERVISOR_PAGE_SIZE}; + + /// @brief ensure that the tls_t does not exceed the max supported size + static_assert(!(sizeof(tls_t) > MAX_TLS_SIZE)); +} + +#endif diff --git a/kernel/integration/support/x64/intel/vmexit_t.hpp b/kernel/integration/support/x64/intel/vmexit_t.hpp new file mode 100644 index 00000000..857484fa --- /dev/null +++ b/kernel/integration/support/x64/intel/vmexit_t.hpp @@ -0,0 +1,383 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_T_HPP +#define VMEXIT_T_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace integration +{ + /// @class integration::vmexit_t + /// + /// + /// @brief Defines the extension's VMExit handler + /// + class vmexit_t final + { + public: + /// + /// @brief Initializes this vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + gs.msr_bitmap = sys.bf_mem_op_alloc_page(gs.msr_bitmap_phys); + if (bsl::unlikely_assert(nullptr == gs.msr_bitmap)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Release the vmexit_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// + static constexpr void + release( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept + { + bsl::errc_type ret{}; + + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + ret = sys.bf_mem_op_free_page(gs.msr_bitmap); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + } + else { + bsl::touch(); + } + + gs.msr_bitmap = {}; + gs.msr_bitmap_phys = {}; + } + + /// + /// @brief Handle NMIs. This is required by Intel. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + handle_nmi( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + constexpr auto vmcs_procbased_ctls_idx{0x4002_u64}; + constexpr auto vmcs_set_nmi_window_exiting{0x400000_u32}; + + bsl::safe_uint32 val{}; + bsl::errc_type ret{}; + + val = sys.bf_vps_op_read32(vpsid, vmcs_procbased_ctls_idx); + if (bsl::unlikely_assert(!val)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + val |= vmcs_set_nmi_window_exiting; + + ret = sys.bf_vps_op_write32(vpsid, vmcs_procbased_ctls_idx, val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return sys.bf_vps_op_run_current(); + } + + /// + /// @brief Handle NMIs Windows + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + handle_nmi_window( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + constexpr auto vmcs_procbased_ctls_idx{0x4002_u64}; + constexpr auto vmcs_clear_nmi_window_exiting{0xFFBFFFFF_u32}; + + bsl::safe_uint32 val{}; + bsl::errc_type ret{}; + + val = sys.bf_vps_op_read32(vpsid, vmcs_procbased_ctls_idx); + if (bsl::unlikely_assert(!val)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + val &= vmcs_clear_nmi_window_exiting; + + ret = sys.bf_vps_op_write32(vpsid, vmcs_procbased_ctls_idx, val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + constexpr auto vmcs_entry_interrupt_info_idx{0x4016_u64}; + constexpr auto vmcs_entry_interrupt_info_val{0x80000202_u32}; + + ret = sys.bf_vps_op_write32( + vpsid, vmcs_entry_interrupt_info_idx, vmcs_entry_interrupt_info_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return sys.bf_vps_op_run_current(); + } + + /// + /// @brief Handles the CPUID VMexit + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + handle_cpuid( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + bsl::errc_type ret{}; + + auto rax{sys.bf_tls_rax()}; + auto rbx{sys.bf_tls_rbx()}; + auto rcx{sys.bf_tls_rcx()}; + auto rdx{sys.bf_tls_rdx()}; + + if (loader::CPUID_COMMAND_EAX == bsl::to_u32_unsafe(rax)) { + switch (bsl::to_u32_unsafe(rcx).get()) { + case loader::CPUID_COMMAND_ECX_STOP.get(): { + sys.bf_tls_set_rax(loader::CPUID_COMMAND_RAX_SUCCESS); + + ret = sys.bf_vps_op_advance_ip(vpsid); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return sys.bf_vps_op_promote(vpsid); + } + + case loader::CPUID_COMMAND_ECX_REPORT_ON.get(): { + break; + } + + case loader::CPUID_COMMAND_ECX_REPORT_OFF.get(): { + break; + } + + default: { + bsl::error() << "unsupported cpuid command " // -- + << bsl::hex(rcx) // -- + << bsl::endl // -- + << bsl::here(); // -- + + break; + } + } + + return sys.bf_vps_op_advance_ip_and_run_current(); + } + + intrinsic.cpuid(rax, rbx, rcx, rdx); + + sys.bf_tls_set_rax(rax); + sys.bf_tls_set_rbx(rbx); + sys.bf_tls_set_rcx(rcx); + sys.bf_tls_set_rdx(rdx); + + return sys.bf_vps_op_advance_ip_and_run_current(); + } + + /// + /// @brief Dispatches the VMExit. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + dispatch( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint64 const &exit_reason) noexcept -> bsl::errc_type + { + constexpr auto exit_reason_nmi{0x0_u64}; + constexpr auto exit_reason_nmi_window{0x8_u64}; + constexpr auto exit_reason_cpuid{0xA_u64}; + + switch (exit_reason.get()) { + case exit_reason_nmi.get(): { + return handle_nmi(gs, tls, sys, intrinsic, vp_pool, vps_pool, vpsid); + } + + case exit_reason_nmi_window.get(): { + return handle_nmi_window(gs, tls, sys, intrinsic, vp_pool, vps_pool, vpsid); + } + + case exit_reason_cpuid.get(): { + return handle_cpuid(gs, tls, sys, intrinsic, vp_pool, vps_pool, vpsid); + } + + default: { + break; + } + } + + bsl::error() << "unsupported vmexit " // -- + << bsl::hex(exit_reason) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + }; +} + +#endif diff --git a/kernel/integration/support/x64/intel/vps_t.hpp b/kernel/integration/support/x64/intel/vps_t.hpp new file mode 100644 index 00000000..536ce8d3 --- /dev/null +++ b/kernel/integration/support/x64/intel/vps_t.hpp @@ -0,0 +1,277 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VPS_T_HPP +#define VPS_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace integration +{ + /// + /// @brief Returns the masked version of the VMCS control fields + /// + /// + /// @param val the value of the control fields read from the MSRs + /// @return The masked version of the control fields. + /// + [[nodiscard]] constexpr auto + ctls_mask(bsl::safe_uint64 const &val) noexcept -> bsl::safe_uint32 + { + constexpr auto mask{0x00000000FFFFFFFF_u64}; + constexpr auto shift{32_u64}; + return bsl::to_u32_unsafe((val & mask) & (val >> shift)); + }; + + /// @class integration::vps_t + /// + /// + /// @brief Defines the extension's notion of a VPS + /// + class vps_t final + { + /// @brief stores the ID associated with this vps_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + + public: + /// + /// @brief Initializes this vps_t + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param i the ID for this vps_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + m_id = i; + return bsl::errc_success; + } + + /// + /// @brief Release the vps_t. + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// + constexpr void + release(gs_t &gs, tls_t &tls, syscall::bf_syscall_t &sys, intrinsic_t &intrinsic) noexcept + { + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(sys); + bsl::discard(intrinsic); + + m_id = bsl::safe_uint16::failure(); + } + + /// + /// @brief Allocates a vps_t and returns it's ID + /// + /// + /// @param gs the gs_t to use + /// @param tls the tls_t to use + /// @param sys the bf_syscall_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vpid the ID of the VP to assign the vps_t to + /// @param ppid the ID of the PP to assign the vps_t to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate( + gs_t &gs, + tls_t &tls, + syscall::bf_syscall_t &sys, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + bsl::discard(gs); + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(vpid); + bsl::discard(ppid); + + ret = sys.bf_vps_op_init_as_root(m_id); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + constexpr auto vmcs_vpid_idx{0x0000_u64}; + constexpr auto vmcs_vpid_val{0x1_u16}; + + ret = sys.bf_vps_op_write16(m_id, vmcs_vpid_idx, vmcs_vpid_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + constexpr auto vmcs_link_ptr_idx{0x2800_u64}; + constexpr auto vmcs_link_ptr_val{0xFFFFFFFFFFFFFFFF_u64}; + + ret = sys.bf_vps_op_write64(m_id, vmcs_link_ptr_idx, vmcs_link_ptr_val); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + constexpr auto vmcs_pinbased_ctls_idx{0x4000_u64}; + constexpr auto vmcs_procbased_ctls_idx{0x4002_u64}; + constexpr auto vmcs_exit_ctls_idx{0x400C_u64}; + constexpr auto vmcs_entry_ctls_idx{0x4012_u64}; + constexpr auto vmcs_procbased_ctls2_idx{0x401E_u64}; + + constexpr auto ia32_vmx_true_pinbased_ctls{0x48D_u32}; + constexpr auto ia32_vmx_true_procbased_ctls{0x48E_u32}; + constexpr auto ia32_vmx_true_exit_ctls{0x48F_u32}; + constexpr auto ia32_vmx_true_entry_ctls{0x490_u32}; + constexpr auto ia32_vmx_true_procbased_ctls2{0x48B_u32}; + + bsl::safe_uintmax ctls{}; + + ctls = sys.bf_intrinsic_op_rdmsr(ia32_vmx_true_pinbased_ctls); + if (bsl::unlikely_assert(!ctls)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = sys.bf_vps_op_write32(m_id, vmcs_pinbased_ctls_idx, ctls_mask(ctls)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + constexpr auto enable_msr_bitmaps{0x10000000_u64}; + constexpr auto enable_procbased_ctls2{0x80000000_u64}; + + ctls = sys.bf_intrinsic_op_rdmsr(ia32_vmx_true_procbased_ctls); + if (bsl::unlikely_assert(!ctls)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ctls |= enable_msr_bitmaps; + ctls |= enable_procbased_ctls2; + + ret = sys.bf_vps_op_write32(m_id, vmcs_procbased_ctls_idx, ctls_mask(ctls)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + ctls = sys.bf_intrinsic_op_rdmsr(ia32_vmx_true_exit_ctls); + if (bsl::unlikely_assert(!ctls)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = sys.bf_vps_op_write32(m_id, vmcs_exit_ctls_idx, ctls_mask(ctls)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + ctls = sys.bf_intrinsic_op_rdmsr(ia32_vmx_true_entry_ctls); + if (bsl::unlikely_assert(!ctls)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = sys.bf_vps_op_write32(m_id, vmcs_entry_ctls_idx, ctls_mask(ctls)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + constexpr auto enable_vpid{0x00000020_u64}; + constexpr auto enable_rdtscp{0x00000008_u64}; + constexpr auto enable_invpcid{0x00001000_u64}; + constexpr auto enable_xsave{0x00100000_u64}; + constexpr auto enable_uwait{0x04000000_u64}; + + ctls = sys.bf_intrinsic_op_rdmsr(ia32_vmx_true_procbased_ctls2); + if (bsl::unlikely_assert(!ctls)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ctls |= enable_vpid; + ctls |= enable_rdtscp; + ctls |= enable_invpcid; + ctls |= enable_xsave; + ctls |= enable_uwait; + + ret = sys.bf_vps_op_write32(m_id, vmcs_procbased_ctls2_idx, ctls_mask(ctls)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + constexpr auto vmcs_msr_bitmaps{0x2004_u64}; + + ret = sys.bf_vps_op_write64(m_id, vmcs_msr_bitmaps, gs.msr_bitmap_phys); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return bsl::errc_success; + } + }; +} + +#endif diff --git a/kernel/integration/support/x64/intrinsic_cpuid_impl.S b/kernel/integration/support/x64/intrinsic_cpuid_impl.S new file mode 100644 index 00000000..98e67426 --- /dev/null +++ b/kernel/integration/support/x64/intrinsic_cpuid_impl.S @@ -0,0 +1,52 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl intrinsic_cpuid_impl + .type intrinsic_cpuid_impl, @function +intrinsic_cpuid_impl: + push rbx + + mov r10, rdx + mov r11, rcx + + mov eax, [rdi] + mov ebx, [rsi] + mov ecx, [r10] + mov edx, [r11] + cpuid + mov [rdi], eax + mov [rsi], ebx + mov [r10], ecx + mov [r11], edx + + pop rbx + ret + int 3 + + .size intrinsic_cpuid_impl, .-intrinsic_cpuid_impl diff --git a/kernel/integration/support/x64/intrinsic_cpuid_impl.hpp b/kernel/integration/support/x64/intrinsic_cpuid_impl.hpp new file mode 100644 index 00000000..5bf31d65 --- /dev/null +++ b/kernel/integration/support/x64/intrinsic_cpuid_impl.hpp @@ -0,0 +1,49 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INTRINSIC_IMPL_PROTOTYPES_HPP +#define INTRINSIC_IMPL_PROTOTYPES_HPP + +#include + +namespace integration +{ + /// + /// @brief Executes the CPUID instruction given the provided EAX and ECX + /// and returns the results + /// + /// + /// @param rax the index used by CPUID, returns resulting rax + /// @param rbx returns resulting rbx + /// @param rcx the subindex used by CPUID, returns the resulting rcx + /// @param rdx returns resulting rdx + /// + extern "C" void intrinsic_cpuid_impl( + bsl::uint64 *const rax, + bsl::uint64 *const rbx, + bsl::uint64 *const rcx, + bsl::uint64 *const rdx) noexcept; +} + +#endif diff --git a/kernel/mocks/lock_guard_t.hpp b/kernel/mocks/lock_guard_t.hpp new file mode 100644 index 00000000..2d1e2bfb --- /dev/null +++ b/kernel/mocks/lock_guard_t.hpp @@ -0,0 +1,110 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_LOCK_GUARD_T_HPP +#define MOCKS_LOCK_GUARD_T_HPP + +#include + +#include + +namespace mk +{ + /// @class mk::lock_guard_t + /// + /// + /// @brief Implements a mocked version of lock_guard_t. + /// + /// + /// @tparam T the type of mutex being locked + /// + template + class lock_guard_t final + { + public: + /// + /// @brief Creates a lock_guard_t, locking the provided + /// spinlock/mutex on construction. + /// + /// + /// @param tls the current TLS block + /// @param lck the spinlock/mutex to guard + /// + constexpr lock_guard_t(tls_t const &tls, T &lck) noexcept // -- + { + bsl::discard(tls); + bsl::discard(lck); + } + + /// + /// @brief Do not allow temporaries. + /// + /// + /// @param tls the current TLS block + /// @param lck the spinlock/mutex to guard + /// + constexpr lock_guard_t(tls_t const &tls, T const &lck) noexcept = delete; + + /// + /// @brief Destructor + /// + constexpr ~lock_guard_t() noexcept = default; + + /// + /// @brief copy constructor + /// + /// + /// @param o the object being copied + /// + constexpr lock_guard_t(lock_guard_t const &o) noexcept = delete; + + /// + /// @brief move constructor + /// + /// + /// @param o the object being moved + /// + constexpr lock_guard_t(lock_guard_t &&o) noexcept = default; + + /// + /// @brief copy assignment + /// + /// + /// @param o the object being copied + /// @return a reference to *this + /// + [[maybe_unused]] auto operator=(lock_guard_t const &o) &noexcept -> lock_guard_t & = delete; + + /// + /// @brief move assignment + /// + /// + /// @param o the object being moved + /// @return a reference to *this + /// + [[maybe_unused]] auto operator=(lock_guard_t &&o) &noexcept -> lock_guard_t & = default; + }; +} + +#endif diff --git a/kernel/mocks/spinlock_t.hpp b/kernel/mocks/spinlock_t.hpp new file mode 100644 index 00000000..0d55f24c --- /dev/null +++ b/kernel/mocks/spinlock_t.hpp @@ -0,0 +1,95 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_SPINLOCK_T_HPP +#define MOCKS_SPINLOCK_T_HPP + +#include +#include + +#include + +namespace mk +{ + /// @class mk::spinlock_t + /// + /// + /// @brief Implements a mocked version of spinlock_t + /// + /// + /// @note This spinlock_t is designed to detect and prevent deadlock + /// when the same PP attempts to take the lock more than once. This + /// could occur for example if a hardware exception fires before + /// the lock is released. It also handles the case when the lock is + /// taken, and then an ESR fires that is legit and must take the + /// lock as well. + /// + class spinlock_t final + { + /// @brief stores whether or not the spin lock is locked. + bool m_flag{}; + + public: + /// + /// @brief Locks the spinlock_t. This will not return until the + /// spinlock_t can be successfully acquired. + /// + /// + /// @param tls the current TLS block + /// + constexpr void + lock(tls_t const &tls) noexcept + { + bsl::discard(tls); + m_flag = true; + } + + /// + /// @brief Unlocks the spinlock_t. + /// + /// + /// @param tls the current TLS block + /// + constexpr void + unlock(tls_t const &tls) noexcept + { + bsl::discard(tls); + m_flag = false; + } + + /// + /// @brief Returns true if the spinlock_t is locked + /// + /// + /// @return Returns true if the spinlock_t is locked + /// + [[nodiscard]] constexpr auto + is_locked() const noexcept -> bool + { + return m_flag; + } + }; +} + +#endif diff --git a/kernel/mocks/state_save_t.hpp b/kernel/mocks/state_save_t.hpp new file mode 100644 index 00000000..808a5118 --- /dev/null +++ b/kernel/mocks/state_save_t.hpp @@ -0,0 +1,39 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_STATE_SAVE_T_HPP +#define MOCKS_STATE_SAVE_T_HPP + +namespace loader +{ + /// @struct loader::state_save_t + /// + /// + /// @brief TODO + /// + struct state_save_t final + {}; +} + +#endif diff --git a/kernel/mocks/tls_t.hpp b/kernel/mocks/tls_t.hpp new file mode 100644 index 00000000..fae605e1 --- /dev/null +++ b/kernel/mocks/tls_t.hpp @@ -0,0 +1,203 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_TLS_T_HPP +#define MOCKS_TLS_T_HPP + +#include + +#include +#include + +namespace mk +{ + /// @struct mk::tls_t + /// + /// + /// @brief Defines the layout of the microkernel's TLS block. This + /// should not be confused with the TLS blocks given to an extension, + /// for which there are two, the TLS block for thread_local and the + /// TLS block provided by the microkernel's ABI. + /// + struct tls_t final + { + /// -------------------------------------------------------------------- + /// Extension State + /// -------------------------------------------------------------------- + + /// @brief RAX, stores the extension's syscall + bsl::uintmax ext_syscall; + /// @brief RDI, stores the value of REG0 for the extension + bsl::uintmax ext_reg0; + /// @brief RSI, stores the value of REG1 for the extension + bsl::uintmax ext_reg1; + /// @brief RDX, stores the value of REG2 for the extension + bsl::uintmax ext_reg2; + /// @brief R10, stores the value of REG3 for the extension + bsl::uintmax ext_reg3; + /// @brief R8, stores the value of REG4 for the extension + bsl::uintmax ext_reg4; + /// @brief R9, stores the value of REG5 for the extension + bsl::uintmax ext_reg5; + + /// -------------------------------------------------------------------- + /// ESR State + /// -------------------------------------------------------------------- + + /// @brief stores the value of ip for the ESR + bsl::uintmax esr_ip; + /// @brief stores the value of sp for the ESR + bsl::uintmax esr_sp; + + /// @brief stores the value of the ESR vector + bsl::uintmax esr_vector; + /// @brief stores the value of the ESR error code + bsl::uintmax esr_error_code; + + /// @brief stores the value of a page fault address for the ESR + bsl::uintmax esr_pf_addr; + + /// -------------------------------------------------------------------- + /// Fast Fail Information + /// -------------------------------------------------------------------- + + /// @brief stores the current fast fail address + bsl::uintmax current_fast_fail_ip; + /// @brief stores the current fast fail stack + bsl::uintmax current_fast_fail_sp; + + /// @brief stores the mk_main fast fail address + bsl::uintmax mk_main_fast_fail_ip; + /// @brief stores the mk_main fast fail stack + bsl::uintmax mk_main_fast_fail_sp; + + /// @brief stores the call_ext fast fail address + bsl::uintmax call_ext_fast_fail_ip; + /// @brief stores the call_ext fast fail stack + bsl::uintmax call_ext_fast_fail_sp; + + /// @brief stores the dispatch_syscall fast fail address + bsl::uintmax dispatch_syscall_fast_fail_ip; + /// @brief stores the dispatch_syscall fast fail stack + bsl::uintmax dispatch_syscall_fast_fail_sp; + + /// @brief stores the vmexit loop address + bsl::uintmax vmexit_loop_ip; + /// @brief stores the vmexit loop stack + bsl::uintmax vmexit_loop_sp; + + /// -------------------------------------------------------------------- + /// Context Information + /// -------------------------------------------------------------------- + + /// @brief stores the virtual address of this TLS block + tls_t *self; + + /// @brief stores the currently active VMID + bsl::uint16 ppid; + /// @brief stores the total number of online PPs + bsl::uint16 online_pps; + /// @brief reserved + bsl::uint16 reserved_padding0; + /// @brief reserved + bsl::uint16 reserved_padding1; + + /// @brief stores the currently active extension + void *ext; + /// @brief stores the extension registered for VMExits + void *ext_vmexit; + /// @brief stores the extension registered for fast fail events + void *ext_fail; + + /// @brief stores the loader provided state for the microkernel + loader::state_save_t *mk_state; + /// @brief stores the loader provided state for the root VP + loader::state_save_t *root_vp_state; + + /// @brief stores the currently active extension ID + bsl::uint16 active_extid; + /// @brief stores the currently active VMID + bsl::uint16 active_vmid; + /// @brief stores the currently active VPID + bsl::uint16 active_vpid; + /// @brief stores the currently active VPSID + bsl::uint16 active_vpsid; + + /// @brief stores the sp used by extensions for callbacks + bsl::uintmax sp; + /// @brief stores the tps used by extensions for callbacks + bsl::uintmax tp; + + /// @brief used to store a return address for unsafe ops + bsl::uintmax unsafe_rip; + + /// @brief reserved + bsl::uintmax reserved_padding2; + /// @brief reserved + bsl::uintmax reserved_padding3; + + /// @brief stores whether or not the first launch succeeded + bsl::uintmax first_launch_succeeded; + + /// @brief stores the currently active root page table + void *active_rpt; + + /// -------------------------------------------------------------------- + /// Failure Handling + /// -------------------------------------------------------------------- + + /// @brief stores a whether or not state is changing + bool state_reversal_required; + + /// @brief stores the syscall return status + bsl::uintmax syscall_ret_status; + + /// @brief logs an extid for state reversal if needed + bsl::uint16 log_extid; + /// @brief logs a vmid for state reversal if needed + bsl::uint16 log_vmid; + /// @brief logs a vpid for state reversal if needed + bsl::uint16 log_vpid; + /// @brief logs a vpsid for state reversal if needed + bsl::uint16 log_vpsid; + + /// @brief logs an ext for state reversal if needed + void *log_ext; + /// @brief logs a vm for state reversal if needed + void *log_vm; + /// @brief logs a vp for state reversal if needed + void *log_vp; + /// @brief logs a vps for state reversal if needed + void *log_vps; + + /// -------------------------------------------------------------------- + /// Unit Test Specific + /// -------------------------------------------------------------------- + + /// @brief used by some of the unit tests + bsl::errc_type test_ret; + }; +} + +#endif diff --git a/kernel/src/arm/aarch64/__stack_chk_fail.S b/kernel/src/arm/aarch64/__stack_chk_fail.S new file mode 100644 index 00000000..28a62fc5 --- /dev/null +++ b/kernel/src/arm/aarch64/__stack_chk_fail.S @@ -0,0 +1,36 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl __stack_chk_fail + .type __stack_chk_fail, @function +__stack_chk_fail: + + bl msg_stack_chk_fail + b return_to_current_fast_fail + + .size __stack_chk_fail, .-__stack_chk_fail diff --git a/kernel/src/arm/aarch64/call_ext.S b/kernel/src/arm/aarch64/call_ext.S new file mode 100644 index 00000000..6336e150 --- /dev/null +++ b/kernel/src/arm/aarch64/call_ext.S @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl call_ext + .type call_ext, @function +call_ext: + + .size call_ext, .-call_ext + + /**************************************************************************/ + /* Fast Fail Routine */ + /**************************************************************************/ + + .globl call_ext_fast_fail_entry + .type call_ext_fast_fail_entry, @function +call_ext_fast_fail_entry: + + .size call_ext_fast_fail_entry, .-call_ext_fast_fail_entry diff --git a/kernel/src/dispatch_esr_trampoline.cpp b/kernel/src/arm/aarch64/dispatch_esr.hpp similarity index 65% rename from kernel/src/dispatch_esr_trampoline.cpp rename to kernel/src/arm/aarch64/dispatch_esr.hpp index 8e2c91e8..e8c3c5aa 100644 --- a/kernel/src/dispatch_esr_trampoline.cpp +++ b/kernel/src/arm/aarch64/dispatch_esr.hpp @@ -22,33 +22,43 @@ /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE /// SOFTWARE. -#include -#include +#ifndef DISPATCH_ESR_HPP +#define DISPATCH_ESR_HPP + +#include +#include +#include #include -#include +#include #include +#include +#include +#include +#include namespace mk { /// - /// @brief Since we cannot create a template function pointer, we need - /// a way to call a template function from our ASM entry point. - /// Normally the way this works in a normal program is the OS calls - /// _start, which then calls main(). The main() function, which is - /// an extern C function, similar to this function, can then call a - /// template function as needed. So the whole point of this function - /// is to simply trampoline from our ASM logic, to a C++ template - /// function that is easy to test. + /// @brief Provides the main entry point for all exceptions. This + /// function will dispatch exceptions as needed. /// /// /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @param intrinsic the intrinsics to use /// @return Returns bsl::exit_success if the exception was handled, /// bsl::exit_failure otherwise /// - extern "C" [[nodiscard]] auto - dispatch_esr_trampoline(tls_t *const tls) noexcept -> bsl::exit_code + [[nodiscard]] constexpr auto + dispatch_esr(tls_t &tls, ext_t *const ext, intrinsic_t &intrinsic) noexcept -> bsl::exit_code { - return dispatch_esr(*tls, g_intrinsic); + bsl::discard(tls); + bsl::discard(ext); + bsl::discard(intrinsic); + + return bsl::exit_failure; } } + +#endif diff --git a/kernel/src/arm/aarch64/dispatch_esr_entry.S b/kernel/src/arm/aarch64/dispatch_esr_entry.S new file mode 100644 index 00000000..d1a10915 --- /dev/null +++ b/kernel/src/arm/aarch64/dispatch_esr_entry.S @@ -0,0 +1,33 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl dispatch_esr_entry + .type dispatch_esr_entry, @function +dispatch_esr_entry: + + .size dispatch_esr_entry, .-dispatch_esr_entry diff --git a/kernel/src/arm/aarch64/dispatch_syscall_entry.S b/kernel/src/arm/aarch64/dispatch_syscall_entry.S new file mode 100644 index 00000000..fdabafe3 --- /dev/null +++ b/kernel/src/arm/aarch64/dispatch_syscall_entry.S @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl dispatch_syscall_entry + .type dispatch_syscall_entry, @function +dispatch_syscall_entry: + + .size dispatch_syscall_entry, .-dispatch_syscall_entry + + /**************************************************************************/ + /* Fast Fail Routine */ + /**************************************************************************/ + + .globl dispatch_syscall_fast_fail_entry + .type dispatch_syscall_fast_fail_entry, @function +dispatch_syscall_fast_fail_entry: + + .size dispatch_syscall_fast_fail_entry, .-dispatch_syscall_fast_fail_entry diff --git a/kernel/src/arm/aarch64/dispatch_syscall_intrinsic_op.hpp b/kernel/src/arm/aarch64/dispatch_syscall_intrinsic_op.hpp new file mode 100644 index 00000000..66d57ef6 --- /dev/null +++ b/kernel/src/arm/aarch64/dispatch_syscall_intrinsic_op.hpp @@ -0,0 +1,82 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_SYSCALL_INTRINSIC_OP_HPP +#define DISPATCH_SYSCALL_INTRINSIC_OP_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Dispatches the bf_intrinsic_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @param intrinsic the intrinsics to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + dispatch_syscall_intrinsic_op(tls_t &tls, ext_t const &ext, intrinsic_t &intrinsic) + -> bsl::errc_type + { + bsl::discard(intrinsic); + + if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { + bsl::error() << "invalid handle " // -- + << bsl::hex(tls.ext_reg0) // -- + << bsl::endl // -- + << bsl::here(); // -- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_INVALID_HANDLE.get(); + return bsl::errc_failure; + } + + switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { + default: { + break; + } + } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; + } +} + +#endif diff --git a/kernel/src/arm/aarch64/fast_fail_entry.S b/kernel/src/arm/aarch64/fast_fail_entry.S new file mode 100644 index 00000000..3798483c --- /dev/null +++ b/kernel/src/arm/aarch64/fast_fail_entry.S @@ -0,0 +1,33 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl fast_fail_entry + .type fast_fail_entry, @function +fast_fail_entry: + + .size fast_fail_entry, .-fast_fail_entry diff --git a/kernel/src/arm/aarch64/get_current_tls.S b/kernel/src/arm/aarch64/get_current_tls.S new file mode 100644 index 00000000..d8fb4383 --- /dev/null +++ b/kernel/src/arm/aarch64/get_current_tls.S @@ -0,0 +1,36 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl get_current_tls + .type get_current_tls, @function +get_current_tls: + + mrs x0, tpidr_el2 + ret + + .size get_current_tls, .-get_current_tls diff --git a/kernel/src/arm/aarch64/intrinsic_t.S b/kernel/src/arm/aarch64/intrinsic_t.S new file mode 100644 index 00000000..b6bde4f8 --- /dev/null +++ b/kernel/src/arm/aarch64/intrinsic_t.S @@ -0,0 +1,27 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text diff --git a/kernel/src/arm/aarch64/intrinsic_t.hpp b/kernel/src/arm/aarch64/intrinsic_t.hpp new file mode 100644 index 00000000..e870f287 --- /dev/null +++ b/kernel/src/arm/aarch64/intrinsic_t.hpp @@ -0,0 +1,91 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef INTRINSIC_HPP +#define INTRINSIC_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace mk +{ + /// @class mk::intrinsic_t + /// + /// + /// @brief Provides raw access to intrinsics. Instead of using global + /// functions, the intrinsics class provides a means for the rest of + /// the kernel to mock the intrinsics when needed during unit testing. + /// + class intrinsic_t final + { + public: + /// + /// @brief Returns the value of tp (TLS pointer) + /// + /// + /// @return Returns the value of tp (TLS pointer) + /// + [[nodiscard]] static constexpr auto + tp() noexcept -> bsl::safe_uint64 + { + if (bsl::is_constant_evaluated()) { + return {}; + } + + return {}; + } + + /// + /// @brief Sets the value of tp (TLS pointer) + /// + /// + /// @param val the value to set tp (TLS pointer) to + /// + static constexpr void + set_tp(bsl::safe_uint64 const &val) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + if (bsl::unlikely(!val)) { + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return; + } + + bsl::touch(); + } + }; +} + +#endif diff --git a/kernel/src/arm/aarch64/mk_main_entry.S b/kernel/src/arm/aarch64/mk_main_entry.S new file mode 100644 index 00000000..37956154 --- /dev/null +++ b/kernel/src/arm/aarch64/mk_main_entry.S @@ -0,0 +1,293 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + /** @brief defines the offset of mk_args_t.ppid */ + #define ARGS_OFFSET_PPID 0x0 + /** @brief defines the offset of mk_args_t.online_pps */ + #define ARGS_OFFSET_ONLINE_PPS 0x002 + /** @brief defines the offset of mk_args_t.mk_state */ + #define ARGS_OFFSET_MK_STATE 0x008 + /** @brief defines the offset of mk_args_t.root_vp_state */ + #define ARGS_OFFSET_ROOT_VP_STATE 0x010 + /** @brief defines the offset of mk_args_t.debug_ring */ + #define ARGS_OFFSET_DEBUG_RING 0x018 + + /** @brief defines the size of the TLS block */ + #define TLS_SIZE 0x400 + /** @brief defines the offset of tls_t.current_fast_fail_ip */ + #define TLS_OFFSET_CURRENT_FAST_FAIL_IP 0x290 + /** @brief defines the offset of tls_t.current_fast_fail_sp */ + #define TLS_OFFSET_CURRENT_FAST_FAIL_SP 0x298 + /** @brief defines the offset of tls_t.mk_main_fast_fail_ip */ + #define TLS_OFFSET_MK_MAIN_FAST_FAIL_IP 0x2A0 + /** @brief defines the offset of tls_t.mk_main_fast_fail_sp */ + #define TLS_OFFSET_MK_MAIN_FAST_FAIL_SP 0x2A8 + /** @brief defines the offset of tls_t.call_ext_fast_fail_ip */ + #define TLS_OFFSET_CALL_EXT_FAST_FAIL_IP 0x2B0 + /** @brief defines the offset of tls_t.dispatch_syscall_fast_fail_ip */ + #define TLS_OFFSET_DISPATCH_SYSCALL_FAST_FAIL_IP 0x2C0 + /** @brief defines the offset of tls_t.self */ + #define TLS_OFFSET_SELF 0x300 + /** @brief defines the offset of tls_t.ppid */ + #define TLS_OFFSET_PPID 0x308 + /** @brief defines the offset of tls_t.online_pps */ + #define TLS_OFFSET_ONLINE_PPS 0x30A + /** @brief defines the offset of tls_t.mk_state */ + #define TLS_OFFSET_MK_STATE 0x328 + /** @brief defines the offset of tls_t.root_vp_state */ + #define TLS_OFFSET_ROOT_VP_STATE 0x330 + /** @brief defines the offset of tls_t.active_<>id */ + #define TLS_OFFSET_ACTIVE_IDS 0x338 + + .text + + .globl mk_main_entry + .type mk_main_entry, @function +mk_main_entry: + + /** + * NOTE: + * - The first thing we need to do is save off RDI for the fast fail + * handler. If it is called, it will need the args that this function + * was provided, so we leave this on the stack for it. Since the state + * save has the correct stack pointer, we can leave it in this state + * as a safe return that uses the Root VP state will use the correct + * stack pointer, while a failure will use the current stack pointer + * with this return address on it. + * - On ARMv8, we push x1 as well because all stack operations must be + * 16 byte aligned, so we just add x1 as a place holder. + * - We also store x0 into x20 so that we can call functions if needed + * without losing the arguments. + */ + + stp x0, x1, [sp, #-0x10]! + mov x20, x0 + + /** + * NOTE: + * - The next thing to do is get the TLS block for this PP. Each PP has + * it's own TLS block (both in the microkernel, and in each extension) + * which means that our definition of a thread is similar to that of + * Intel's and AMD's, meaning each logical core is a thread. + * - The loader will tell us in the args that it provided what the PPID + * is. Remember that this entry point will be called for each PP, so it + * is called more than once. Once we have the PPID, we can calculate + * which TLS block to grab based on the size of each TLS block. + */ + + mvn x23, xzr + add x21, x20, #ARGS_OFFSET_PPID + ldrh w23, [x21] + + mov x21, #TLS_SIZE + mul x22, x21, x23 + adrp x21, g_tls_blocks + add x22, x21, x22 + + /** + * NOTE: + * - Next we program the platform register with the location of the TLS + * block so that we can index into the TLS block using x18. We also + * put the TLS block into TPIDR_EL2 so that we can restore x18 when + * an exception is taken. + */ + + mov x18, x22 + msr tpidr_el2, x22 + + /** + * NOTE: + * - From here we need to set the "self" pointer in the TLS block as + * well as the PPID to the TLS block so that we always know what the + * PPID is no matter where we are. + */ + + add x21, x18, #TLS_OFFSET_SELF + str x18, [x21] + add x21, x18, #TLS_OFFSET_PPID + str x23, [x21] + + /** + * NOTE: + * - To start, there are no active extensions, VMs, VPs or VPSs. + */ + + mvn x22, xzr + add x21, x18, #TLS_OFFSET_ACTIVE_IDS + str x22, [x21] + + /** + * NOTE: + * - Next we set some of the fast fail entry points in the TLS block. + * These will be used when an error or exception occurs so that + * we can gracefully handle issues. + */ + + adr x22, mk_main_fast_fail_entry + add x21, x18, #TLS_OFFSET_MK_MAIN_FAST_FAIL_IP + str x22, [x21] + + adr x22, call_ext_fast_fail_entry + add x21, x18, #TLS_OFFSET_CALL_EXT_FAST_FAIL_IP + str x22, [x21] + + adr x22, dispatch_syscall_fast_fail_entry + add x21, x18, #TLS_OFFSET_DISPATCH_SYSCALL_FAST_FAIL_IP + str x22, [x21] + + /** + * NOTE: + * - Next we need to set the number of online PPs on the system. + * The microkernel will need to know this so that it can properly set + * up it's internal resources. + */ + + add x21, x20, #ARGS_OFFSET_ONLINE_PPS + ldrh w22, [x21] + add x21, x18, #TLS_OFFSET_ONLINE_PPS + strh w22, [x21] + + /** + * NOTE: + * - Next we store the location of the MK and Root VP state save areas + * that the loader created for us. For the most part, we only really + * need the Root VP state as we will use this to return back to the + * Root VP once we start the hypervisor on this PP, but just in case, + * we also provide the MK state as well. In general, the microkernel + * is really unware of the state that the loader gives it. + */ + + add x21, x20, #ARGS_OFFSET_MK_STATE + ldr x22, [x21] + add x21, x18, #TLS_OFFSET_MK_STATE + str x22, [x21] + + add x21, x20, #ARGS_OFFSET_ROOT_VP_STATE + ldr x22, [x21] + add x21, x18, #TLS_OFFSET_ROOT_VP_STATE + str x22, [x21] + + /** + * NOTE: + * - Next we store the pointer to the debug ring that the loader has + * set up for us. This is needed so that we have somewhere to put + * debug information. + */ + + add x21, x20, #ARGS_OFFSET_DEBUG_RING + ldr x22, [x21] + adr x21, g_debug_ring + str x22, [x21] + + /** + * NOTE: + * - Set up the exception vectors. Currently we are using exception + * vectors provided by the loader. This loads the exception vectors + * that the actual kernel will use. + */ + + /** TODO */ + + /** + * NOTE: + * - This next block of assembly is seen throughout the assembly code. + * Basically, it stores the information needed for fast failing. Each + * time we enter a new context like calling into an extension, handling + * a syscall, etc, we need to swap around the fast fail handler and RSP + * so that we know where to return to in the event of an error. + */ + + mov x22, sp + add x21, x18, #TLS_OFFSET_MK_MAIN_FAST_FAIL_SP + str x22, [x21] + add x21, x18, #TLS_OFFSET_CURRENT_FAST_FAIL_SP + str x22, [x21] + + add x21, x18, #TLS_OFFSET_MK_MAIN_FAST_FAIL_IP + ldr x22, [x21] + add x21, x18, #TLS_OFFSET_CURRENT_FAST_FAIL_IP + str x22, [x21] + + /** + * NOTE: + * - Finally, call the main trampoline. + */ + + mov x0, x20 + mov x1, x18 + bl mk_main_trampoline + + /** + * NOTE: + * - If we get here, it is because an error occurred and we need to + * fast fail. + */ + + b return_to_current_fast_fail + + .size mk_main_entry, .-mk_main_entry + + /**************************************************************************/ + /* Fast Fail Routine */ + /**************************************************************************/ + + .globl mk_main_fast_fail_entry + .type mk_main_fast_fail_entry, @function +mk_main_fast_fail_entry: + + /** + * NOTE: + * - In the beginning of mk_main_entry, we saved the original arguments + * to the stack which we will use here. + * - On ARMv8, we pop x1 as well because all stack operations must be + * 16 byte aligned, so we just add x1 as a place holder. + */ + + ldp x0, x1, [sp], #0x10 + + /** + * NOTE: + * - Promote back to the root OS on failure. + */ + + add x1, x0, #ARGS_OFFSET_ROOT_VP_STATE + ldr x0, [x1] + mov x1, #1 + b promote + + .size mk_main_fast_fail_entry, .-mk_main_fast_fail_entry + + + + /**************************************************************************/ + /* Runtime Helpers */ + /**************************************************************************/ + + .rodata + + .globl __stack_chk_guard +__stack_chk_guard: + .quad 0xDEADBEEFDEADBEEF diff --git a/kernel/src/arm/aarch64/promote.S b/kernel/src/arm/aarch64/promote.S new file mode 100644 index 00000000..227f2800 --- /dev/null +++ b/kernel/src/arm/aarch64/promote.S @@ -0,0 +1,84 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + /** @brief defines the offset of state_save_t.x0 */ + #define SS_OFFSET_X0 0x000 + /** @brief defines the offset of state_save_t.promote_handler */ + #define SS_OFFSET_PROMOTE_HANDLER 0x210 + /** @brief defines the offset of state_save_t.exception_vectors */ + #define SS_OFFSET_EXCEPTION_VECTORS 0x218 + + .text + + .globl promote + .type promote, @function +promote: + + /** + * NOTE: + * - Save off the first argument just in case we need to call other + * functions including debugging. The first argument in this case + * is a pointer to the root VP's state save. + */ + mov x20, x0 + + /** + * NOTE: + * - Store the return value for the demote() function. Once this function + * is done, it will return to the loader's promote() function which + * will return to the C portion of the loader as if demote() had returned + * and this is where we store the return value. Note that promote() + * can be called on error, or when the hypervisor is stopping. + */ + + add x21, x20, #SS_OFFSET_X0 + str x1, [x21] + + /** + * NOTE: + * - Restore the exception vectors. This is needed because we will no + * longer be able to use the exception vectores from the microkernel + * as we unload it, so we will use the exception vectors from the + * loader instead. + */ + + add x21, x20, #SS_OFFSET_EXCEPTION_VECTORS + ldr x22, [x21] + msr vbar_el2, x22 + + /** + * NOTE: + * - Call the loader's promote() handler. This will conclude execution + * from the microkernel. + */ + + add x21, x20, #SS_OFFSET_PROMOTE_HANDLER + ldr x22, [x21] + + mov x2, x20 + ret x22 + + .size promote, .-promote diff --git a/kernel/src/arm/aarch64/return_to_current_fast_fail.S b/kernel/src/arm/aarch64/return_to_current_fast_fail.S new file mode 100644 index 00000000..0098d3ae --- /dev/null +++ b/kernel/src/arm/aarch64/return_to_current_fast_fail.S @@ -0,0 +1,52 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + /** @brief defines the offset of tls_t.current_fast_fail_ip */ + #define TLS_OFFSET_CURRENT_FAST_FAIL_IP 0x290 + /** @brief defines the offset of tls_t.current_fast_fail_sp */ + #define TLS_OFFSET_CURRENT_FAST_FAIL_SP 0x298 + + .text + + .globl return_to_current_fast_fail + .type return_to_current_fast_fail, @function +return_to_current_fast_fail: + + mrs x18, tpidr_el2 + + add x11, x18, #TLS_OFFSET_CURRENT_FAST_FAIL_SP + ldr x10, [x11] + + cbz x10, use_current_stack + mov sp, x10 +use_current_stack: + + add x11, x18, #TLS_OFFSET_CURRENT_FAST_FAIL_IP + ldr x10, [x11] + + ret x10 + + .size return_to_current_fast_fail, .-return_to_current_fast_fail diff --git a/kernel/src/arm/aarch64/return_to_mk.S b/kernel/src/arm/aarch64/return_to_mk.S new file mode 100644 index 00000000..1aef39da --- /dev/null +++ b/kernel/src/arm/aarch64/return_to_mk.S @@ -0,0 +1,33 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl return_to_mk + .type return_to_mk, @function +return_to_mk: + + .size return_to_mk, .-return_to_mk diff --git a/kernel/src/arm/aarch64/return_to_vmexit_loop.S b/kernel/src/arm/aarch64/return_to_vmexit_loop.S new file mode 100644 index 00000000..837c9d05 --- /dev/null +++ b/kernel/src/arm/aarch64/return_to_vmexit_loop.S @@ -0,0 +1,33 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl return_to_vmexit_loop + .type return_to_vmexit_loop, @function +return_to_vmexit_loop: + + .size return_to_vmexit_loop, .-return_to_vmexit_loop diff --git a/kernel/src/arm/aarch64/root_page_table_t.hpp b/kernel/src/arm/aarch64/root_page_table_t.hpp new file mode 100644 index 00000000..2c7aa4e0 --- /dev/null +++ b/kernel/src/arm/aarch64/root_page_table_t.hpp @@ -0,0 +1,1543 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef ROOT_PAGE_TABLE_T_HPP +#define ROOT_PAGE_TABLE_T_HPP + +#include "../../lock_guard_t.hpp" +#include "../../spinlock_t.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mk +{ + /// @class mk::root_page_table_t + /// + /// + /// @brief Implements the root pages tables used by the microkernel + /// for mapping extension memory. + /// + class root_page_table_t final + { + /// @brief stores true if initialized() has been executed + bool m_initialized{}; + /// @brief stores a reference to the intrinsics to use + intrinsic_t *m_intrinsic{}; + /// @brief stores a reference to the page pool to use + page_pool_t *m_page_pool{}; + /// @brief stores a reference to the huge pool to use + huge_pool_t *m_huge_pool{}; + /// @brief stores a pointer to the l0t + l0t_t *m_l0t{}; + /// @brief stores the physical address of the l0t + bsl::safe_uintmax m_l0t_phys{bsl::safe_uintmax::failure()}; + /// @brief safe guards operations on the RPT. + mutable spinlock_t m_lock{}; + + // /// + // /// @brief Returns the index of the last entry present in a page + // /// table. + // /// + // /// + // /// @tparam TABLE_CONCEPT the type of page table to search + // /// @param table the page table to search + // /// @return Returns the index of the last entry present in a page + // /// table. + // /// + // template + // [[nodiscard]] constexpr auto + // get_last_index(TABLE_CONCEPT const *const table) const noexcept -> bsl::safe_uintmax + // { + // bsl::safe_uintmax last_index{}; + // for (auto const elem : table->entries) { + // if (bsl::ZERO_UMAX == elem.data->p) { + // continue; + // } + + // last_index = elem.index; + // } + + // return last_index; + // } + + // /// + // /// @brief Given index and the index of the last + // /// present entry in the page table being dumped, this function + // /// will output a decoration and the index. + // /// + // /// + // /// @param index the current index of the entry being dumped + // /// @param last_index the index of the last present entry in the page + // /// table being dumped. + // /// + // constexpr void + // output_decoration_and_index( + // bsl::safe_uintmax const &index, bsl::safe_uintmax const &last_index) const noexcept + // { + // bsl::print() << bsl::rst; + + // if (index != last_index) { + // bsl::print() << "├── "; + // } + // else { + // bsl::print() << "└── "; + // } + + // bsl::print() << "[" << bsl::ylw << bsl::fmt{"#05x", index} << bsl::rst << "] "; + // } + + // /// + // /// @brief Given whether or not the page table + // /// entry is the last entry in the table, this function will + // /// either output whtspace, or a | and shitespace. + // /// + // /// + // /// @param is_last_index true if the entry being outputted is the + // /// last index in the table. + // /// + // constexpr void + // output_spacing(bool const is_last_index) const noexcept + // { + // bsl::print() << bsl::rst; + + // if (!is_last_index) { + // bsl::print() << "│ "; + // } + // else { + // bsl::print() << " "; + // } + // } + + // /// + // /// @brief Given a page table entry, this + // /// function outputs the flags associated with the entry + // /// + // /// + // /// @tparam ENTRY_CONCEPT the type of page table entry to output + // /// @param entry the page table entry to output + // /// + // template + // constexpr void + // output_entry_and_flags(ENTRY_CONCEPT const *const entry) const noexcept + // { + // bool add_comma{}; + + // bsl::print() << bsl::hex( + // *static_cast(static_cast(entry))); + // bsl::print() << bsl::rst << " ("; + + // if (bsl::ZERO_UMAX != entry->rw) { + // bsl::print() << bsl::grn << 'W'; + // add_comma = true; + // } + // else { + // bsl::touch(); + // } + + // if (bsl::ZERO_UMAX != entry->us) { + // if (add_comma) { + // bsl::print() << bsl::rst << ", "; + // } + // else { + // bsl::touch(); + // } + + // bsl::print() << bsl::grn << 'U'; + // add_comma = true; + // } + // else { + // bsl::touch(); + // } + + // if (bsl::ZERO_UMAX != entry->nx) { + // if (add_comma) { + // bsl::print() << bsl::rst << ", "; + // } + // else { + // bsl::touch(); + // } + + // bsl::print() << bsl::grn << "NX"; + // add_comma = true; + // } + // else { + // bsl::touch(); + // } + + // if constexpr (bsl::is_same::value) { + // if (bsl::ZERO_UMAX != entry->alias) { + // if (add_comma) { + // bsl::print() << bsl::rst << ", "; + // } + // else { + // bsl::touch(); + // } + + // bsl::print() << bsl::grn << "alias"; + // add_comma = true; + // } + // else { + // bsl::touch(); + // } + // } + + // if constexpr (bsl::is_same::value) { + // if (add_comma) { + // bsl::print() << bsl::rst << ", "; + // } + // else { + // bsl::touch(); + // } + + // switch (entry->auto_release) { + // case MAP_PAGE_AUTO_RELEASE_ALLOC_PAGE.get(): { + // bsl::print() << bsl::grn << "auto_release_alloc_page"; + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_ALLOC_HUGE.get(): { + // bsl::print() << bsl::grn << "auto_release_alloc_huge"; + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_ALLOC_HEAP.get(): { + // bsl::print() << bsl::grn << "auto_release_alloc_heap"; + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_STACK.get(): { + // bsl::print() << bsl::grn << "auto_release_stack"; + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_TLS.get(): { + // bsl::print() << bsl::grn << "auto_release_tls"; + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_ELF.get(): { + // bsl::print() << bsl::grn << "auto_release_elf"; + // break; + // } + + // default: { + // bsl::print() << bsl::grn << "manual"; + // break; + // } + // } + + // add_comma = true; + // } + + // bsl::print() << bsl::rst << ')'; + // bsl::print() << bsl::rst << bsl::endl; + // } + + // /// + // /// @brief Returns the page-map level-4 (PML4T) offset given a + // /// virtual address. + // /// + // /// + // /// @param virt the virtual address to get the PML4T offset from. + // /// @return the PML4T offset from the virtual address + // /// + // [[nodiscard]] static constexpr auto + // l0to(bsl::safe_uintmax const &virt) noexcept -> bsl::safe_uintmax + // { + // constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + // constexpr bsl::safe_uintmax shift{bsl::to_umax(39)}; + // return (virt >> shift) & mask; + // } + + // /// + // /// @brief Dumps the provided l0t_t + // /// + // /// + // /// @param l0t the l0t_t to dump + // /// + // constexpr void + // dump_l0t(l0t_t const *const l0t) const noexcept + // { + // bsl::safe_uintmax const last_index{this->get_last_index(l0t)}; + + // bsl::print() << bsl::blu << bsl::hex(m_l0t_phys); + // bsl::print() << bsl::rst << bsl::endl; + + // for (auto const elem : l0t->entries) { + // if (bsl::ZERO_UMAX == elem.data->p) { + // continue; + // } + + // this->output_decoration_and_index(elem.index, last_index); + + // if (bsl::ZERO_UMAX != elem.data->us) { + // bsl::print() << bsl::blu; + // this->output_entry_and_flags(elem.data); + // } + // else { + // bsl::print() << bsl::blk; + // this->output_entry_and_flags(elem.data); + // } + + // if (bsl::ZERO_UMAX != elem.data->us) { + // this->dump_l1t(this->get_l1t(elem.data), elem.index == last_index); + // } + // else { + // bsl::touch(); + // } + // } + // } + + // /// + // /// @brief Adds a l1t_t to the provided l0te_t. + // /// + // /// + // /// @param tls the current TLS block + // /// @param l0te the l0te_t to add a l1t_t too + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// and friends otherwise + // /// + // [[nodiscard]] constexpr auto + // add_l1t(tls_t &tls, loader::l0te_t *const l0te) noexcept -> bsl::errc_type + // { + // auto const *const table{m_page_pool->allocate(tls, ALLOCATE_TAG_PDPTS)}; + // if (bsl::unlikely(nullptr == table)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // auto const table_phys{m_page_pool->virt_to_phys(table)}; + // if (bsl::unlikely_assert(!table_phys)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // l0te->phys = (table_phys >> HYPERVISOR_PAGE_SHIFT).get(); + // l0te->p = bsl::ONE_UMAX.get(); + // l0te->rw = bsl::ONE_UMAX.get(); + // l0te->us = bsl::ONE_UMAX.get(); + + // return bsl::errc_success; + // } + + // /// + // /// @brief Adds a l1t_t to the provided l0te_t. + // /// + // /// + // /// @param tls the current TLS block + // /// @param l0te the l0te_t to add a l1t_t too + // /// + // constexpr void + // remove_l1t(tls_t &tls, loader::l0te_t *const l0te) noexcept + // { + // for (auto const elem : get_l1t(l0te)->entries) { + // if (elem.data->p != bsl::ZERO_UMAX) { + // this->remove_l2t(tls, elem.data); + // } + // else { + // bsl::touch(); + // } + // } + + // m_page_pool->deallocate(tls, get_l1t(l0te), ALLOCATE_TAG_PDPTS); + // } + + // /// + // /// @brief Returns the l1t_t associated with the provided + // /// l0te_t. + // /// + // /// + // /// @param l0te the l0te_t to get the l1t_t from + // /// @return A pointer to the requested l1t_t + // /// + // [[nodiscard]] constexpr auto + // get_l1t(loader::l0te_t *const l0te) noexcept -> l1t_t * + // { + // bsl::safe_uintmax entry_phys{l0te->phys}; + // entry_phys <<= HYPERVISOR_PAGE_SHIFT; + + // return m_page_pool->template phys_to_virt(entry_phys); + // } + + // /// + // /// @brief Returns the l1t_t associated with the provided + // /// l0te_t. + // /// + // /// + // /// @param l0te the l0te_t to get the l1t_t from + // /// @return A pointer to the requested l1t_t + // /// + // [[nodiscard]] constexpr auto + // get_l1t(loader::l0te_t const *const l0te) const noexcept -> l1t_t const * + // { + // bsl::safe_uintmax entry_phys{l0te->phys}; + // entry_phys <<= HYPERVISOR_PAGE_SHIFT; + + // return m_page_pool->template phys_to_virt(entry_phys); + // } + + // /// + // /// @brief Returns the page-directory-pointer table (PDPT) offset + // /// given a virtual address. + // /// + // /// + // /// @param virt the virtual address to get the PDPT offset from. + // /// @return the PDPT offset from the virtual address + // /// + // [[nodiscard]] static constexpr auto + // l1to(bsl::safe_uintmax const &virt) noexcept -> bsl::safe_uintmax + // { + // constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + // constexpr bsl::safe_uintmax shift{bsl::to_umax(30)}; + // return (virt >> shift) & mask; + // } + + // /// + // /// @brief Dumps the provided l1t_t + // /// + // /// + // /// @param l1t the l1t_t to dump + // /// @param is_l0te_last_index true if the parent l0te was the + // /// last l0te in the table + // /// + // constexpr void + // dump_l1t(l1t_t const *const l1t, bool is_l0te_last_index) const noexcept + // { + // bsl::safe_uintmax const last_index{this->get_last_index(l1t)}; + + // for (auto const elem : l1t->entries) { + // if (bsl::ZERO_UMAX == elem.data->p) { + // continue; + // } + + // this->output_spacing(is_l0te_last_index); + // this->output_decoration_and_index(elem.index, last_index); + + // bsl::print() << bsl::blu; + // this->output_entry_and_flags(elem.data); + + // this->dump_l2t( + // this->get_l2t(elem.data), is_l0te_last_index, elem.index == last_index); + // } + // } + + // /// + // /// @brief Adds a l2t_t to the provided l1te_t. + // /// + // /// + // /// @param tls the current TLS block + // /// @param l1te the l1te_t to add a l2t_t too + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// and friends otherwise + // /// + // [[nodiscard]] constexpr auto + // add_l2t(tls_t &tls, loader::l1te_t *const l1te) noexcept -> bsl::errc_type + // { + // auto const *const table{m_page_pool->allocate(tls, ALLOCATE_TAG_PDTS)}; + // if (bsl::unlikely(nullptr == table)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // auto const table_phys{m_page_pool->virt_to_phys(table)}; + // if (bsl::unlikely_assert(!table_phys)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // l1te->phys = (table_phys >> HYPERVISOR_PAGE_SHIFT).get(); + // l1te->p = bsl::ONE_UMAX.get(); + // l1te->rw = bsl::ONE_UMAX.get(); + // l1te->us = bsl::ONE_UMAX.get(); + + // return bsl::errc_success; + // } + + // /// + // /// @brief Adds a l2t_t to the provided l1te_t. + // /// + // /// + // /// @param tls the current TLS block + // /// @param l1te the l1te_t to add a l2t_t too + // /// + // constexpr void + // remove_l2t(tls_t &tls, loader::l1te_t *const l1te) noexcept + // { + // for (auto const elem : get_l2t(l1te)->entries) { + // if (elem.data->p != bsl::ZERO_UMAX) { + // this->remove_l3t(tls, elem.data); + // } + // else { + // bsl::touch(); + // } + // } + + // m_page_pool->deallocate(tls, get_l2t(l1te), ALLOCATE_TAG_PDTS); + // } + + // /// + // /// @brief Returns the l2t_t associated with the provided + // /// l1te_t. + // /// + // /// + // /// @param l1te the l1te_t to get the l2t_t from + // /// @return A pointer to the requested l2t_t + // /// + // [[nodiscard]] constexpr auto + // get_l2t(loader::l1te_t *const l1te) noexcept -> l2t_t * + // { + // bsl::safe_uintmax entry_phys{l1te->phys}; + // entry_phys <<= HYPERVISOR_PAGE_SHIFT; + + // return m_page_pool->template phys_to_virt(entry_phys); + // } + + // /// + // /// @brief Returns the l2t_t associated with the provided + // /// l1te_t. + // /// + // /// + // /// @param l1te the l1te_t to get the l2t_t from + // /// @return A pointer to the requested l2t_t + // /// + // [[nodiscard]] constexpr auto + // get_l2t(loader::l1te_t const *const l1te) const noexcept -> l2t_t const * + // { + // bsl::safe_uintmax entry_phys{l1te->phys}; + // entry_phys <<= HYPERVISOR_PAGE_SHIFT; + + // return m_page_pool->template phys_to_virt(entry_phys); + // } + + // /// + // /// @brief Returns the page-directory table (PDT) offset given a + // /// virtual address. + // /// + // /// + // /// @param virt the virtual address to get the PDT offset from. + // /// @return the PDT offset from the virtual address + // /// + // [[nodiscard]] static constexpr auto + // l2to(bsl::safe_uintmax const &virt) noexcept -> bsl::safe_uintmax + // { + // constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + // constexpr bsl::safe_uintmax shift{bsl::to_umax(21)}; + // return (virt >> shift) & mask; + // } + + // /// + // /// @brief Dumps the provided l2t_t + // /// + // /// + // /// @param l2t the l2t_t to dump + // /// @param is_l0te_last_index true if the parent l0te was the + // /// last l0te in the table + // /// @param is_l1te_last_index true if the parent l1te was the + // /// last l1te in the table + // /// + // constexpr void + // dump_l2t(l2t_t const *const l2t, bool is_l0te_last_index, bool is_l1te_last_index) + // const noexcept + // { + // bsl::safe_uintmax const last_index{this->get_last_index(l2t)}; + + // for (auto const elem : l2t->entries) { + // if (bsl::ZERO_UMAX == elem.data->p) { + // continue; + // } + + // this->output_spacing(is_l0te_last_index); + // this->output_spacing(is_l1te_last_index); + // this->output_decoration_and_index(elem.index, last_index); + + // bsl::print() << bsl::blu; + // this->output_entry_and_flags(elem.data); + + // this->dump_l3t( + // this->get_l3t(elem.data), + // is_l0te_last_index, + // is_l1te_last_index, + // elem.index == last_index); + // } + // } + + // /// + // /// @brief Adds a l3t_t to the provided l2te_t. + // /// + // /// + // /// @param tls the current TLS block + // /// @param l2te the l2te_t to add a l3t_t too + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// and friends otherwise + // /// + // [[nodiscard]] constexpr auto + // add_l3t(tls_t &tls, loader::l2te_t *const l2te) noexcept -> bsl::errc_type + // { + // auto const *const table{m_page_pool->allocate(tls, ALLOCATE_TAG_PTS)}; + // if (bsl::unlikely(nullptr == table)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // auto const table_phys{m_page_pool->virt_to_phys(table)}; + // if (bsl::unlikely_assert(!table_phys)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // l2te->phys = (table_phys >> HYPERVISOR_PAGE_SHIFT).get(); + // l2te->p = bsl::ONE_UMAX.get(); + // l2te->rw = bsl::ONE_UMAX.get(); + // l2te->us = bsl::ONE_UMAX.get(); + + // return bsl::errc_success; + // } + + // /// + // /// @brief Adds a l3t_t to the provided l2te_t. + // /// + // /// + // /// @param tls the current TLS block + // /// @param l2te the l2te_t to add a l3t_t too + // /// + // constexpr void + // remove_l3t(tls_t &tls, loader::l2te_t *const l2te) noexcept + // { + // for (auto const elem : get_l3t(l2te)->entries) { + // if (elem.data->p == bsl::ZERO_UMAX) { + // continue; + // } + + // switch (elem.data->auto_release) { + // case MAP_PAGE_NO_AUTO_RELEASE.get(): { + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_ALLOC_PAGE.get(): { + // m_page_pool->deallocate( + // tls, + // this->l3te_from_page_pool_to_virt(elem.data), + // ALLOCATE_TAG_BF_MEM_OP_ALLOC_PAGE); + + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_ALLOC_HUGE.get(): { + // m_huge_pool->deallocate(tls, this->l3te_from_huge_pool_to_virt(elem.data)); + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_ALLOC_HEAP.get(): { + // m_page_pool->deallocate( + // tls, + // this->l3te_from_page_pool_to_virt(elem.data), + // ALLOCATE_TAG_BF_MEM_OP_ALLOC_HEAP); + + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_STACK.get(): { + // m_page_pool->deallocate( + // tls, + // this->l3te_from_page_pool_to_virt(elem.data), + // ALLOCATE_TAG_EXT_STACK); + + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_TLS.get(): { + // m_page_pool->deallocate( + // tls, this->l3te_from_page_pool_to_virt(elem.data), ALLOCATE_TAG_EXT_TLS); + + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_ELF.get(): { + // m_page_pool->deallocate( + // tls, this->l3te_from_page_pool_to_virt(elem.data), ALLOCATE_TAG_EXT_ELF); + + // break; + // } + + // default: { + // bsl::error() << "uknown tag\n" << bsl::here(); + // break; + // } + // } + // } + + // m_page_pool->deallocate(tls, get_l3t(l2te), ALLOCATE_TAG_PTS); + // } + + // /// + // /// @brief Returns the l3t_t associated with the provided + // /// l2te_t. + // /// + // /// + // /// @param l2te the l2te_t to get the l3t_t from + // /// @return A pointer to the requested l3t_t + // /// + // [[nodiscard]] constexpr auto + // get_l3t(loader::l2te_t *const l2te) noexcept -> l3t_t * + // { + // bsl::safe_uintmax entry_phys{l2te->phys}; + // entry_phys <<= HYPERVISOR_PAGE_SHIFT; + + // return m_page_pool->template phys_to_virt(entry_phys); + // } + + // /// + // /// @brief Returns the l3t_t associated with the provided + // /// l2te_t. + // /// + // /// + // /// @param l2te the l2te_t to get the l3t_t from + // /// @return A pointer to the requested l3t_t + // /// + // [[nodiscard]] constexpr auto + // get_l3t(loader::l2te_t const *const l2te) const noexcept -> l3t_t const * + // { + // bsl::safe_uintmax entry_phys{l2te->phys}; + // entry_phys <<= HYPERVISOR_PAGE_SHIFT; + + // return m_page_pool->template phys_to_virt(entry_phys); + // } + + // /// + // /// @brief Returns the page-table (PT) offset given a + // /// virtual address. + // /// + // /// + // /// @param virt the virtual address to get the PT offset from. + // /// @return the PT offset from the virtual address + // /// + // [[nodiscard]] static constexpr auto + // l3to(bsl::safe_uintmax const &virt) noexcept -> bsl::safe_uintmax + // { + // constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; + // constexpr bsl::safe_uintmax shift{bsl::to_umax(12)}; + // return (virt >> shift) & mask; + // } + + // /// + // /// @brief Dumps the provided l3t_t + // /// + // /// + // /// @param l3t the l3t_t to dump + // /// @param is_l0te_last_index true if the parent l0te was the + // /// last l0te in the table + // /// @param is_l1te_last_index true if the parent l1te was the + // /// last l1te in the table + // /// @param is_l2te_last_index true if the parent l2te was the + // /// last l2te in the table + // /// + // constexpr void + // dump_l3t( + // l3t_t const *const l3t, + // bool is_l0te_last_index, + // bool is_l1te_last_index, + // bool is_l2te_last_index) const noexcept + // { + // bsl::safe_uintmax const last_index{this->get_last_index(l3t)}; + + // for (auto const elem : l3t->entries) { + // if (bsl::ZERO_UMAX == elem.data->p) { + // continue; + // } + + // this->output_spacing(is_l0te_last_index); + // this->output_spacing(is_l1te_last_index); + // this->output_spacing(is_l2te_last_index); + // this->output_decoration_and_index(elem.index, last_index); + + // bsl::print() << bsl::rst; + // this->output_entry_and_flags(elem.data); + // } + // } + + // /// + // /// @brief Returns the virtual address associated with a specific + // /// l3te that was allocated using the page pool. + // /// + // /// + // /// @param l3te the l3te_t to convert + // /// @return Returns the virtual address associated with a specific + // /// l3te that was allocated using the page pool. + // /// + // [[nodiscard]] constexpr auto + // l3te_from_page_pool_to_virt(loader::l3te_t *const l3te) noexcept -> void * + // { + // bsl::safe_uintmax entry_phys{l3te->phys}; + // entry_phys <<= HYPERVISOR_PAGE_SHIFT; + + // return m_page_pool->phys_to_virt(entry_phys); + // } + + // /// + // /// @brief Returns the virtual address associated with a specific + // /// l3te that was allocated using the huge pool. + // /// + // /// + // /// @param l3te the l3te_t to convert + // /// @return Returns the virtual address associated with a specific + // /// l3te that was allocated using the huge pool. + // /// + // [[nodiscard]] constexpr auto + // l3te_from_huge_pool_to_virt(loader::l3te_t *const l3te) noexcept -> void * + // { + // bsl::safe_uintmax entry_phys{l3te->phys}; + // entry_phys <<= HYPERVISOR_PAGE_SHIFT; + + // return m_huge_pool->phys_to_virt(entry_phys); + // } + + /// + /// @brief Returns the page aligned version of the addr + /// + /// + /// @param addr the address to query + /// @return Returns the page aligned version of the addr + /// + [[nodiscard]] static constexpr auto + page_aligned(bsl::safe_uintmax const &addr) noexcept -> bsl::safe_uintmax + { + return (addr & ~(HYPERVISOR_PAGE_SIZE - bsl::ONE_UMAX)); + } + + /// + /// @brief Returns true if the provided address is page aligned + /// + /// + /// @param addr the address to query + /// @return Returns true if the provided address is page aligned + /// + [[nodiscard]] static constexpr auto + is_page_aligned(bsl::safe_uintmax const &addr) noexcept -> bool + { + return (addr & (HYPERVISOR_PAGE_SIZE - bsl::ONE_UMAX)) == bsl::ZERO_UMAX; + } + + /// + /// @brief Allocates a page from the provided page pool and maps it + /// into the root page table being managed by this class The page + /// is marked as "auto release", meaning when this root page table + /// is released, the pages allocated by this function will + /// automatically be deallocated and put back into the provided + /// page pool. + /// + /// + /// @param tls the current TLS block + /// @param page_virt the virtual address to map the allocated + /// page to + /// @param page_flags defines how memory should be mapped + /// @param auto_release defines what auto release tag to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate_page( + tls_t &tls, + bsl::safe_uintmax const &page_virt, + bsl::safe_uintmax const &page_flags, + bsl::safe_int32 const &auto_release) noexcept -> void * + { + // bsl::errc_type ret{}; + + void *page{}; + + bsl::discard(tls); + bsl::discard(page_virt); + bsl::discard(page_flags); + bsl::discard(auto_release); + // switch (auto_release.get()) { + // case MAP_PAGE_AUTO_RELEASE_STACK.get(): { + // page = m_page_pool->allocate(tls, ALLOCATE_TAG_EXT_STACK); + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_TLS.get(): { + // page = m_page_pool->allocate(tls, ALLOCATE_TAG_EXT_TLS); + // break; + // } + + // case MAP_PAGE_AUTO_RELEASE_ELF.get(): { + // page = m_page_pool->allocate(tls, ALLOCATE_TAG_EXT_ELF); + // break; + // } + + // default: { + // bsl::error() << "unknown tag\n" << bsl::here(); + // break; + // } + // } + + // if (bsl::unlikely(nullptr == page)) { + // bsl::print() << bsl::here(); + // return nullptr; + // } + + // auto const page_phys{m_page_pool->virt_to_phys(page)}; + // if (bsl::unlikely_assert(!page_phys)) { + // bsl::error() << "physical address is invalid " // -- + // << bsl::hex(page_phys) // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return nullptr; + // } + + // ret = this->map_page(tls, page_virt, page_phys, page_flags, auto_release); + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return nullptr; + // } + + return page; + } + + // /// + // /// @brief Releases the memory allocated for tables + // /// + // /// + // /// @param tls the current TLS block + // /// + // constexpr void + // release_tables(tls_t &tls) noexcept + // { + // if (bsl::unlikely(nullptr == m_l0t)) { + // return; + // } + + // if (bsl::unlikely(nullptr == m_page_pool)) { + // return; + // } + + // if (bsl::unlikely(nullptr == m_huge_pool)) { + // return; + // } + + // for (auto const elem : m_l0t->entries) { + // if (elem.data->p == bsl::ZERO_UMAX) { + // continue; + // } + + // if (elem.data->alias != bsl::ZERO_UMAX) { + // continue; + // } + + // this->remove_l1t(tls, elem.data); + // } + + // m_page_pool->deallocate(tls, m_l0t, ALLOCATE_TAG_PML4TS); + // m_l0t = {}; + // m_l0t_phys = bsl::safe_uintmax::failure(); + // } + + public: + /// + /// @brief Initializes this root_page_table_t + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param page_pool the page pool to use + /// @param huge_pool the huge pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + tls_t &tls, + intrinsic_t *const intrinsic, + page_pool_t *const page_pool, + huge_pool_t *const huge_pool) noexcept -> bsl::errc_type + { + bsl::print() << bsl::rst << "Hello from ARMv8 on a Raspberry Pi 4!!!\n"; + bsl::print() << bsl::endl; + + bsl::error() << "aarch64 support not complete" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(page_pool); + bsl::discard(huge_pool); + + // if (bsl::unlikely_assert(m_initialized)) { + // bsl::error() << "root_page_table_t already initialized\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // bsl::finally release_on_error{[this, &tls]() noexcept -> void { + // this->release(tls); + // }}; + + // m_intrinsic = intrinsic; + // if (bsl::unlikely_assert(nullptr == intrinsic)) { + // bsl::error() << "invalid intrinsic\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // m_page_pool = page_pool; + // if (bsl::unlikely_assert(nullptr == page_pool)) { + // bsl::error() << "invalid page_pool\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // m_huge_pool = huge_pool; + // if (bsl::unlikely_assert(nullptr == huge_pool)) { + // bsl::error() << "invalid huge_pool\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // m_l0t = m_page_pool->template allocate(tls, ALLOCATE_TAG_PML4TS); + // if (bsl::unlikely(nullptr == m_l0t)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // m_l0t_phys = m_page_pool->virt_to_phys(m_l0t); + // if (bsl::unlikely_assert(!m_l0t_phys)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // release_on_error.ignore(); + // m_initialized = true; + + // return bsl::errc_success; + } + + /// + /// @brief Releases all of the resources used by the RPT. + /// + /// + /// @param tls the current TLS block + /// + constexpr void + release(tls_t &tls) noexcept + { + lock_guard_t lock{tls, m_lock}; + + // this->release_tables(tls); + + m_huge_pool = {}; + m_page_pool = {}; + m_intrinsic = {}; + m_initialized = false; + } + + /// + /// @brief Returns true if this RPT is initialized. + /// + /// + /// @return Returns true if this RPT is initialized. + /// + [[nodiscard]] constexpr auto + is_initialized() const noexcept -> bool + { + return m_initialized; + } + + /// + /// @brief Sets the current root page table to this root page table. + /// + /// + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + activate() const noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_initialized)) { + bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + // m_intrinsic->set_cr3(m_l0t_phys); + return bsl::errc_success; + } + + /// + /// @brief Given a root page table, the l0te_t enties are aliased + /// into this page table, allowing software using this root page + /// table to access the memory mapped into the provided root page + /// table. The additions are aliases only, meaning when this root + /// page table loses scope, aliased entries added by this function + /// are not returned back to the page pool. + /// + /// + /// @param tls the current TLS block + /// @param rpt the root page table to add aliases to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + add_tables(tls_t &tls, void const *const rpt) noexcept -> bsl::errc_type + { + lock_guard_t lock{tls, m_lock}; + + if (bsl::unlikely_assert(!m_initialized)) { + bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + bsl::discard(rpt); + // auto const *const l0t{static_cast(rpt)}; + // if (bsl::unlikely_assert(nullptr == l0t)) { + // bsl::error() << "invalid rpt\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // for (auto const elem : l0t->entries) { + // if (elem.data->p != bsl::ZERO_UMAX) { + // auto *const pml4e_dst{m_l0t->entries.at_if(elem.index)}; + + // *pml4e_dst = *elem.data; + // pml4e_dst->alias = bsl::ONE_UMAX.get(); + // } + // else { + // bsl::touch(); + // } + // } + + return bsl::errc_success; + } + + /// + /// @brief Given a root page table, the l0te_t enties are aliased + /// into this page table, allowing software using this root page + /// table to access the memory mapped into the provided root page + /// table. The additions are aliases only, meaning when this root + /// page table loses scope, aliased entries added by this function + /// are not returned back to the page pool. + /// + /// + /// @param tls the current TLS block + /// @param rpt the root page table to add aliases to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + add_tables(tls_t &tls, root_page_table_t const &rpt) noexcept -> bsl::errc_type + { + return this->add_tables(tls, rpt.m_l0t); + } + + /// + /// @brief Maps a page into the root page table being managed + /// by this class. + /// + /// + /// @param tls the current TLS block + /// @param page_virt the virtual address to map the physical address + /// too. + /// @param page_phys the physical address to map. + /// @param page_flags defines how memory should be mapped + /// @param auto_release defines what auto release tag to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + map_page( + tls_t &tls, + bsl::safe_uintmax const &page_virt, + bsl::safe_uintmax const &page_phys, + bsl::safe_uintmax const &page_flags, + bsl::safe_int32 const &auto_release) noexcept -> bsl::errc_type + { + lock_guard_t lock{tls, m_lock}; + + if (bsl::unlikely_assert(!m_initialized)) { + bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(page_virt.is_zero())) { + bsl::error() << "virtual address is invalid " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(!this->is_page_aligned(page_virt))) { + bsl::error() << "virtual address is not page aligned " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(page_phys.is_zero())) { + bsl::error() << "physical address is invalid " // -- + << bsl::hex(page_phys) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(!this->is_page_aligned(page_phys))) { + bsl::error() << "physical address is not page aligned " // -- + << bsl::hex(page_phys) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(!page_flags)) { + bsl::error() << "invalid flags " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(!auto_release)) { + bsl::error() << "invalid auto release " // -- + << auto_release // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if ((page_flags & MAP_PAGE_WRITE).is_pos()) { + if ((page_flags & MAP_PAGE_EXECUTE).is_pos()) { + bsl::error() << "invalid page_flags " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + // auto *const l0te{m_l0t->entries.at_if(this->l0to(page_virt))}; + // if (l0te->p == bsl::ZERO_UMAX) { + // if (bsl::unlikely(!this->add_l1t(tls, l0te))) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // bsl::touch(); + // } + // else { + + // /// NOTE: + // /// - The loader doesn't map in the memory associated with + // /// the microkernel's page tables. This means this code + // /// cannot walk any pages mapped to the microkernel, it + // /// can only alias these pages. For this reason, mapping + // /// must always take place on userspace specific memory + // /// and the address spaces must be distinct. + // /// + + // if (l0te->us == bsl::ZERO_UMAX) { + // bsl::error() << "atteml3t to map the userspace address " // -- + // << bsl::hex(page_virt) // -- + // << " in an address range owned by the kernel failed" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // bsl::touch(); + // } + + // auto *const l1t{this->get_l1t(l0te)}; + // auto *const l1te{l1t->entries.at_if(this->l1to(page_virt))}; + // if (l1te->p == bsl::ZERO_UMAX) { + // if (bsl::unlikely(!this->add_l2t(tls, l1te))) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // bsl::touch(); + // } + // else { + // bsl::touch(); + // } + + // auto *const l2t{this->get_l2t(l1te)}; + // auto *const l2te{l2t->entries.at_if(this->l2to(page_virt))}; + // if (l2te->p == bsl::ZERO_UMAX) { + // if (bsl::unlikely(!this->add_l3t(tls, l2te))) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // bsl::touch(); + // } + // else { + // bsl::touch(); + // } + + // auto *const l3t{this->get_l3t(l2te)}; + // auto *const l3te{l3t->entries.at_if(this->l3to(page_virt))}; + // if (bsl::unlikely(l3te->p != bsl::ZERO_UMAX)) { + // bsl::error() << "virtual address " // -- + // << bsl::hex(page_virt) // -- + // << " already mapped" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_already_exists; + // } + + // l3te->phys = (page_phys >> HYPERVISOR_PAGE_SHIFT).get(); + // l3te->p = bsl::ONE_UMAX.get(); + // l3te->us = bsl::ONE_UMAX.get(); + // l3te->auto_release = auto_release.get(); + + // if (!(page_flags & MAP_PAGE_WRITE).is_zero()) { + // l3te->rw = bsl::ONE_UMAX.get(); + // } + // else { + // l3te->rw = bsl::ZERO_UMAX.get(); + // } + + // if (!(page_flags & MAP_PAGE_EXECUTE).is_zero()) { + // l3te->nx = bsl::ZERO_UMAX.get(); + // } + // else { + // l3te->nx = bsl::ONE_UMAX.get(); + // } + + return bsl::errc_success; + } + + /// + /// @brief Maps a page into the root page table being managed + /// by this class. This version allows for unaligned virtual and + /// physical addresses and will perform the alignment for you. + /// Note that you should only use this function if you actually + /// need unaligned support to ensure alignment mistakes are not + /// accidentally introduced. + /// + /// + /// @param tls the current TLS block + /// @param page_virt the virtual address to map the physical address + /// too. + /// @param page_phys the physical address to map. If the physical + /// address is set to 0, map_page will use the page pool to + /// determine the physical address. + /// @param page_flags defines how memory should be mapped + /// @param auto_release defines what auto release tag to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + map_page_unaligned( + tls_t &tls, + bsl::safe_uintmax const &page_virt, + bsl::safe_uintmax const &page_phys, + bsl::safe_uintmax const &page_flags, + bsl::safe_int32 const &auto_release) noexcept -> bsl::errc_type + { + return this->map_page( + tls, + this->page_aligned(page_virt), + this->page_aligned(page_phys), + page_flags, + auto_release); + } + + /// + /// @brief Allocates a page from the provided page pool and maps it + /// into the root page table being managed by this class The page + /// is marked as "auto release", meaning when this root page table + /// is released, the pages allocated by this function will + /// automatically be deallocated and put back into the provided + /// page pool. Note that this version maps the memory in as + /// read/write. + /// + /// + /// @param tls the current TLS block + /// @param page_virt the virtual address to map the allocated + /// page to + /// @param auto_release defines what auto release tag to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate_page_rw( + tls_t &tls, + bsl::safe_uintmax const &page_virt, + bsl::safe_int32 const &auto_release) noexcept -> void * + { + if (bsl::unlikely_assert(!m_initialized)) { + bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); + return nullptr; + } + + if (bsl::unlikely_assert(page_virt.is_zero())) { + bsl::error() << "virtual address is invalid " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return nullptr; + } + + if (bsl::unlikely_assert(!this->is_page_aligned(page_virt))) { + bsl::error() << "virtual address is not page aligned " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return nullptr; + } + + if (bsl::unlikely_assert(!auto_release)) { + bsl::error() << "invalid auto release " // -- + << auto_release // -- + << bsl::endl // -- + << bsl::here(); // -- + + return nullptr; + } + + return this->allocate_page( + tls, page_virt, MAP_PAGE_READ | MAP_PAGE_WRITE, auto_release); + } + + /// + /// @brief Allocates a page from the provided page pool and maps it + /// into the root page table being managed by this class The page + /// is marked as "auto release", meaning when this root page table + /// is released, the pages allocated by this function will + /// automatically be deallocated and put back into the provided + /// page pool. Note that this version maps the memory in as + /// read/execute. + /// + /// + /// @param tls the current TLS block + /// @param page_virt the virtual address to map the allocated + /// page to + /// @param auto_release defines what auto release tag to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate_page_rx( + tls_t &tls, + bsl::safe_uintmax const &page_virt, + bsl::safe_int32 const &auto_release) noexcept -> void * + { + if (bsl::unlikely_assert(!m_initialized)) { + bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); + return nullptr; + } + + if (bsl::unlikely_assert(page_virt.is_zero())) { + bsl::error() << "virtual address is invalid " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return nullptr; + } + + if (bsl::unlikely_assert(!this->is_page_aligned(page_virt))) { + bsl::error() << "virtual address is not page aligned " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return nullptr; + } + + if (bsl::unlikely_assert(!auto_release)) { + bsl::error() << "invalid auto release " // -- + << auto_release // -- + << bsl::endl // -- + << bsl::here(); // -- + + return nullptr; + } + + return this->allocate_page( + tls, page_virt, MAP_PAGE_READ | MAP_PAGE_EXECUTE, auto_release); + } + + /// + /// @brief Dumps the provided pml4_t + /// + constexpr void + dump() const noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + + if (bsl::unlikely_assert(!m_initialized)) { + bsl::print() << "[error]" << bsl::endl; + return; + } + + // this->dump_l0t(m_l0t); + bsl::touch(); + } + }; +} + +#endif diff --git a/kernel/src/arm/aarch64/serial_write_c.S b/kernel/src/arm/aarch64/serial_write_c.S new file mode 100644 index 00000000..c0c31c7e --- /dev/null +++ b/kernel/src/arm/aarch64/serial_write_c.S @@ -0,0 +1,51 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .global serial_write_c + .type serial_write_c, @function +serial_write_c: + stp x0, x1, [sp, #-0x10]! + +wait_for_ffio_empty: + movz x1, #HYPERVISOR_SERIAL_PORTL + movk x1, #HYPERVISOR_SERIAL_PORTH, LSL #16 + add x1, x1, #0x18 + ldr x1, [x1] + + and x1, x1, #0x20 + cbnz x1, wait_for_ffio_empty + + movz x1, #HYPERVISOR_SERIAL_PORTL + movk x1, #HYPERVISOR_SERIAL_PORTH, LSL #16 + str x0, [x1] + + ldp x0, x1, [sp], #0x10 + ret + + + .size serial_write_c, .-serial_write_c diff --git a/kernel/src/arm/aarch64/serial_write_hex.S b/kernel/src/arm/aarch64/serial_write_hex.S new file mode 100644 index 00000000..96c4ef0d --- /dev/null +++ b/kernel/src/arm/aarch64/serial_write_hex.S @@ -0,0 +1,118 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .global serial_write_hex + .type serial_write_hex, @function +serial_write_hex: + stp x29, x30, [sp, #-0x10]! + stp x19, x20, [sp, #-0x10]! + stp x0, x1, [sp, #-0x10]! + + mov x19, x0 + mov x20, #0xF + + mov x0, #0x30 + bl serial_write_c + + mov x0, #0x78 + bl serial_write_c + + and x0, x20, x19, LSR #60 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #56 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #52 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #48 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #44 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #40 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #36 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #32 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #28 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #24 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #20 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #16 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #12 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #8 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #4 + bl serial_write_hex_digit + + and x0, x20, x19 + bl serial_write_hex_digit + + ldp x0, x1, [sp], #0x10 + ldp x19, x20, [sp], #0x10 + ldp x29, x30, [sp], #0x10 + ret + +serial_write_hex_digit: + stp x29, x30, [sp, #-0x10]! + + cmp x0, #9 + bgt serial_write_hex_digit_a_to_f + + add x0, x0, #0x30 + bl serial_write_c + + ldp x29, x30, [sp], #0x10 + ret + +serial_write_hex_digit_a_to_f: + + add x0, x0, #0x37 + bl serial_write_c + + ldp x29, x30, [sp], #0x10 + ret + + .size serial_write_hex, .-serial_write_hex diff --git a/kernel/src/arm/aarch64/vmexit_log_t.hpp b/kernel/src/arm/aarch64/vmexit_log_t.hpp new file mode 100644 index 00000000..38fe69d3 --- /dev/null +++ b/kernel/src/arm/aarch64/vmexit_log_t.hpp @@ -0,0 +1,217 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_LOG_T_HPP +#define VMEXIT_LOG_T_HPP + +#include + +#include +#include +#include +#include +#include + +namespace mk +{ + /// @class mk::vmexit_log_t + /// + /// + /// @brief Stores a log of all VMExits that occur. Each PP has one log + /// that is shared between all of the VPSs so that you get a consistent + /// view of what actually happened during execution, which is more + /// important when implementing guest support as VPSs can swap between + /// execution on the same PP as the hypervisor is moving between VMs. + /// + class vmexit_log_t final + { + /// @brief stores the VMExit log + bsl::array, HYPERVISOR_MAX_PPS> m_vmexit_logs{}; + + /// + /// @brief Dumps the contents of the VMExit log for the requested PP + /// + /// + /// @param str the name of the field + /// @param val the value of the field + /// + constexpr void + dump_field(bsl::string_view const &str, bsl::safe_uintmax const &val) noexcept + { + if (val.is_zero()) { + bsl::print() << bsl::ylw << str << bsl::blk << bsl::hex(val); + } + else { + bsl::print() << bsl::ylw << str << bsl::rst << bsl::hex(val); + } + } + + public: + /// + /// @brief Adds a record in the VMExit log + /// + /// + /// @param ppid the id of the PP whose log should be added to + /// @param rec the record to add to the log + /// + constexpr void + add(bsl::safe_uint16 const &ppid, vmexit_log_record_t const &rec) noexcept + { + if constexpr (BSL_DEBUG_LEVEL < bsl::VV) { + return; + } + + auto *const pp_log{m_vmexit_logs.at_if(bsl::to_umax(ppid))}; + if (bsl::unlikely(nullptr == pp_log)) { + return; + } + + *pp_log->log.at_if(pp_log->crsr) = rec; + + ++pp_log->crsr; + if (pp_log->crsr < pp_log->log.size()) { + bsl::touch(); + } + else { + pp_log->crsr = {}; + } + } + + /// + /// @brief Dumps the contents of the VMExit log for the requested PP + /// + /// + /// @param ppid the ID of the PP whose log should be dumped + /// + constexpr void + dump(bsl::safe_uint16 const &ppid) noexcept + { + if constexpr (BSL_DEBUG_LEVEL < bsl::VV) { + return; + } + + auto *const pp_log{m_vmexit_logs.at_if(bsl::to_umax(ppid))}; + if (bsl::unlikely(nullptr == pp_log)) { + bsl::error() << "invalid ppid " // -- + << bsl::hex(ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return; + } + + bsl::print() << bsl::mag << "vmexit log for pp ["; + bsl::print() << bsl::rst << bsl::hex(ppid); + bsl::print() << bsl::mag << "]: "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+---------------------------------"; + bsl::print() << bsl::ylw << "----------------------------------"; + bsl::print() << bsl::ylw << "----------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + // for (bsl::safe_uintmax i{}; i < pp_log->log.size(); ++i) { + // auto const rec{pp_log->log.at_if(pp_log->crsr)}; + + // if (rec->rip.is_pos()) { + // bsl::print() << bsl::ylw << "| "; + // bsl::print() << bsl::blu << "VM:"; + // bsl::print() << bsl::cyn << bsl::fmt{"04x", rec->vmid}; + // bsl::print() << bsl::rst << ", "; + // bsl::print() << bsl::blu << "VP:"; + // bsl::print() << bsl::cyn << bsl::fmt{"04x", rec->vpid}; + // bsl::print() << bsl::rst << ", "; + // bsl::print() << bsl::blu << "VPS:"; + // bsl::print() << bsl::cyn << bsl::fmt{"04x", rec->vpsid}; + // bsl::print() << bsl::rst << ", "; + // bsl::print() << bsl::blu << "REASON:"; + // bsl::print() << bsl::cyn << bsl::fmt{">2d", rec->exit_reason}; + // bsl::print() << bsl::rst << " "; + // bsl::print() << bsl::ylw << " |"; + // bsl::print() << bsl::rst << bsl::endl; + + // bsl::print() << bsl::ylw << "| "; + // bsl::print() << bsl::rst << " -"; + // this->dump_field(" rip: ", rec->rip); + // this->dump_field(" ei1: ", rec->ei1); + // this->dump_field(" ei2: ", rec->ei2); + // this->dump_field(" ei3: ", rec->ei3); + // bsl::print() << bsl::ylw << " |"; + // bsl::print() << bsl::rst << bsl::endl; + + // bsl::print() << bsl::ylw << "| "; + // bsl::print() << bsl::rst << " -"; + // this->dump_field(" rax: ", rec->rax); + // this->dump_field(" rbx: ", rec->rbx); + // this->dump_field(" rcx: ", rec->rcx); + // this->dump_field(" rdx: ", rec->rdx); + // bsl::print() << bsl::ylw << " |"; + // bsl::print() << bsl::rst << bsl::endl; + + // bsl::print() << bsl::ylw << "| "; + // bsl::print() << bsl::rst << " -"; + // this->dump_field(" rbp: ", rec->rbp); + // this->dump_field(" rsi: ", rec->rsi); + // this->dump_field(" rdi: ", rec->rdi); + // this->dump_field(" r08: ", rec->r8); + // bsl::print() << bsl::ylw << " |"; + // bsl::print() << bsl::rst << bsl::endl; + + // bsl::print() << bsl::ylw << "| "; + // bsl::print() << bsl::rst << " -"; + // this->dump_field(" r09: ", rec->r9); + // this->dump_field(" r10: ", rec->r10); + // this->dump_field(" r11: ", rec->r11); + // this->dump_field(" r12: ", rec->r12); + // bsl::print() << bsl::ylw << " |"; + // bsl::print() << bsl::rst << bsl::endl; + + // bsl::print() << bsl::ylw << "| "; + // bsl::print() << bsl::rst << " -"; + // this->dump_field(" r13: ", rec->r13); + // this->dump_field(" r14: ", rec->r14); + // this->dump_field(" r15: ", rec->r15); + // this->dump_field(" rsp: ", rec->rsp); + // bsl::print() << bsl::ylw << " |"; + // bsl::print() << bsl::rst << bsl::endl; + + // bsl::print() << bsl::ylw << "+---------------------------------"; + // bsl::print() << bsl::ylw << "----------------------------------"; + // bsl::print() << bsl::ylw << "----------------------------------+"; + // bsl::print() << bsl::rst << bsl::endl; + // } + + // ++pp_log->crsr; + // if (pp_log->crsr < pp_log->log.size()) { + // bsl::touch(); + // } + // else { + // pp_log->crsr = {}; + // } + // } + } + }; +} + +#endif diff --git a/kernel/src/arm/aarch64/vmexit_loop_entry.S b/kernel/src/arm/aarch64/vmexit_loop_entry.S new file mode 100644 index 00000000..0797ae4a --- /dev/null +++ b/kernel/src/arm/aarch64/vmexit_loop_entry.S @@ -0,0 +1,33 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl vmexit_loop_entry + .type vmexit_loop_entry, @function +vmexit_loop_entry: + + .size vmexit_loop_entry, .-vmexit_loop_entry diff --git a/kernel/src/arm/aarch64/vps_t.hpp b/kernel/src/arm/aarch64/vps_t.hpp new file mode 100644 index 00000000..78b9712e --- /dev/null +++ b/kernel/src/arm/aarch64/vps_t.hpp @@ -0,0 +1,1714 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VPS_T_HPP +#define VPS_T_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mk +{ + /// @class mk::vps_t + /// + /// + /// @brief Defines the microkernel's notion of a VPS. + /// + class vps_t final + { + /// @brief stores the ID associated with this vp_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + /// @brief stores whether or not this vp_t is allocated. + allocated_status_t m_allocated{allocated_status_t::deallocated}; + /// @brief stores the ID of the VP this vps_t is assigned to + bsl::safe_uint16 m_assigned_vpid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vp_t is assigned to + bsl::safe_uint16 m_assigned_ppid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vp_t is active on + bsl::safe_uint16 m_active_ppid{bsl::safe_uint16::failure()}; + + /// @brief stores the general purpose registers + general_purpose_regs_t m_gprs{}; + + /// + /// @brief Dumps the contents of a field + /// + /// + /// @tparam T the type of field to dump + /// @param str the name of the field + /// @param val the field to dump + /// + template + constexpr void + dump_field(bsl::string_view const &str, bsl::safe_integral const &val) const noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + + auto const *rowcolor{bsl::rst}; + + if (val.is_zero()) { + rowcolor = bsl::blk; + } + else { + bsl::touch(); + } + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<30s", str}; + bsl::print() << bsl::ylw << "| "; + + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << " " << bsl::hex(val) << " "; + } + + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << " " << bsl::hex(val) << " "; + } + + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << " " << bsl::hex(val) << " "; + } + + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << bsl::hex(val) << ' '; + } + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + } + + public: + /// + /// @brief Initializes this vps_t + /// + /// + /// @param i the ID for this vps_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize(bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(m_id)) { + bsl::error() << "vps_t already initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(!i)) { + bsl::error() << "invalid id\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == i)) { + bsl::error() << "id " // -- + << bsl::hex(i) // -- + << " is invalid and cannot be used for initialization" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + m_id = i; + return bsl::errc_success; + } + + /// + /// @brief Release the vp_t. Note that if this function fails, + /// the microkernel is left in a corrupt state and all use of the + /// vp_t after calling this function will results in UB. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + release(tls_t &tls, page_pool_t &page_pool) noexcept -> bsl::errc_type + { + bsl::discard(page_pool); + + if (this->is_zombie()) { + return bsl::errc_success; + } + + tls.state_reversal_required = true; + bsl::finally zombify_on_error{[this]() noexcept -> void { + this->zombify(); + }}; + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is active on pp " // -- + << bsl::hex(m_active_ppid) // -- + << " and therefore vp " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + m_gprs = {}; + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vpid = syscall::BF_INVALID_ID; + m_allocated = allocated_status_t::deallocated; + m_id = bsl::safe_uint16::failure(); + + zombify_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Returns the ID of this vps_t + /// + /// + /// @return Returns the ID of this vps_t + /// + [[nodiscard]] constexpr auto + id() const noexcept -> bsl::safe_uint16 const & + { + return m_id; + } + + /// + /// @brief Allocates this vps_t + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param page_pool the page pool to use + /// @param vp_pool the VP pool to use + /// @param vpid The ID of the VP to assign the newly created VP to + /// @param ppid The ID of the PP to assign the newly created VP to + /// @return Returns ID of the newly allocated vps + /// + [[nodiscard]] constexpr auto + allocate( + tls_t &tls, + intrinsic_t &intrinsic, + page_pool_t &page_pool, + vp_pool_t &vp_pool, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::safe_uint16 + { + bsl::discard(intrinsic); + bsl::discard(page_pool); + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(syscall::BF_INVALID_ID == vpid)) { + bsl::error() << "vp " // -- + << bsl::hex(vpid) // -- + << " is invalid and a vps cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(vp_pool.is_zombie(tls, vpid))) { + bsl::error() << "vp " // -- + << bsl::hex(vpid) // -- + << " is a zombie and a vps cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(vp_pool.is_deallocated(tls, vpid))) { + bsl::error() << "vp " // -- + << bsl::hex(vpid) // -- + << " has not been created and a vps cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(syscall::BF_INVALID_ID == ppid)) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is invalid and a vps cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(!(ppid < tls.online_pps))) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is not less than the total number of online pps " // -- + << bsl::hex(tls.online_pps) // -- + << " and a vps cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::zombie)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is a zombie and cannot be allocated" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is already allocated and cannot be created" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + tls.state_reversal_required = true; + tls.log_vpsid = m_id.get(); + + m_assigned_vpid = vpid; + m_assigned_ppid = ppid; + m_allocated = allocated_status_t::allocated; + + return m_id; + } + + /// + /// @brief Deallocates this vps_t + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + deallocate(tls_t &tls, page_pool_t &page_pool) noexcept -> bsl::errc_type + { + bsl::discard(page_pool); + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated == allocated_status_t::zombie)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is a zombie and cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is already deallocated and cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + tls.state_reversal_required = true; + bsl::finally zombify_on_error{[this]() noexcept -> void { + this->zombify(); + }}; + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is active on pp " // -- + << bsl::hex(m_active_ppid) // -- + << " and therefore vps " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + m_gprs = {}; + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vpid = syscall::BF_INVALID_ID; + m_allocated = allocated_status_t::deallocated; + + zombify_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Sets this vps_t's status as zombified, meaning it is no + /// longer usable. + /// + constexpr void + zombify() noexcept + { + if (bsl::unlikely_assert(!m_id)) { + return; + } + + if (m_allocated == allocated_status_t::zombie) { + return; + } + + bsl::alert() << "vps " // -- + << bsl::hex(m_id) // -- + << " has been zombified" // -- + << bsl::endl; // -- + + m_allocated = allocated_status_t::zombie; + } + + /// + /// @brief Returns true if this vps_t is deallocated, false otherwise + /// + /// + /// @return Returns true if this vps_t is deallocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_deallocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::deallocated; + } + + /// + /// @brief Returns true if this vps_t is allocated, false otherwise + /// + /// + /// @return Returns true if this vps_t is allocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_allocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::allocated; + } + + /// + /// @brief Returns true if this vps_t is a zombie, false otherwise + /// + /// + /// @return Returns true if this vps_t is a zombie, false otherwise + /// + [[nodiscard]] constexpr auto + is_zombie() const noexcept -> bool + { + return m_allocated == allocated_status_t::zombie; + } + + /// + /// @brief Sets this vps_t as active. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_active(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type + { + bsl::discard(intrinsic); + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.active_vpid != m_assigned_vpid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is assigned to vp " // -- + << bsl::hex(m_assigned_vpid) // -- + << " and cannot be activated with vp " // -- + << bsl::hex(tls.active_vpid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be activated on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID != tls.active_vpsid)) { + bsl::error() << "vps " // -- + << bsl::hex(tls.active_vpsid) // -- + << " is still active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is already the active vps on pp " // -- + << bsl::hex(m_active_ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + bsl::discard(intrinsic); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RAX, m_gprs.rax); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBX, m_gprs.rbx); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RCX, m_gprs.rcx); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDX, m_gprs.rdx); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBP, m_gprs.rbp); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RSI, m_gprs.rsi); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDI, m_gprs.rdi); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R8, m_gprs.r8); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R9, m_gprs.r9); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R10, m_gprs.r10); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R11, m_gprs.r11); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R12, m_gprs.r12); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R13, m_gprs.r13); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R14, m_gprs.r14); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R15, m_gprs.r15); + + tls.active_vpsid = m_id.get(); + m_active_ppid = tls.ppid; + + return bsl::errc_success; + } + + /// + /// @brief Sets this vps_t as inactive. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_inactive(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::deallocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == tls.active_vpsid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is not active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(tls.active_vpsid != m_id)) { + bsl::error() << "vps " // -- + << bsl::hex(tls.active_vpsid) // -- + << " is still active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(!m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is not active " // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(tls.ppid != m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is not active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + bsl::discard(intrinsic); + // m_gprs.rax = intrinsic.tls_reg(syscall::TLS_OFFSET_RAX).get(); + // m_gprs.rbx = intrinsic.tls_reg(syscall::TLS_OFFSET_RBX).get(); + // m_gprs.rcx = intrinsic.tls_reg(syscall::TLS_OFFSET_RCX).get(); + // m_gprs.rdx = intrinsic.tls_reg(syscall::TLS_OFFSET_RDX).get(); + // m_gprs.rbp = intrinsic.tls_reg(syscall::TLS_OFFSET_RBP).get(); + // m_gprs.rsi = intrinsic.tls_reg(syscall::TLS_OFFSET_RSI).get(); + // m_gprs.rdi = intrinsic.tls_reg(syscall::TLS_OFFSET_RDI).get(); + // m_gprs.r8 = intrinsic.tls_reg(syscall::TLS_OFFSET_R8).get(); + // m_gprs.r9 = intrinsic.tls_reg(syscall::TLS_OFFSET_R9).get(); + // m_gprs.r10 = intrinsic.tls_reg(syscall::TLS_OFFSET_R10).get(); + // m_gprs.r11 = intrinsic.tls_reg(syscall::TLS_OFFSET_R11).get(); + // m_gprs.r12 = intrinsic.tls_reg(syscall::TLS_OFFSET_R12).get(); + // m_gprs.r13 = intrinsic.tls_reg(syscall::TLS_OFFSET_R13).get(); + // m_gprs.r14 = intrinsic.tls_reg(syscall::TLS_OFFSET_R14).get(); + // m_gprs.r15 = intrinsic.tls_reg(syscall::TLS_OFFSET_R15).get(); + + tls.active_vpsid = syscall::BF_INVALID_ID.get(); + m_active_ppid = bsl::safe_uint16::failure(); + + return bsl::errc_success; + } + + /// + /// @brief Returns the ID of the PP that this vps_t is still active + /// on. If the vps_t is inactive, this function returns + /// bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @return Returns the ID of the PP that this vps_t is still active + /// on. If the vps_t is inactive, this function returns + /// bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_active(tls_t &tls) const noexcept -> bsl::safe_uint16 + { + bsl::discard(tls); + return m_active_ppid; + } + + /// + /// @brief Returns true if this vps_t is active on the current PP, + /// false otherwise + /// + /// + /// @param tls the current TLS block + /// @return Returns true if this vps_t is active on the current PP, + /// false otherwise + /// + [[nodiscard]] constexpr auto + is_active_on_current_pp(tls_t &tls) const noexcept -> bool + { + return tls.ppid == m_active_ppid; + } + + /// + /// @brief Migrates this vps_t from one PP to another. This should + /// only be called by the run ABI when the VP and VPS's assigned + /// ppids do not match. The VPS should always match the assigned + /// VP's ID. If it doesn't we need to migrate the VPS. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param ppid the ID of the PP to migrate to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + migrate(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uint16 const &ppid) noexcept + -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(ppid); + + // if (bsl::unlikely_assert(!m_id)) { + // bsl::error() << "vps_t not initialized\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(!m_allocated)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " was never allocated" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(!ppid)) { + // bsl::error() << "invalid ppid\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(syscall::BF_INVALID_ID == ppid)) { + // bsl::error() << "invalid ppid\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(!(ppid < tls.online_pps))) { + // bsl::error() << "invalid ppid\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(tls.ppid != ppid)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " is being migrated to pp " // -- + // << bsl::hex(ppid) // -- + // << " by pp " // -- + // << bsl::hex(tls.ppid) // -- + // << " which is not allowed " // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(ppid == m_assigned_ppid)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " is already assigned to a pp " // -- + // << bsl::hex(m_assigned_ppid) // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(syscall::BF_INVALID_ID != m_active_ppid)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " is still active on pp " // -- + // << bsl::hex(m_active_ppid) // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // m_guest_vmcb->vmcb_clean_bits = bsl::ZERO_U32.get(); + // m_assigned_ppid = ppid; + + return bsl::errc_success; + } + + /// + /// @brief Returns the ID of the VP this vp_t is assigned to + /// + /// + /// @return Returns the ID of the VP this vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_vp() const noexcept -> bsl::safe_uint16 + { + if (bsl::unlikely(syscall::BF_INVALID_ID == m_assigned_vpid)) { + return bsl::safe_uint16::failure(); + } + + return m_assigned_vpid; + } + + /// + /// @brief Returns the ID of the PP this vp_t is assigned to + /// + /// + /// @return Returns the ID of the PP this vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_pp() const noexcept -> bsl::safe_uint16 + { + if (bsl::unlikely(syscall::BF_INVALID_ID == m_assigned_ppid)) { + return bsl::safe_uint16::failure(); + } + + return m_assigned_ppid; + } + + /// + /// @brief Stores the provided state in the VPS. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param state the state to set the VPS to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + state_save_to_vps( + tls_t &tls, intrinsic_t &intrinsic, loader::state_save_t const &state) noexcept + -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + bsl::discard(intrinsic); + bsl::discard(state); + // if (tls.active_vpsid == m_id) { + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RAX, state.rax); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBX, state.rbx); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RCX, state.rcx); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDX, state.rdx); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBP, state.rbp); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RSI, state.rsi); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDI, state.rdi); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R8, state.r8); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R9, state.r9); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R10, state.r10); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R11, state.r11); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R12, state.r12); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R13, state.r13); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R14, state.r14); + // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R15, state.r15); + // } + // else { + // m_gprs.rax = state.rax; + // m_gprs.rbx = state.rbx; + // m_gprs.rcx = state.rcx; + // m_gprs.rdx = state.rdx; + // m_gprs.rbp = state.rbp; + // m_gprs.rsi = state.rsi; + // m_gprs.rdi = state.rdi; + // m_gprs.r8 = state.r8; + // m_gprs.r9 = state.r9; + // m_gprs.r10 = state.r10; + // m_gprs.r11 = state.r11; + // m_gprs.r12 = state.r12; + // m_gprs.r13 = state.r13; + // m_gprs.r14 = state.r14; + // m_gprs.r15 = state.r15; + // } + + return bsl::errc_success; + } + + /// + /// @brief Stores the VPS state in the provided state save. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param state the state save to store the VPS state to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + vps_to_state_save(tls_t &tls, intrinsic_t &intrinsic, loader::state_save_t &state) noexcept + -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + bsl::discard(intrinsic); + bsl::discard(state); + // if (tls.active_vpsid == m_id) { + // state.rax = intrinsic.tls_reg(syscall::TLS_OFFSET_RAX).get(); + // state.rbx = intrinsic.tls_reg(syscall::TLS_OFFSET_RBX).get(); + // state.rcx = intrinsic.tls_reg(syscall::TLS_OFFSET_RCX).get(); + // state.rdx = intrinsic.tls_reg(syscall::TLS_OFFSET_RDX).get(); + // state.rbp = intrinsic.tls_reg(syscall::TLS_OFFSET_RBP).get(); + // state.rsi = intrinsic.tls_reg(syscall::TLS_OFFSET_RSI).get(); + // state.rdi = intrinsic.tls_reg(syscall::TLS_OFFSET_RDI).get(); + // state.r8 = intrinsic.tls_reg(syscall::TLS_OFFSET_R8).get(); + // state.r9 = intrinsic.tls_reg(syscall::TLS_OFFSET_R9).get(); + // state.r10 = intrinsic.tls_reg(syscall::TLS_OFFSET_R10).get(); + // state.r11 = intrinsic.tls_reg(syscall::TLS_OFFSET_R11).get(); + // state.r12 = intrinsic.tls_reg(syscall::TLS_OFFSET_R12).get(); + // state.r13 = intrinsic.tls_reg(syscall::TLS_OFFSET_R13).get(); + // state.r14 = intrinsic.tls_reg(syscall::TLS_OFFSET_R14).get(); + // state.r15 = intrinsic.tls_reg(syscall::TLS_OFFSET_R15).get(); + // } + // else { + // state.rax = m_gprs.rax; + // state.rbx = m_gprs.rbx; + // state.rcx = m_gprs.rcx; + // state.rdx = m_gprs.rdx; + // state.rbp = m_gprs.rbp; + // state.rsi = m_gprs.rsi; + // state.rdi = m_gprs.rdi; + // state.r8 = m_gprs.r8; + // state.r9 = m_gprs.r9; + // state.r10 = m_gprs.r10; + // state.r11 = m_gprs.r11; + // state.r12 = m_gprs.r12; + // state.r13 = m_gprs.r13; + // state.r14 = m_gprs.r14; + // state.r15 = m_gprs.r15; + // } + + return bsl::errc_success; + } + + /// + /// @brief Reads a field from the VPS given the index of + /// the field to read. + /// + /// + /// @tparam FIELD_TYPE the type (i.e., size) of field to read + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param index the index of the field to read from the VPS + /// @return Returns the value of the requested field from the + /// VPS or bsl::safe_integral::failure() + /// on failure. + /// + template + [[nodiscard]] constexpr auto + read(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uintmax const &index) noexcept + -> bsl::safe_integral + { + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(index); + + bsl::error() << "read not supported on aarch64\n" << bsl::here(); + return bsl::safe_integral::failure(); + } + + /// + /// @brief Writes a field to the VPS given the index of + /// the field and the value to write. + /// + /// + /// @tparam FIELD_TYPE the type (i.e., size) of field to write + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param index the index of the field to write to the VPS + /// @param val the value to write to the VPS + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + template + [[nodiscard]] constexpr auto + write( + tls_t &tls, + intrinsic_t &intrinsic, + bsl::safe_uintmax const &index, + bsl::safe_integral const &val) noexcept -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(index); + bsl::discard(val); + + bsl::error() << "write not supported on aarch64\n" << bsl::here(); + return bsl::errc_failure; + } + + /// + /// @brief Reads a field from the VPS given a bf_reg_t + /// defining the field to read. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param reg a bf_reg_t defining the field to read from the VPS + /// @return Returns the value of the requested field from the + /// VPS or bsl::safe_uintmax::failure() on failure. + /// + [[nodiscard]] constexpr auto + read_reg(tls_t &tls, intrinsic_t &intrinsic, syscall::bf_reg_t const reg) noexcept + -> bsl::safe_uintmax + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::safe_uintmax::failure(); + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + bsl::discard(intrinsic); + bsl::discard(reg); + // switch (reg) { + // // case syscall::bf_reg_t::bf_reg_t_rax: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_RAX); + // // } + + // // return m_gprs.rax; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rbx: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_RBX); + // // } + + // // return m_gprs.rbx; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rcx: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_RCX); + // // } + + // // return m_gprs.rcx; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rdx: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_RDX); + // // } + + // // return m_gprs.rdx; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rbp: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_RBP); + // // } + + // // return m_gprs.rbp; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rsi: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_RSI); + // // } + + // // return m_gprs.rsi; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rdi: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_RDI); + // // } + + // // return m_gprs.rdi; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r8: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_R8); + // // } + + // // return m_gprs.r8; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r9: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_R9); + // // } + + // // return m_gprs.r9; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r10: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_R10); + // // } + + // // return m_gprs.r10; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r11: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_R11); + // // } + + // // return m_gprs.r11; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r12: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_R12); + // // } + + // // return m_gprs.r12; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r13: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_R13); + // // } + + // // return m_gprs.r13; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r14: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_R14); + // // } + + // // return m_gprs.r14; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r15: { + // // if (tls.active_vpsid == m_id) { + // // return intrinsic.tls_reg(syscall::TLS_OFFSET_R15); + // // } + + // // return m_gprs.r15; + // // } + + // default: { + // bsl::error() << "unknown by bf_reg_t\n" << bsl::here(); + // break; + // } + // } + + return bsl::safe_uintmax::failure(); + } + + /// + /// @brief Writes a field to the VPS given a bf_reg_t + /// defining the field and a value to write. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param reg a bf_reg_t defining the field to write to the VPS + /// @param val the value to write to the VPS + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + write_reg( + tls_t &tls, + intrinsic_t &intrinsic, + syscall::bf_reg_t const reg, + bsl::safe_uintmax const &val) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(!val)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_failure; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + bsl::discard(intrinsic); + bsl::discard(reg); + // switch (reg) { + // // case syscall::bf_reg_t::bf_reg_t_rax: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RAX, val); + // // } + // // else { + // // m_gprs.rax = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rbx: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBX, val); + // // } + // // else { + // // m_gprs.rbx = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rcx: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RCX, val); + // // } + // // else { + // // m_gprs.rcx = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rdx: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDX, val); + // // } + // // else { + // // m_gprs.rdx = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rbp: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBP, val); + // // } + // // else { + // // m_gprs.rbp = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rsi: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RSI, val); + // // } + // // else { + // // m_gprs.rsi = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_rdi: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDI, val); + // // } + // // else { + // // m_gprs.rdi = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r8: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R8, val); + // // } + // // else { + // // m_gprs.r8 = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r9: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R9, val); + // // } + // // else { + // // m_gprs.r9 = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r10: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R10, val); + // // } + // // else { + // // m_gprs.r10 = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r11: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R11, val); + // // } + // // else { + // // m_gprs.r11 = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r12: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R12, val); + // // } + // // else { + // // m_gprs.r12 = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r13: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R13, val); + // // } + // // else { + // // m_gprs.r13 = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r14: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R14, val); + // // } + // // else { + // // m_gprs.r14 = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // // case syscall::bf_reg_t::bf_reg_t_r15: { + // // if (tls.active_vpsid == m_id) { + // // intrinsic.set_tls_reg(syscall::TLS_OFFSET_R15, val); + // // } + // // else { + // // m_gprs.r15 = val.get(); + // // } + // // return bsl::errc_success; + // // } + + // default: { + // bsl::error() << "unknown by bf_reg_t\n" << bsl::here(); + // break; + // } + // } + + return bsl::errc_failure; + } + + /// + /// @brief Runs the VPS. Note that this function does not + /// return until a VMExit occurs. Once complete, this function + /// will return the VMExit reason. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param log the VMExit log to use + /// @return Returns the VMExit reason on success, or + /// bsl::safe_uintmax::failure() on failure. + /// + [[nodiscard]] constexpr auto + run(tls_t &tls, intrinsic_t &intrinsic, vmexit_log_t &log) noexcept -> bsl::safe_uintmax + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::safe_uintmax::failure(); + } + + if (bsl::unlikely_assert(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + if (bsl::unlikely_assert(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot run by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + bsl::discard(intrinsic); + bsl::discard(log); + // bsl::safe_uintmax const exit_reason{intrinsic_vmrun( + // m_guest_vmcb, m_guest_vmcb_phys.get(), m_host_vmcb, m_host_vmcb_phys.get())}; + + // if constexpr (!(BSL_DEBUG_LEVEL < bsl::VV)) { + // log.add( + // tls.ppid, + // {tls.active_vmid, + // tls.active_vpid, + // tls.active_vpsid, + // exit_reason, + // m_guest_vmcb->exitinfo1, + // m_guest_vmcb->exitinfo2, + // m_guest_vmcb->exitininfo, + // intrinsic.tls_reg(syscall::TLS_OFFSET_RAX), + // intrinsic.tls_reg(syscall::TLS_OFFSET_RBX), + // intrinsic.tls_reg(syscall::TLS_OFFSET_RCX), + // intrinsic.tls_reg(syscall::TLS_OFFSET_RDX), + // intrinsic.tls_reg(syscall::TLS_OFFSET_RBP), + // intrinsic.tls_reg(syscall::TLS_OFFSET_RSI), + // intrinsic.tls_reg(syscall::TLS_OFFSET_RDI), + // intrinsic.tls_reg(syscall::TLS_OFFSET_R8), + // intrinsic.tls_reg(syscall::TLS_OFFSET_R9), + // intrinsic.tls_reg(syscall::TLS_OFFSET_R10), + // intrinsic.tls_reg(syscall::TLS_OFFSET_R11), + // intrinsic.tls_reg(syscall::TLS_OFFSET_R12), + // intrinsic.tls_reg(syscall::TLS_OFFSET_R13), + // intrinsic.tls_reg(syscall::TLS_OFFSET_R14), + // intrinsic.tls_reg(syscall::TLS_OFFSET_R15), + // m_guest_vmcb->rsp, + // m_guest_vmcb->rip}); + // } + + /// TODO: + /// - Add check logic to if an entry failure occurs and output + /// what the error was and why. + /// + + return bsl::safe_uintmax::failure(); + } + + /// + /// @brief Advance the IP of the VPS + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + advance_ip(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type + { + bsl::discard(intrinsic); + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + return bsl::errc_success; + } + + /// + /// @brief Clears the VPS's internal cache. Note that this is a + /// hardware specific function and doesn't change the actual + /// values stored in the VPS. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + clear(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type + { + bsl::discard(intrinsic); + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + return bsl::errc_success; + } + + /// + /// @brief Dumps the vm_t + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// + constexpr void + dump(tls_t &tls, intrinsic_t &intrinsic) const noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + + // clang-format off + + if (bsl::unlikely_assert(!m_id)) { + bsl::print() << "[error]" << bsl::endl; + return; + } + + bsl::print() << bsl::mag << "vps ["; + bsl::print() << bsl::rst << bsl::hex(m_id); + bsl::print() << bsl::mag << "] dump: "; + bsl::print() << bsl::rst << bsl::endl; + + /// Header + /// + + bsl::print() << bsl::ylw << "+----------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^30s", "description "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^19s", "value "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+----------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + /// Allocated + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<30s", "allocated "}; + bsl::print() << bsl::ylw << "| "; + if (this->is_allocated()) { + bsl::print() << bsl::grn << bsl::fmt{"^19s", "yes "}; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^19s", "no "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Assigned VP + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<30s", "assigned vp "}; + bsl::print() << bsl::ylw << "| "; + if (m_assigned_vpid != syscall::BF_INVALID_ID) { + bsl::print() << bsl::grn << " " << bsl::hex(m_assigned_vpid) << " "; + } + else { + bsl::print() << bsl::red << " " << bsl::hex(m_assigned_vpid) << " "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Assigned PP + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<30s", "assigned pp "}; + bsl::print() << bsl::ylw << "| "; + if (m_assigned_ppid != syscall::BF_INVALID_ID) { + bsl::print() << bsl::grn << " " << bsl::hex(m_assigned_ppid) << " "; + } + else { + bsl::print() << bsl::red << " " << bsl::hex(m_assigned_ppid) << " "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Guest Missing Fields + /// + + bsl::print() << bsl::ylw << "+----------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + if (!this->is_allocated()) { + return; + } + + bsl::discard(intrinsic); + bsl::discard(tls); + + /// Footer + /// + + bsl::print() << bsl::ylw << "+----------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + // clang-format on + } + }; +} + +#endif diff --git a/kernel/src/arm/aarch64/yield.S b/kernel/src/arm/aarch64/yield.S new file mode 100644 index 00000000..ca06bd45 --- /dev/null +++ b/kernel/src/arm/aarch64/yield.S @@ -0,0 +1,33 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl yield + .type yield, @function +yield: + + .size yield, .-yield diff --git a/loader/include/interface/cpp/bfelf/elf64_ehdr_t.hpp b/kernel/src/bfelf/elf64_ehdr_t.hpp similarity index 70% rename from loader/include/interface/cpp/bfelf/elf64_ehdr_t.hpp rename to kernel/src/bfelf/elf64_ehdr_t.hpp index 9947dec7..1107c0ef 100644 --- a/loader/include/interface/cpp/bfelf/elf64_ehdr_t.hpp +++ b/kernel/src/bfelf/elf64_ehdr_t.hpp @@ -26,7 +26,6 @@ #define BFELF_ELF64_EHDR_T_HPP #include -#include #include #include #include @@ -40,70 +39,70 @@ namespace bfelf { /// @brief e_ident[EI_MAG0] contains 0x7FU for file identification - constexpr bsl::safe_uint64 EI_MAG0{bsl::to_u64(0)}; + constexpr auto EI_MAG0{0_umax}; /// @brief e_ident[EI_MAG1] contains 0x45U for file identification - constexpr bsl::safe_uint64 EI_MAG1{bsl::to_u64(1)}; + constexpr auto EI_MAG1{1_umax}; /// @brief e_ident[EI_MAG2] contains 0x4CU for file identification - constexpr bsl::safe_uint64 EI_MAG2{bsl::to_u64(2)}; + constexpr auto EI_MAG2{2_umax}; /// @brief e_ident[EI_MAG3] contains 0x46U for file identification - constexpr bsl::safe_uint64 EI_MAG3{bsl::to_u64(3)}; + constexpr auto EI_MAG3{3_umax}; /// @brief e_ident[EI_CLASS] identifies if the file is 32bit or 64 bit - constexpr bsl::safe_uint64 EI_CLASS{bsl::to_u64(4)}; + constexpr auto EI_CLASS{4_umax}; /// @brief e_ident[EI_DATA] specifies the data bit encoding of the file - constexpr bsl::safe_uint64 EI_DATA{bsl::to_u64(5)}; + constexpr auto EI_DATA{5_umax}; /// @brief e_ident[EI_VERSION] identifies the version of the file - constexpr bsl::safe_uint64 EI_VERSION{bsl::to_u64(6)}; + constexpr auto EI_VERSION{6_umax}; /// @brief e_ident[EI_OSABI] identifies file's ABI scheme - constexpr bsl::safe_uint64 EI_OSABI{bsl::to_u64(7)}; + constexpr auto EI_OSABI{7_umax}; /// @brief e_ident[EI_ABIVERSION] identifies file's ABI version - constexpr bsl::safe_uint64 EI_ABIVERSION{bsl::to_u64(8)}; + constexpr auto EI_ABIVERSION{8_umax}; /// @brief defines the size of e_ident - constexpr bsl::safe_uint64 EI_NIDENT{bsl::to_u64(16)}; + constexpr auto EI_NIDENT{16_umax}; /// @brief defines the expected e_ident[EI_MAG0] value - constexpr bsl::safe_uint8 ELFMAG0{bsl::to_u8(0x7F)}; + constexpr auto ELFMAG0{0x7F_u8}; /// @brief defines the expected e_ident[EI_MAG1] value - constexpr bsl::safe_uint8 ELFMAG1{bsl::to_u8(0x45)}; + constexpr auto ELFMAG1{0x45_u8}; /// @brief defines the expected e_ident[EI_MAG2] value - constexpr bsl::safe_uint8 ELFMAG2{bsl::to_u8(0x4C)}; + constexpr auto ELFMAG2{0x4C_u8}; /// @brief defines the expected e_ident[EI_MAG3] value - constexpr bsl::safe_uint8 ELFMAG3{bsl::to_u8(0x46)}; + constexpr auto ELFMAG3{0x46_u8}; /// @brief defines e_ident[EI_CLASS] for 32bit objects - constexpr bsl::safe_uint8 ELFCLASS32{bsl::to_u8(1)}; + constexpr auto ELFCLASS32{1_u8}; /// @brief defines e_ident[EI_CLASS] for 64bit objects - constexpr bsl::safe_uint8 ELFCLASS64{bsl::to_u8(2)}; + constexpr auto ELFCLASS64{2_u8}; /// @brief defines e_ident[EI_DATA] for little endian - constexpr bsl::safe_uint8 ELFDATA2LSB{bsl::to_u8(1)}; + constexpr auto ELFDATA2LSB{1_u8}; /// @brief defines e_ident[EI_DATA] for big endian - constexpr bsl::safe_uint8 ELFDATA2MSB{bsl::to_u8(2)}; + constexpr auto ELFDATA2MSB{2_u8}; /// @brief defines e_ident[EI_OSABI] for system v abi - constexpr bsl::safe_uint8 ELFOSABI_SYSV{bsl::to_u8(0)}; + constexpr auto ELFOSABI_SYSV{0_u8}; /// @brief defines e_ident[EI_OSABI] for hp-ux operating system - constexpr bsl::safe_uint8 ELFOSABI_HPUX{bsl::to_u8(1)}; + constexpr auto ELFOSABI_HPUX{1_u8}; /// @brief defines e_ident[EI_OSABI] for standalone applications - constexpr bsl::safe_uint8 ELFOSABI_STANDALONE{bsl::to_u8(255)}; + constexpr auto ELFOSABI_STANDALONE{255_u8}; /// @brief defines e_type for no file type - constexpr bsl::safe_uint16 ET_NONE{bsl::to_u16(0)}; + constexpr auto ET_NONE{0_u16}; /// @brief defines e_type for an relocatable object file - constexpr bsl::safe_uint16 ET_REL{bsl::to_u16(1)}; + constexpr auto ET_REL{1_u16}; /// @brief defines e_type for an executable file - constexpr bsl::safe_uint16 ET_EXEC{bsl::to_u16(2)}; + constexpr auto ET_EXEC{2_u16}; /// @brief defines e_type for an shared object file - constexpr bsl::safe_uint16 ET_DYN{bsl::to_u16(3)}; + constexpr auto ET_DYN{3_u16}; /// @brief defines e_type for an core file - constexpr bsl::safe_uint16 ET_CORE{bsl::to_u16(4)}; + constexpr auto ET_CORE{4_u16}; /// @brief defines e_type for an environment-specific use (lo) - constexpr bsl::safe_uint16 ET_LOOS{bsl::to_u16(0xFE00)}; + constexpr auto ET_LOOS{0xFE00_u16}; /// @brief defines e_type for an environment-specific use (hi) - constexpr bsl::safe_uint16 ET_HIOS{bsl::to_u16(0xFEFF)}; + constexpr auto ET_HIOS{0xFEFF_u16}; /// @brief defines e_type for an processor-specific use (lo) - constexpr bsl::safe_uint16 ET_LOPROC{bsl::to_u16(0xFF00)}; + constexpr auto ET_LOPROC{0xFF00_u16}; /// @brief defines e_type for an processor-specific use (hi) - constexpr bsl::safe_uint16 ET_HIPROC{bsl::to_u16(0xFFFF)}; + constexpr auto ET_HIPROC{0xFFFF_u16}; /// @struct elf64_ehdr_t /// @@ -151,7 +150,7 @@ namespace bfelf /// @return returns a pointer to the ELF header, or nullptr on error /// [[nodiscard]] constexpr auto - get_elf64_ehdr(bsl::span const &file) noexcept -> elf64_ehdr_t const * + get_elf64_ehdr(bsl::span const &file) noexcept -> elf64_ehdr_t const * { if (file.empty()) { bsl::error() << "invalid ELF file\n" << bsl::here(); @@ -175,7 +174,7 @@ namespace bfelf /// @return Returns 0 on success or an error code on failure. /// [[nodiscard]] constexpr auto - validate_elf64_ehdr(bsl::span const &file) noexcept -> bsl::errc_type + validate_elf64_ehdr(bsl::span const &file) noexcept -> bsl::errc_type { auto const *const ehdr{get_elf64_ehdr(file)}; if (nullptr == ehdr) { @@ -183,44 +182,36 @@ namespace bfelf return bsl::errc_failure; } - if (*ehdr->e_ident.at_if(bsl::to_umax(EI_MAG0)) != ELFMAG0) { + if (*ehdr->e_ident.at_if(EI_MAG0) != ELFMAG0) { bsl::error() << "invalid ELF magic number\n" << bsl::here(); return bsl::errc_failure; } - if (*ehdr->e_ident.at_if(bsl::to_umax(EI_MAG1)) != ELFMAG1) { + if (*ehdr->e_ident.at_if(EI_MAG1) != ELFMAG1) { bsl::error() << "invalid ELF magic number\n" << bsl::here(); return bsl::errc_failure; } - if (*ehdr->e_ident.at_if(bsl::to_umax(EI_MAG2)) != ELFMAG2) { + if (*ehdr->e_ident.at_if(EI_MAG2) != ELFMAG2) { bsl::error() << "invalid ELF magic number\n" << bsl::here(); return bsl::errc_failure; } - if (*ehdr->e_ident.at_if(bsl::to_umax(EI_MAG3)) != ELFMAG3) { + if (*ehdr->e_ident.at_if(EI_MAG3) != ELFMAG3) { bsl::error() << "invalid ELF magic number\n" << bsl::here(); return bsl::errc_failure; } - if (*ehdr->e_ident.at_if(bsl::to_umax(EI_CLASS)) != ELFCLASS64) { + if (*ehdr->e_ident.at_if(EI_CLASS) != ELFCLASS64) { bsl::error() << "invalid ELF class\n" << bsl::here(); return bsl::errc_failure; } - if (*ehdr->e_ident.at_if(bsl::to_umax(EI_OSABI)) != ELFOSABI_SYSV) { + if (*ehdr->e_ident.at_if(EI_OSABI) != ELFOSABI_SYSV) { bsl::error() << "invalid ELF OSABI\n" << bsl::here(); return bsl::errc_failure; } - /// TODO: - /// - Eventually we can remove this requirement. For now, this ELF - /// loader only supports statically linked, non-PIE executables. - /// Once this ELF loader is capable of support relocations likes - /// its previous version, we can remove this requirement as we - /// will then be able to handle both dynamic libraries and binaries. - /// - if (ehdr->e_type != ET_EXEC) { bsl::error() << "invalid ELF type\n" << bsl::here(); return bsl::errc_failure; @@ -231,17 +222,17 @@ namespace bfelf /// /// @brief Returns the ELF entry point given an ELF file, or - /// bsl::safe_uintmax::zero(true) if a entry point does not exist or + /// bsl::safe_uintmax::failure() if a entry point does not exist or /// a failure occurs. /// /// /// @param file the ELF file to get the ELF entry point from /// @return Returns the ELF entry point given an ELF file, or - /// bsl::safe_uintmax::zero(true) if a entry point does not exist or + /// bsl::safe_uintmax::failure() if a entry point does not exist or /// a failure occurs. /// [[nodiscard]] constexpr auto - get_elf64_ip(bsl::span const &file) noexcept -> bsl::safe_uintmax + get_elf64_ip(bsl::span const &file) noexcept -> bsl::safe_uintmax { return get_elf64_ehdr(file)->e_entry; } diff --git a/loader/include/interface/cpp/bfelf/elf64_phdr_t.hpp b/kernel/src/bfelf/elf64_phdr_t.hpp similarity index 77% rename from loader/include/interface/cpp/bfelf/elf64_phdr_t.hpp rename to kernel/src/bfelf/elf64_phdr_t.hpp index f73ea90f..ae56e3b2 100644 --- a/loader/include/interface/cpp/bfelf/elf64_phdr_t.hpp +++ b/kernel/src/bfelf/elf64_phdr_t.hpp @@ -25,9 +25,8 @@ #ifndef BFELF_ELF64_PHDR_T_HPP #define BFELF_ELF64_PHDR_T_HPP -#include "elf64_ehdr_t.hpp" +#include -#include #include #include #include @@ -40,44 +39,43 @@ namespace bfelf { - /// @brief defines p_type for unused entry - constexpr bsl::safe_uint32 PT_NULL{bsl::to_u32(0U)}; + constexpr auto PT_NULL{0_u32}; /// @brief defines p_type for a loadable segment - constexpr bsl::safe_uint32 PT_LOAD{bsl::to_u32(1U)}; + constexpr auto PT_LOAD{1_u32}; /// @brief defines p_type for dynamic linking tables - constexpr bsl::safe_uint32 PT_DYNAMIC{bsl::to_u32(2U)}; + constexpr auto PT_DYNAMIC{2_u32}; /// @brief defines p_type for the program interpreter path - constexpr bsl::safe_uint32 PT_INTERP{bsl::to_u32(3U)}; + constexpr auto PT_INTERP{3_u32}; /// @brief defines p_type for note sections - constexpr bsl::safe_uint32 PT_NOTE{bsl::to_u32(4U)}; + constexpr auto PT_NOTE{4_u32}; /// @brief defines p_type for reserved - constexpr bsl::safe_uint32 PT_SHLIB{bsl::to_u32(5U)}; + constexpr auto PT_SHLIB{5_u32}; /// @brief defines p_type for the program header table - constexpr bsl::safe_uint32 PT_PHDR{bsl::to_u32(6U)}; + constexpr auto PT_PHDR{6_u32}; /// @brief defines p_type for the tls segment - constexpr bsl::safe_uint32 PT_TLS{bsl::to_u32(7U)}; + constexpr auto PT_TLS{7_u32}; /// @brief defines p_type for environment-specific use (lo) - constexpr bsl::safe_uint32 PT_LOOS{bsl::to_u32(0x60000000U)}; + constexpr auto PT_LOOS{0x60000000_u32}; /// @brief defines p_type for the GNU stack segment - constexpr bsl::safe_uint32 PT_GNU_STACK{bsl::to_u32(0x6474e551U)}; + constexpr auto PT_GNU_STACK{0x6474e551_u32}; /// @brief defines p_type for environment-specific use (hi) - constexpr bsl::safe_uint32 PT_HIOS{bsl::to_u32(0x6FFFFFFFU)}; + constexpr auto PT_HIOS{0x6FFFFFFF_u32}; /// @brief defines p_type for processor-specific use (lo) - constexpr bsl::safe_uint32 PT_LOPROC{bsl::to_u32(0x70000000U)}; + constexpr auto PT_LOPROC{0x70000000_u32}; /// @brief defines p_type for processor-specific use (hi) - constexpr bsl::safe_uint32 PT_HIPROC{bsl::to_u32(0x7FFFFFFFU)}; + constexpr auto PT_HIPROC{0x7FFFFFFF_u32}; /// @brief defines p_flags for execute permissions - constexpr bsl::safe_uint32 PF_X{bsl::to_u32(1U)}; + constexpr auto PF_X{1_u32}; /// @brief defines p_flags for write permissions - constexpr bsl::safe_uint32 PF_W{bsl::to_u32(2U)}; + constexpr auto PF_W{2_u32}; /// @brief defines p_flags for read permissions - constexpr bsl::safe_uint32 PF_R{bsl::to_u32(4U)}; + constexpr auto PF_R{4_u32}; /// @brief defines p_flags for environment-specific use - constexpr bsl::safe_uint32 PF_MASKOS{bsl::to_u32(0x00FF0000U)}; + constexpr auto PF_MASKOS{0x00FF0000_u32}; /// @brief defines p_flags for environment-specific use - constexpr bsl::safe_uint32 PF_MASKPROC{bsl::to_u32(0xFF000000U)}; + constexpr auto PF_MASKPROC{0xFF000000_u32}; /// @struct elf64_phdr_t /// @@ -115,7 +113,7 @@ namespace bfelf /// on error /// [[nodiscard]] constexpr auto - get_elf64_phdrtab(bsl::span const &file) noexcept + get_elf64_phdrtab(bsl::span const &file) noexcept -> bsl::span { auto const *const ehdr{get_elf64_ehdr(file)}; diff --git a/kernel/src/bsl/cstdio.hpp b/kernel/src/bsl/cstdio.hpp index e781b95a..c9829cb8 100644 --- a/kernel/src/bsl/cstdio.hpp +++ b/kernel/src/bsl/cstdio.hpp @@ -27,6 +27,8 @@ #include #include +#include +#include #include #include @@ -48,7 +50,7 @@ namespace bsl } mk::debug_ring_write(c); - mk::serial_write(c); + mk::serial_write_c(c); } /// diff --git a/kernel/src/bsl/details/print_thread_id.hpp b/kernel/src/bsl/details/print_thread_id.hpp index 96d997fa..4148914f 100644 --- a/kernel/src/bsl/details/print_thread_id.hpp +++ b/kernel/src/bsl/details/print_thread_id.hpp @@ -48,12 +48,19 @@ namespace bsl::details return; } - safe_uintmax thread_id{mk::get_current_tls()->thread_id}; - - o << " [" // -- - << bsl::cyan << bsl::fmt("#018x", thread_id) << bsl::reset_color << " - " // -- - << bsl::black << "MK" << bsl::reset_color // -- - << ']'; // -- + o << bsl::rst << " [" // -- + << bsl::cyn << bsl::fmt{"04x", mk::get_current_tls()->active_extid} // -- + << bsl::rst << ":" // -- + << bsl::cyn << bsl::fmt{"04x", mk::get_current_tls()->active_vmid} // -- + << bsl::rst << ":" // -- + << bsl::cyn << bsl::fmt{"04x", mk::get_current_tls()->active_vpid} // -- + << bsl::rst << ":" // -- + << bsl::cyn << bsl::fmt{"04x", mk::get_current_tls()->active_vpsid} // -- + << bsl::rst << ":" // -- + << bsl::cyn << bsl::fmt{"04x", mk::get_current_tls()->ppid} // -- + << bsl::rst << ":" // -- + << bsl::blk << "MK" // -- + << bsl::rst << ']'; // -- } } diff --git a/kernel/src/debug_ring_write.hpp b/kernel/src/debug_ring_write.hpp index 5fa1c3d1..393536a0 100644 --- a/kernel/src/debug_ring_write.hpp +++ b/kernel/src/debug_ring_write.hpp @@ -37,8 +37,12 @@ namespace mk { - /// @brief stores a pointer to the debug ring provided by the loader - extern "C" constinit inline loader::debug_ring_t *g_debug_ring{}; + extern "C" + { + /// @brief stores a pointer to the debug ring provided by the loader + // NOLINTNEXTLINE(bsl-var-braced-init) + extern loader::debug_ring_t *g_debug_ring; + } /// /// @brief Outputs a character to the serial port. diff --git a/kernel/src/dispatch_esr_page_fault.hpp b/kernel/src/dispatch_esr_page_fault.hpp new file mode 100644 index 00000000..9340f6b2 --- /dev/null +++ b/kernel/src/dispatch_esr_page_fault.hpp @@ -0,0 +1,67 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_ESR_PAGE_FAULT_HPP +#define DISPATCH_ESR_PAGE_FAULT_HPP + +#include +#include + +#include +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Provides the ESR handler for page faults + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success if the exception was handled, + /// bsl::errc_failure otherwise + /// + [[nodiscard]] constexpr auto + dispatch_esr_page_fault(tls_t &tls, page_pool_t &page_pool, ext_t *const ext) noexcept + -> bsl::errc_type + { + /// NOTE: + /// - When the microkernel is still bootstrapping, the ext field in + /// the TLS has not yet been set, so ext could actually be a nullptr + /// which is why it is not passed by reference. + /// + + if (bsl::unlikely(nullptr == ext)) { + return bsl::errc_failure; + } + + return ext->map_page_direct(tls, page_pool, tls.esr_pf_addr); + } +} + +#endif diff --git a/kernel/src/dispatch_syscall.hpp b/kernel/src/dispatch_syscall.hpp index a550d9bf..78db3288 100644 --- a/kernel/src/dispatch_syscall.hpp +++ b/kernel/src/dispatch_syscall.hpp @@ -25,6 +25,7 @@ #ifndef DISPATCH_SYSCALL_HPP #define DISPATCH_SYSCALL_HPP +#include #include #include #include @@ -34,7 +35,16 @@ #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -47,142 +57,148 @@ namespace mk /// will dispatch syscalls as needed. /// /// - /// @tparam SMAP_GUARD_CONCEPT defines the type of smap guard to use - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @tparam VM_POOL_CONCEPT defines the type of VM pool to use - /// @tparam VP_POOL_CONCEPT defines the type of VP pool to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use /// @param tls the current TLS block - /// @param ext the extension that made the syscall + /// @param page_pool the page pool to use + /// @param huge_pool the huge pool to use /// @param intrinsic the intrinsics to use /// @param vm_pool the VM pool to use /// @param vp_pool the VP pool to use /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. + /// @param ext_pool the extension pool to use + /// @param ext the extension that made the syscall + /// @param log the VMExit log to use + /// @return Returns bsl::exit_success on success, bsl::exit_failure + /// otherwise /// - template< - typename SMAP_GUARD_CONCEPT, - typename TLS_CONCEPT, - typename EXT_CONCEPT, - typename INTRINSIC_CONCEPT, - typename VM_POOL_CONCEPT, - typename VP_POOL_CONCEPT, - typename VPS_POOL_CONCEPT> [[nodiscard]] constexpr auto dispatch_syscall( - TLS_CONCEPT &tls, - EXT_CONCEPT &ext, - INTRINSIC_CONCEPT &intrinsic, - VM_POOL_CONCEPT &vm_pool, - VP_POOL_CONCEPT &vp_pool, - VPS_POOL_CONCEPT &vps_pool) noexcept -> syscall::bf_status_t + tls_t &tls, + page_pool_t &page_pool, + huge_pool_t &huge_pool, + intrinsic_t &intrinsic, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + ext_pool_t &ext_pool, + ext_t &ext, + vmexit_log_t &log) noexcept -> bsl::exit_code { - syscall::bf_status_t ret{}; + bsl::errc_type ret{}; switch (syscall::bf_syscall_opcode(tls.ext_syscall).get()) { case syscall::BF_CONTROL_OP_VAL.get(): { - ret = dispatch_syscall_control_op(tls); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = dispatch_syscall_control_op(tls, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return ret; + return bsl::exit_failure; } - return ret; + return bsl::exit_success; } case syscall::BF_HANDLE_OP_VAL.get(): { ret = dispatch_syscall_handle_op(tls, ext); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return ret; + return bsl::exit_failure; } - return ret; + return bsl::exit_success; } case syscall::BF_DEBUG_OP_VAL.get(): { - ret = - dispatch_syscall_debug_op(tls, vm_pool, vp_pool, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = dispatch_syscall_debug_op( + tls, + page_pool, + huge_pool, + intrinsic, + vm_pool, + vp_pool, + vps_pool, + ext_pool, + log); + + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return ret; + return bsl::exit_failure; } - return ret; + return bsl::exit_success; } case syscall::BF_CALLBACK_OP_VAL.get(): { ret = dispatch_syscall_callback_op(tls, ext); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return ret; + return bsl::exit_failure; } - return ret; + return bsl::exit_success; } case syscall::BF_VM_OP_VAL.get(): { - ret = dispatch_syscall_vm_op(tls, ext, vm_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = dispatch_syscall_vm_op(tls, page_pool, vm_pool, vp_pool, ext_pool, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return ret; + return bsl::exit_failure; } - return ret; + return bsl::exit_success; } case syscall::BF_VP_OP_VAL.get(): { - ret = dispatch_syscall_vp_op(tls, ext, vp_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = dispatch_syscall_vp_op(tls, vp_pool, vps_pool, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return ret; + return bsl::exit_failure; } - return ret; + return bsl::exit_success; } case syscall::BF_VPS_OP_VAL.get(): { - ret = dispatch_syscall_vps_op(tls, ext, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = dispatch_syscall_vps_op( + tls, page_pool, intrinsic, vm_pool, vp_pool, vps_pool, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return ret; + return bsl::exit_failure; } - return ret; + return bsl::exit_success; } case syscall::BF_INTRINSIC_OP_VAL.get(): { - ret = dispatch_syscall_intrinsic_op(tls, ext, intrinsic); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = dispatch_syscall_intrinsic_op(tls, intrinsic, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return ret; + return bsl::exit_failure; } - return ret; + return bsl::exit_success; } case syscall::BF_MEM_OP_VAL.get(): { - ret = dispatch_syscall_mem_op(tls, ext); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = dispatch_syscall_mem_op(tls, page_pool, huge_pool, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return ret; + return bsl::exit_failure; } - return ret; + return bsl::exit_success; } default: { - bsl::error() << "unknown syscall signature/opcode: " //-- - << bsl::hex(tls.ext_syscall) //-- - << bsl::endl //-- - << bsl::here(); //-- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; + break; } } + + bsl::error() << "unknown syscall signature/opcode " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::exit_failure; } } diff --git a/kernel/src/dispatch_syscall_callback_op.hpp b/kernel/src/dispatch_syscall_callback_op.hpp index b3546346..2c838759 100644 --- a/kernel/src/dispatch_syscall_callback_op.hpp +++ b/kernel/src/dispatch_syscall_callback_op.hpp @@ -25,8 +25,9 @@ #ifndef DISPATCH_SYSCALL_CALLBACK_OP_HPP #define DISPATCH_SYSCALL_CALLBACK_OP_HPP -#include -#include +#include +#include +#include #include #include @@ -37,155 +38,165 @@ namespace mk { - namespace details + /// + /// @brief Implements the bf_callback_op_register_bootstrap syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_callback_op_register_bootstrap(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type { - /// - /// @brief Implements the bf_callback_op_register_bootstrap syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @param tls the current TLS block - /// @param ext the extension that made the syscall - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_callback_op_register_bootstrap(TLS_CONCEPT &tls, EXT_CONCEPT &ext) - -> syscall::bf_status_t - { - if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { - bsl::error() << "invalid handle: " // -- - << bsl::hex(tls.ext_reg0) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::safe_uintmax callback{tls.ext_reg1}; + if (bsl::unlikely(callback.is_zero())) { + bsl::error() << "the bootstrap callback cannot be null" // -- + << bsl::endl // -- + << bsl::here(); // -- - return syscall::BF_STATUS_FAILURE_INVALID_HANDLE; - } - - if (bsl::unlikely(ext.bootstrap_ip())) { - bsl::error() << "ext [" // -- - << bsl::hex(ext.id()) // -- - << "] already registered a bootstrap callback\n" // -- - << bsl::here(); // -- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - ext.set_bootstrap_ip(tls.ext_reg1); - return syscall::BF_STATUS_SUCCESS; + return bsl::errc_failure; } - /// - /// @brief Implements the bf_callback_op_register_vmexit syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @param tls the current TLS block - /// @param ext the extension that made the syscall - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_callback_op_register_vmexit(TLS_CONCEPT &tls, EXT_CONCEPT &ext) - -> syscall::bf_status_t - { - if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { - bsl::error() << "invalid handle: " // -- - << bsl::hex(tls.ext_reg0) // -- - << bsl::endl // -- - << bsl::here(); // -- + if (bsl::unlikely(ext.bootstrap_ip())) { + bsl::error() << "ext " // -- + << bsl::hex(ext.id()) // -- + << " already registered a bootstrap callback\n" // -- + << bsl::here(); // -- - return syscall::BF_STATUS_FAILURE_INVALID_HANDLE; - } - - if (bsl::likely(nullptr == tls.ext_vmexit)) { - tls.ext_vmexit = &ext; - } - else { - bsl::error() << "ext [" // -- - << bsl::hex(static_cast(tls.ext_vmexit)->id()) // -- - << "] already registered a VMExit callback\n" // -- - << bsl::here(); // -- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - ext.set_vmexit_ip(tls.ext_reg1); - return syscall::BF_STATUS_SUCCESS; + return bsl::errc_failure; } - /// - /// @brief Implements the bf_callback_op_register_fail syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @param tls the current TLS block - /// @param ext the extension that made the syscall - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_callback_op_register_fail(TLS_CONCEPT &tls, EXT_CONCEPT &ext) - -> syscall::bf_status_t - { - if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { - bsl::error() << "invalid handle: " // -- - << bsl::hex(tls.ext_reg0) // -- - << bsl::endl // -- - << bsl::here(); // -- + tls.state_reversal_required = true; + ext.set_bootstrap_ip(callback); - return syscall::BF_STATUS_FAILURE_INVALID_HANDLE; - } + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } - if (bsl::likely(nullptr == tls.ext_fail)) { - tls.ext_fail = &ext; - } - else { - bsl::error() << "ext [" // -- - << bsl::hex(static_cast(tls.ext_fail)->id()) // -- - << "] already registered a fast fail callback\n" // -- - << bsl::here(); // -- + /// + /// @brief Implements the bf_callback_op_register_vmexit syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_callback_op_register_vmexit(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + bsl::safe_uintmax callback{tls.ext_reg1}; + if (bsl::unlikely(callback.is_zero())) { + bsl::error() << "the vmexit callback cannot be null" // -- + << bsl::endl // -- + << bsl::here(); // -- - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - ext.set_fail_ip(tls.ext_reg1); - return syscall::BF_STATUS_SUCCESS; + return bsl::errc_failure; } + + if (bsl::unlikely(ext.vmexit_ip())) { + bsl::error() << "ext " // -- + << bsl::hex(ext.id()) // -- + << " already registered a vmexit callback\n" // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(nullptr != tls.ext_vmexit)) { + bsl::error() << "ext " // -- + << bsl::hex(static_cast(tls.ext_vmexit)->id()) // -- + << " already registered a vmexit callback\n" // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + tls.state_reversal_required = true; + ext.set_vmexit_ip(callback); + tls.ext_vmexit = &ext; + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_callback_op_register_fail syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_callback_op_register_fail(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + bsl::safe_uintmax callback{tls.ext_reg1}; + if (bsl::unlikely(callback.is_zero())) { + bsl::error() << "the fast fail callback cannot be null" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(ext.fail_ip())) { + bsl::error() << "ext " // -- + << bsl::hex(ext.id()) // -- + << " already registered a fast fail callback\n" // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(nullptr != tls.ext_fail)) { + bsl::error() << "ext " // -- + << bsl::hex(static_cast(tls.ext_fail)->id()) // -- + << " already registered a fast fail callback\n" // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + tls.state_reversal_required = true; + ext.set_fail_ip(callback); + tls.ext_fail = &ext; + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } /// /// @brief Dispatches the bf_callback_op syscalls /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use /// @param tls the current TLS block /// @param ext the extension that made the syscall - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise /// - template [[nodiscard]] constexpr auto - dispatch_syscall_callback_op(TLS_CONCEPT &tls, EXT_CONCEPT &ext) -> syscall::bf_status_t + dispatch_syscall_callback_op(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type { - syscall::bf_status_t ret{}; + bsl::errc_type ret{}; + + if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { + bsl::error() << "invalid handle " // -- + << bsl::hex(tls.ext_reg0) // -- + << bsl::endl // -- + << bsl::here(); // -- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_INVALID_HANDLE.get(); + return bsl::errc_failure; + } switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { - case syscall::BF_CALLBACK_OP_WAIT_IDX_VAL.get(): { - return_to_mk(bsl::ZERO_UMAX.get()); - return syscall::BF_STATUS_SUCCESS; - } - case syscall::BF_CALLBACK_OP_REGISTER_BOOTSTRAP_IDX_VAL.get(): { - ret = details::syscall_callback_op_register_bootstrap(tls, ext); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_callback_op_register_bootstrap(tls, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -194,8 +205,8 @@ namespace mk } case syscall::BF_CALLBACK_OP_REGISTER_VMEXIT_IDX_VAL.get(): { - ret = details::syscall_callback_op_register_vmexit(tls, ext); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_callback_op_register_vmexit(tls, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -204,8 +215,8 @@ namespace mk } case syscall::BF_CALLBACK_OP_REGISTER_FAIL_IDX_VAL.get(): { - ret = details::syscall_callback_op_register_fail(tls, ext); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_callback_op_register_fail(tls, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -214,14 +225,17 @@ namespace mk } default: { - bsl::error() << "unknown syscall index: " //-- - << bsl::hex(tls.ext_syscall) //-- - << bsl::endl //-- - << bsl::here(); //-- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; + break; } } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; } } diff --git a/kernel/src/dispatch_syscall_callback_op_failure.hpp b/kernel/src/dispatch_syscall_callback_op_failure.hpp new file mode 100644 index 00000000..b9f0e9c0 --- /dev/null +++ b/kernel/src/dispatch_syscall_callback_op_failure.hpp @@ -0,0 +1,127 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_SYSCALL_CALLBACK_OP_FAILURE_HPP +#define DISPATCH_SYSCALL_CALLBACK_OP_FAILURE_HPP + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Implements the bf_callback_op_register_bootstrap syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// + constexpr void + syscall_callback_op_register_bootstrap_failure(tls_t &tls, ext_t &ext) noexcept + { + if (!tls.state_reversal_required) { + return; + } + + ext.set_bootstrap_ip(bsl::safe_uintmax::failure()); + } + + /// + /// @brief Implements the bf_callback_op_register_vmexit syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// + constexpr void + syscall_callback_op_register_vmexit_failure(tls_t &tls, ext_t &ext) noexcept + { + if (!tls.state_reversal_required) { + return; + } + + ext.set_vmexit_ip(bsl::safe_uintmax::failure()); + tls.ext_vmexit = nullptr; + } + + /// + /// @brief Implements the bf_callback_op_register_fail syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// + constexpr void + syscall_callback_op_register_fail_failure(tls_t &tls, ext_t &ext) noexcept + { + if (!tls.state_reversal_required) { + return; + } + + ext.set_fail_ip(bsl::safe_uintmax::failure()); + tls.ext_fail = nullptr; + } + + /// + /// @brief Dispatches the bf_callback_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// + constexpr void + dispatch_syscall_callback_op_failure(tls_t &tls, ext_t &ext) noexcept + { + switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { + case syscall::BF_CALLBACK_OP_REGISTER_BOOTSTRAP_IDX_VAL.get(): { + syscall_callback_op_register_bootstrap_failure(tls, ext); + break; + } + + case syscall::BF_CALLBACK_OP_REGISTER_VMEXIT_IDX_VAL.get(): { + syscall_callback_op_register_vmexit_failure(tls, ext); + break; + } + + case syscall::BF_CALLBACK_OP_REGISTER_FAIL_IDX_VAL.get(): { + syscall_callback_op_register_fail_failure(tls, ext); + break; + } + + default: { + break; + } + } + } +} + +#endif diff --git a/kernel/src/dispatch_syscall_control_op.hpp b/kernel/src/dispatch_syscall_control_op.hpp index 4bf6be1a..9c5a76c1 100644 --- a/kernel/src/dispatch_syscall_control_op.hpp +++ b/kernel/src/dispatch_syscall_control_op.hpp @@ -25,8 +25,10 @@ #ifndef DISPATCH_SYSCALL_CONTROL_OP_HPP #define DISPATCH_SYSCALL_CONTROL_OP_HPP -#include +#include +#include #include +#include #include @@ -36,30 +38,46 @@ namespace mk /// @brief Dispatches the bf_callback_op syscalls /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise /// - template [[nodiscard]] constexpr auto - dispatch_syscall_control_op(TLS_CONCEPT &tls) noexcept -> syscall::bf_status_t + dispatch_syscall_control_op(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type { switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { case syscall::BF_CONTROL_OP_EXIT_IDX_VAL.get(): { - return_to_mk(bsl::ONE_UMAX.get()); - return syscall::BF_STATUS_SUCCESS; + return_to_mk(bsl::exit_failure); + + // Unreachable + return bsl::errc_success; + } + + case syscall::BF_CONTROL_OP_WAIT_IDX_VAL.get(): { + if (ext.is_started()) { + return_to_mk(bsl::exit_failure); + } + else { + return_to_mk(bsl::exit_success); + } + + // Unreachable + return bsl::errc_success; } default: { - bsl::error() << "unknown syscall index: " //-- - << bsl::hex(tls.ext_syscall) //-- - << bsl::endl //-- - << bsl::here(); //-- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; + break; } } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; } } diff --git a/kernel/src/fast_fail_trampoline.cpp b/kernel/src/dispatch_syscall_control_op_failure.hpp similarity index 60% rename from kernel/src/fast_fail_trampoline.cpp rename to kernel/src/dispatch_syscall_control_op_failure.hpp index 6b5aa103..20a49847 100644 --- a/kernel/src/fast_fail_trampoline.cpp +++ b/kernel/src/dispatch_syscall_control_op_failure.hpp @@ -22,30 +22,40 @@ /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE /// SOFTWARE. -#include -#include +#ifndef DISPATCH_SYSCALL_CONTROL_OP_FAILURE_HPP +#define DISPATCH_SYSCALL_CONTROL_OP_FAILURE_HPP + +#include +#include #include +#include + namespace mk { /// - /// @brief Since we cannot create a template function pointer, we need - /// a way to call a template function from our ASM entry point. - /// Normally the way this works in a normal program is the OS calls - /// _start, which then calls main(). The main() function, which is - /// an extern C function, similar to this function, can then call a - /// template function as needed. So the whole point of this function - /// is to simply trampoline from our ASM logic, to a C++ template - /// function that is easy to test. + /// @brief Dispatches the bf_callback_op syscalls /// /// /// @param tls the current TLS block - /// @return Returns bsl::exit_success on success and bsl::exit_failure - /// otherwise /// - extern "C" [[nodiscard]] auto - fast_fail_trampoline(tls_t *const tls) noexcept -> bsl::exit_code + constexpr void + dispatch_syscall_control_op_failure(tls_t &tls) noexcept { - return fast_fail(*tls, static_cast(tls->ext_fail)); + switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { + case syscall::BF_CONTROL_OP_EXIT_IDX_VAL.get(): { + break; + } + + case syscall::BF_CONTROL_OP_WAIT_IDX_VAL.get(): { + break; + } + + default: { + break; + } + } } } + +#endif diff --git a/kernel/src/dispatch_syscall_debug_op.hpp b/kernel/src/dispatch_syscall_debug_op.hpp index b4ea217d..f3f1d48b 100644 --- a/kernel/src/dispatch_syscall_debug_op.hpp +++ b/kernel/src/dispatch_syscall_debug_op.hpp @@ -25,7 +25,16 @@ #ifndef DISPATCH_SYSCALL_DEBUG_OP_HPP #define DISPATCH_SYSCALL_DEBUG_OP_HPP -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -34,65 +43,34 @@ namespace mk { - namespace details - { - /// - /// @brief Implements the debug_op_dump_vps syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_debug_op_dump_vps(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) - -> syscall::bf_status_t - { - auto const ret{vps_pool.dump(tls, bsl::to_u16_unsafe(tls.ext_reg0))}; - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - return syscall::BF_STATUS_SUCCESS; - } - } - /// /// @brief Dispatches the bf_debug_op syscalls /// /// - /// @tparam SMAP_GUARD_CONCEPT defines the type of smap guard to use - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VM_POOL_CONCEPT defines the type of VM pool to use - /// @tparam VP_POOL_CONCEPT defines the type of VP pool to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param huge_pool the huge pool to use + /// @param intrinsic the intrinsics to use /// @param vm_pool the VM pool to use /// @param vp_pool the VP pool to use /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. + /// @param ext_pool the extension pool to use + /// @param log the VMExit log to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise /// - template< - typename SMAP_GUARD_CONCEPT, - typename TLS_CONCEPT, - typename VM_POOL_CONCEPT, - typename VP_POOL_CONCEPT, - typename VPS_POOL_CONCEPT> [[nodiscard]] constexpr auto dispatch_syscall_debug_op( - TLS_CONCEPT &tls, - VM_POOL_CONCEPT &vm_pool, - VP_POOL_CONCEPT &vp_pool, - VPS_POOL_CONCEPT &vps_pool) noexcept -> syscall::bf_status_t + tls_t &tls, + page_pool_t &page_pool, + huge_pool_t &huge_pool, + intrinsic_t &intrinsic, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + ext_pool_t &ext_pool, + vmexit_log_t &log) noexcept -> bsl::errc_type { - syscall::bf_status_t ret{}; - switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { case syscall::BF_DEBUG_OP_OUT_IDX_VAL.get(): { bsl::print() << bsl::hex(tls.ext_reg0) //-- @@ -100,56 +78,96 @@ namespace mk << bsl::hex(tls.ext_reg1) //-- << bsl::endl; //-- - return syscall::BF_STATUS_SUCCESS; + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } case syscall::BF_DEBUG_OP_DUMP_VM_IDX_VAL.get(): { - bsl::discard(vm_pool); - bsl::error() << "bf_debug_op_dump_vms unsupported\n" << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNSUPPORTED; + vm_pool.dump(tls, bsl::to_u16_unsafe(tls.ext_reg0)); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } case syscall::BF_DEBUG_OP_DUMP_VP_IDX_VAL.get(): { - bsl::discard(vp_pool); - bsl::error() << "bf_debug_op_dump_vps unsupported\n" << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNSUPPORTED; + vp_pool.dump(tls, bsl::to_u16_unsafe(tls.ext_reg0)); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } case syscall::BF_DEBUG_OP_DUMP_VPS_IDX_VAL.get(): { - ret = details::syscall_debug_op_dump_vps(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { - bsl::print() << bsl::here(); - return ret; - } + vps_pool.dump(tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg0)); - return ret; + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } case syscall::BF_DEBUG_OP_DUMP_VMEXIT_LOG_IDX_VAL.get(): { - bsl::error() << "bf_debug_op_dump_vmexit_log unsupported\n" << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNSUPPORTED; + log.dump(bsl::to_u16_unsafe(tls.ext_reg0)); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } case syscall::BF_DEBUG_OP_WRITE_C_IDX_VAL.get(): { bsl::print() << static_cast(bsl::to_u8(tls.ext_reg0).get()); - return syscall::BF_STATUS_SUCCESS; + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } case syscall::BF_DEBUG_OP_WRITE_STR_IDX_VAL.get(): { - SMAP_GUARD_CONCEPT unlock{}; + + /// NOTE: + /// - This is the only syscall that might produce an + /// exception, and that is due to the need to access user + /// space memory. If this occurs, reversal is not needed. + /// - The function is still marked as exception unsafe, but + /// in reality, if an exception fires, there is nothing to + /// do, and likely will just result in corrupt debugging + /// information. + /// + bsl::print() << bsl::to_ptr(tls.ext_reg0); - return syscall::BF_STATUS_SUCCESS; + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + case syscall::BF_DEBUG_OP_DUMP_EXT_IDX_VAL.get(): { + ext_pool.dump(tls, page_pool, bsl::to_u16_unsafe(tls.ext_reg0)); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + case syscall::BF_DEBUG_OP_DUMP_PAGE_POOL_IDX_VAL.get(): { + page_pool.dump(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + case syscall::BF_DEBUG_OP_DUMP_HUGE_POOL_IDX_VAL.get(): { + huge_pool.dump(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } default: { - bsl::error() << "unknown syscall index: " //-- - << bsl::hex(tls.ext_syscall) //-- - << bsl::endl //-- - << bsl::here(); //-- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; + break; } } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; } } diff --git a/kernel/src/dispatch_syscall_debug_op_failure.hpp b/kernel/src/dispatch_syscall_debug_op_failure.hpp new file mode 100644 index 00000000..f67b853a --- /dev/null +++ b/kernel/src/dispatch_syscall_debug_op_failure.hpp @@ -0,0 +1,95 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_SYSCALL_DEBUG_OP_FAILURE_HPP +#define DISPATCH_SYSCALL_DEBUG_OP_FAILURE_HPP + +#include +#include + +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Dispatches the bf_debug_op syscalls + /// + /// + /// @param tls the current TLS block + /// + constexpr void + dispatch_syscall_debug_op_failure(tls_t &tls) noexcept + { + switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { + case syscall::BF_DEBUG_OP_OUT_IDX_VAL.get(): { + break; + } + + case syscall::BF_DEBUG_OP_DUMP_VM_IDX_VAL.get(): { + break; + } + + case syscall::BF_DEBUG_OP_DUMP_VP_IDX_VAL.get(): { + break; + } + + case syscall::BF_DEBUG_OP_DUMP_VPS_IDX_VAL.get(): { + break; + } + + case syscall::BF_DEBUG_OP_DUMP_VMEXIT_LOG_IDX_VAL.get(): { + break; + } + + case syscall::BF_DEBUG_OP_WRITE_C_IDX_VAL.get(): { + break; + } + + case syscall::BF_DEBUG_OP_WRITE_STR_IDX_VAL.get(): { + break; + } + + case syscall::BF_DEBUG_OP_DUMP_EXT_IDX_VAL.get(): { + break; + } + + case syscall::BF_DEBUG_OP_DUMP_PAGE_POOL_IDX_VAL.get(): { + break; + } + + case syscall::BF_DEBUG_OP_DUMP_HUGE_POOL_IDX_VAL.get(): { + break; + } + + default: { + break; + } + } + } +} + +#endif diff --git a/kernel/src/dispatch_syscall_failure.hpp b/kernel/src/dispatch_syscall_failure.hpp new file mode 100644 index 00000000..38136f19 --- /dev/null +++ b/kernel/src/dispatch_syscall_failure.hpp @@ -0,0 +1,201 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_SYSCALL_FAILURE_HPP +#define DISPATCH_SYSCALL_FAILURE_HPP + +#include +#include +#include +#include +// #include +// #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace mk +{ + /// + /// @brief Provides the main entry point for all syscalls failures. + /// If something goes wrong, this is the code that will undo any + /// state changes that might have occurred. + /// - If an error should occur (the syscall handler returns an + /// error code), we need to undo any state changes that might + /// have occurred. + /// - We cannot undo the state changes in the handler itself. This + /// is because if an exception were to fire, those state changes + /// would not be reversed. For example, you could put some logic + /// in the syscall handler that detects an error and reverses the + /// change that it previously made. But what if an exception fires + /// after the change, but before the reversal code executes. + /// - The point of these failure functions is to handle all state + /// reversal changes here. If an exception fires, or if an error + /// occurs, the reversal logic happens in the same place so that + /// it can be handled. + /// - These reversal functions need to be able to handle the case + /// were an exception fires while a lock was taken. Not only does + /// it need to reverse the state, but it also needs to clean up + /// the lock state so that this code can handle the reversal + /// without deadlock, and so that future syscalls do not also lead + /// to potential deadlock. + /// - Not every function is likely to cause an exception. With decent + /// unit testing, a fair number of syscalls will never produce an + /// exception because they are not doing anything outside of state + /// management. In either case, we handle any state reversal here + /// just in case. + /// - Not all types of exceptions can be handled. There are some that + /// if they occur, really bad things would happen and there just is + /// no reasonable way to record. For example, if CR3 is swapped and + /// the microkernel can no longer execute, there is nothing we can + /// do. These types of errors however are easy to detect with system + /// and integration testing, so they are less of a potential issue. + /// What we are trying to provide is some protection against coding + /// mistakes as things are being worked on that would lead to hard + /// to debug situations. In otherwords, try to provide some fault + /// tolerance so that the system is easier to work with in general. + /// - It is possible that this code could fire an exception. If that + /// happens, something is really bad and there is nothing we can + /// do but fast fail again and leave. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param huge_pool the huge pool to use + /// @param intrinsic the intrinsics to use + /// @param vm_pool the VM pool to use + /// @param vp_pool the VP pool to use + /// @param vps_pool the VPS pool to use + /// @param ext_pool the extension pool to use + /// @param ext the extension that made the syscall + /// @param log the VMExit log to use + /// @return Returns bsl::exit_success on success, bsl::exit_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + dispatch_syscall_failure( + tls_t &tls, + page_pool_t &page_pool, + huge_pool_t &huge_pool, + intrinsic_t &intrinsic, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + ext_pool_t &ext_pool, + ext_t &ext, + vmexit_log_t &log) noexcept -> bsl::exit_code + { + bsl::discard(huge_pool); + bsl::discard(log); + + bsl::errc_type ret{bsl::errc_success}; + + switch (syscall::bf_syscall_opcode(tls.ext_syscall).get()) { + case syscall::BF_CONTROL_OP_VAL.get(): { + dispatch_syscall_control_op_failure(tls); + break; + } + + case syscall::BF_HANDLE_OP_VAL.get(): { + ret = dispatch_syscall_handle_op_failure(tls, ext); + break; + } + + case syscall::BF_DEBUG_OP_VAL.get(): { + dispatch_syscall_debug_op_failure(tls); + break; + } + + case syscall::BF_CALLBACK_OP_VAL.get(): { + dispatch_syscall_callback_op_failure(tls, ext); + break; + } + + case syscall::BF_VM_OP_VAL.get(): { + ret = dispatch_syscall_vm_op_failure(tls, page_pool, vm_pool, vp_pool, ext_pool); + break; + } + + case syscall::BF_VP_OP_VAL.get(): { + ret = dispatch_syscall_vp_op_failure(tls, vp_pool, vps_pool); + break; + } + + case syscall::BF_VPS_OP_VAL.get(): { + ret = dispatch_syscall_vps_op_failure( + tls, page_pool, intrinsic, vm_pool, vp_pool, vps_pool, ext); + break; + } + + // case syscall::BF_INTRINSIC_OP_VAL.get(): { + // ret = dispatch_syscall_intrinsic_op(tls, ext, intrinsic); + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return bsl::exit_failure; + // } + + // return bsl::exit_success; + // } + + // case syscall::BF_MEM_OP_VAL.get(): { + // ret = dispatch_syscall_mem_op(tls, ext); + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return bsl::exit_failure; + // } + + // return bsl::exit_success; + // } + + default: { + break; + } + } + + if (!ret) { + bsl::print() << bsl::red << " --> FAILED TO REVERSE STATE. CORRUPTION LIKELY"; //-- + bsl::print() << bsl::rst << bsl::endl; + + return bsl::exit_failure; + } + + return bsl::exit_success; + } +} + +#endif diff --git a/kernel/src/dispatch_syscall_handle_op.hpp b/kernel/src/dispatch_syscall_handle_op.hpp index 33467d5b..4563853e 100644 --- a/kernel/src/dispatch_syscall_handle_op.hpp +++ b/kernel/src/dispatch_syscall_handle_op.hpp @@ -25,99 +25,104 @@ #ifndef DISPATCH_SYSCALL_HANDLE_OP_HPP #define DISPATCH_SYSCALL_HANDLE_OP_HPP -#include +#include +#include +#include #include #include namespace mk { - namespace details + /// + /// @brief Implements the bf_handle_op_open_handle syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_handle_op_open_handle(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type { - /// - /// @brief Implements the bf_handle_op_open_handle syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @param tls the current TLS block - /// @param ext the extension that made the syscall - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_handle_op_open_handle(TLS_CONCEPT &tls, EXT_CONCEPT &ext) -> syscall::bf_status_t - { - if (bsl::unlikely(bsl::to_u32(tls.ext_reg0) != syscall::BF_SPEC_ID1_VAL)) { - bsl::error() << "unsupported syscall interface: " //-- - << bsl::hex(tls.ext_reg0) //-- - << bsl::endl //-- - << bsl::here(); //-- + if (bsl::unlikely(bsl::to_u32(tls.ext_reg0) != syscall::BF_SPEC_ID1_VAL)) { + bsl::error() << "unsupported syscall ABI " //-- + << bsl::hex(tls.ext_reg0) //-- + << bsl::endl //-- + << bsl::here(); //-- - return syscall::BF_STATUS_FAILURE_UNSUPPORTED; - } - - auto const handle{ext.open_handle()}; - if (bsl::unlikely(!handle)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - tls.ext_reg0 = handle.get(); - return syscall::BF_STATUS_SUCCESS; + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; } - /// - /// @brief Implements the bf_handle_op_close_handle syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @param tls the current TLS block - /// @param ext the extension that made the syscall - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_handle_op_close_handle(TLS_CONCEPT &tls, EXT_CONCEPT &ext) -> syscall::bf_status_t - { - if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { - bsl::error() << "invalid handle: " // -- - << bsl::hex(tls.ext_reg0) // -- - << bsl::endl // -- - << bsl::here(); // -- + tls.state_reversal_required = true; - return syscall::BF_STATUS_FAILURE_INVALID_HANDLE; - } - - ext.close_handle(); - return syscall::BF_STATUS_SUCCESS; + auto const handle{ext.open_handle()}; + if (bsl::unlikely(!handle)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; } + + tls.ext_reg0 = handle.get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_handle_op_close_handle syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_handle_op_close_handle(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { + bsl::error() << "invalid handle " // -- + << bsl::hex(tls.ext_reg0) // -- + << bsl::endl // -- + << bsl::here(); // -- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_INVALID_HANDLE.get(); + return bsl::errc_failure; + } + + tls.state_reversal_required = true; + ext.close_handle(); + + // int *i = nullptr; + // *i = 42; + + // bsl::error() << "test error\n"; + // return bsl::errc_failure; + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } /// /// @brief Dispatches the bf_handle_op syscalls /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use /// @param tls the current TLS block /// @param ext the extension that made the syscall - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise /// - template [[nodiscard]] constexpr auto - dispatch_syscall_handle_op(TLS_CONCEPT &tls, EXT_CONCEPT &ext) -> syscall::bf_status_t + dispatch_syscall_handle_op(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type { - syscall::bf_status_t ret{}; + bsl::errc_type ret{}; switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { case syscall::BF_HANDLE_OP_OPEN_HANDLE_IDX_VAL.get(): { - ret = details::syscall_handle_op_open_handle(tls, ext); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_handle_op_open_handle(tls, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -126,8 +131,8 @@ namespace mk } case syscall::BF_HANDLE_OP_CLOSE_HANDLE_IDX_VAL.get(): { - ret = details::syscall_handle_op_close_handle(tls, ext); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_handle_op_close_handle(tls, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -136,14 +141,17 @@ namespace mk } default: { - bsl::error() << "unknown syscall index: " //-- - << bsl::hex(tls.ext_syscall) //-- - << bsl::endl //-- - << bsl::here(); //-- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; + break; } } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; } } diff --git a/kernel/src/dispatch_syscall_handle_op_failure.hpp b/kernel/src/dispatch_syscall_handle_op_failure.hpp new file mode 100644 index 00000000..326d80a5 --- /dev/null +++ b/kernel/src/dispatch_syscall_handle_op_failure.hpp @@ -0,0 +1,127 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_SYSCALL_HANDLE_OP_FAILURE_HPP +#define DISPATCH_SYSCALL_HANDLE_OP_FAILURE_HPP + +#include +#include +#include + +#include +#include + +namespace mk +{ + /// + /// @brief Implements the bf_handle_op_open_handle syscall failure logic + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// + constexpr void + syscall_handle_op_open_handle_failure(tls_t &tls, ext_t &ext) noexcept + { + if (!tls.state_reversal_required) { + return; + } + + if (ext.is_handle_open()) { + ext.close_handle(); + } + else { + bsl::touch(); + } + + tls.ext_reg0 = {}; + } + + /// + /// @brief Implements the bf_handle_op_close_handle syscall failure logic + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_handle_op_close_handle_failure(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + if (!tls.state_reversal_required) { + return bsl::errc_success; + } + + if (!ext.is_handle_open()) { + auto const handle{ext.open_handle()}; + if (bsl::unlikely(!handle)) { + bsl::print() << bsl::red << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + return bsl::errc_success; + } + + /// + /// @brief Dispatches the bf_handle_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + dispatch_syscall_handle_op_failure(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { + case syscall::BF_HANDLE_OP_OPEN_HANDLE_IDX_VAL.get(): { + syscall_handle_op_open_handle_failure(tls, ext); + return bsl::errc_success; + } + + case syscall::BF_HANDLE_OP_CLOSE_HANDLE_IDX_VAL.get(): { + ret = syscall_handle_op_close_handle_failure(tls, ext); + return ret; + } + + default: { + break; + } + } + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/src/dispatch_syscall_mem_op.hpp b/kernel/src/dispatch_syscall_mem_op.hpp index da336fdb..822321af 100644 --- a/kernel/src/dispatch_syscall_mem_op.hpp +++ b/kernel/src/dispatch_syscall_mem_op.hpp @@ -25,7 +25,9 @@ #ifndef DISPATCH_SYSCALL_MEM_OP_HPP #define DISPATCH_SYSCALL_MEM_OP_HPP -#include +#include +#include +#include #include #include @@ -34,90 +36,172 @@ namespace mk { - namespace details + /// + /// @brief Implements the bf_mem_op_alloc_page syscall + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_mem_op_alloc_page(tls_t &tls, page_pool_t &page_pool, ext_t &ext) noexcept + -> bsl::errc_type { - /// - /// @brief Implements the bf_mem_op_alloc_page syscall + /// NOTE: + /// - ext.alloc_page is assumped to be exception UNSAFE /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @param tls the current TLS block - /// @param ext the extension that made the syscall - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_mem_op_alloc_page(TLS_CONCEPT &tls, EXT_CONCEPT &ext) -> syscall::bf_status_t - { - auto const page{ext.alloc_page()}; - if (bsl::unlikely(!page.virt)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - tls.ext_reg0 = page.virt.get(); - tls.ext_reg1 = page.phys.get(); - return syscall::BF_STATUS_SUCCESS; + auto const page{ext.alloc_page(tls, page_pool)}; + if (bsl::unlikely(!page.virt)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; } - /// - /// @brief Implements the bf_mem_op_virt_to_phys syscall + /// NOTE: + /// - The remaining is assumped to be exception safe /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @param tls the current TLS block - /// @param ext the extension that made the syscall - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_mem_op_virt_to_phys(TLS_CONCEPT &tls, EXT_CONCEPT &ext) -> syscall::bf_status_t - { - auto const phys{ext.virt_to_phys(tls.ext_reg1)}; - if (bsl::unlikely(!phys)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - tls.ext_reg0 = phys.get(); - return syscall::BF_STATUS_SUCCESS; + tls.ext_reg0 = page.virt.get(); + tls.ext_reg1 = page.phys.get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_mem_op_free_page syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_mem_op_free_page(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + auto const ret{ext.free_page(bsl::to_umax(tls.ext_reg1))}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_mem_op_alloc_huge syscall + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param huge_pool the huge pool to use + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_mem_op_alloc_huge( + tls_t &tls, page_pool_t &page_pool, huge_pool_t &huge_pool, ext_t &ext) noexcept + -> bsl::errc_type + { + auto const huge{ext.alloc_huge(tls, page_pool, huge_pool, bsl::to_umax(tls.ext_reg1))}; + if (bsl::unlikely(!huge.virt)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.ext_reg0 = huge.virt.get(); + tls.ext_reg1 = huge.phys.get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_mem_op_free_huge syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_mem_op_free_huge(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + auto const ret{ext.free_huge(bsl::to_umax(tls.ext_reg1))}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_mem_op_alloc_heap syscall + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_mem_op_alloc_heap(tls_t &tls, page_pool_t &page_pool, ext_t &ext) noexcept + -> bsl::errc_type + { + auto const previous_heap_virt{ext.alloc_heap(tls, page_pool, bsl::to_umax(tls.ext_reg1))}; + if (bsl::unlikely(!previous_heap_virt)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.ext_reg0 = previous_heap_virt.get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } /// /// @brief Dispatches the bf_mem_op syscalls /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param huge_pool the huge pool to use /// @param ext the extension that made the syscall - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise /// - template [[nodiscard]] constexpr auto - dispatch_syscall_mem_op(TLS_CONCEPT &tls, EXT_CONCEPT &ext) -> syscall::bf_status_t + dispatch_syscall_mem_op( + tls_t &tls, page_pool_t &page_pool, huge_pool_t &huge_pool, ext_t &ext) noexcept + -> bsl::errc_type { - syscall::bf_status_t ret{}; + bsl::errc_type ret{}; if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { - bsl::error() << "invalid handle: " // -- + bsl::error() << "invalid handle " // -- << bsl::hex(tls.ext_reg0) // -- << bsl::endl // -- << bsl::here(); // -- - return syscall::BF_STATUS_FAILURE_INVALID_HANDLE; + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_INVALID_HANDLE.get(); + return bsl::errc_failure; } switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { case syscall::BF_MEM_OP_ALLOC_PAGE_IDX_VAL.get(): { - ret = details::syscall_mem_op_alloc_page(tls, ext); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_mem_op_alloc_page(tls, page_pool, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -125,9 +209,39 @@ namespace mk return ret; } - case syscall::BF_MEM_OP_VIRT_TO_PHYS_IDX_VAL.get(): { - ret = details::syscall_mem_op_virt_to_phys(tls, ext); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + case syscall::BF_MEM_OP_FREE_PAGE_IDX_VAL.get(): { + ret = syscall_mem_op_free_page(tls, ext); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_MEM_OP_ALLOC_HUGE_IDX_VAL.get(): { + ret = syscall_mem_op_alloc_huge(tls, page_pool, huge_pool, ext); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_MEM_OP_FREE_HUGE_IDX_VAL.get(): { + ret = syscall_mem_op_free_huge(tls, ext); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_MEM_OP_ALLOC_HEAP_IDX_VAL.get(): { + ret = syscall_mem_op_alloc_heap(tls, page_pool, ext); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -136,14 +250,17 @@ namespace mk } default: { - bsl::error() << "unknown syscall index: " //-- - << bsl::hex(tls.ext_syscall) //-- - << bsl::endl //-- - << bsl::here(); //-- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; + break; } } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; } } diff --git a/kernel/src/dispatch_syscall_mem_op_failure.hpp b/kernel/src/dispatch_syscall_mem_op_failure.hpp new file mode 100644 index 00000000..851d9d44 --- /dev/null +++ b/kernel/src/dispatch_syscall_mem_op_failure.hpp @@ -0,0 +1,255 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_SYSCALL_MEM_OP_HPP +#define DISPATCH_SYSCALL_MEM_OP_HPP + +#include +#include +#include + +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Implements the bf_mem_op_alloc_page syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_mem_op_alloc_page(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + /// NOTE: + /// - ext.alloc_page is assumped to be exception UNSAFE + /// + + auto const page{ext.alloc_page(tls)}; + if (bsl::unlikely(!page.virt)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + /// NOTE: + /// - The remaining is assumped to be exception safe + /// + + tls.ext_reg0 = page.virt.get(); + tls.ext_reg1 = page.phys.get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_mem_op_free_page syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_mem_op_free_page(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + auto const ret{ext.free_page(bsl::to_umax(tls.ext_reg1))}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_mem_op_alloc_huge syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_mem_op_alloc_huge(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + auto const huge{ext.alloc_huge(tls, bsl::to_umax(tls.ext_reg1))}; + if (bsl::unlikely(!huge.virt)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.ext_reg0 = huge.virt.get(); + tls.ext_reg1 = huge.phys.get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_mem_op_free_huge syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_mem_op_free_huge(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + auto const ret{ext.free_huge(bsl::to_umax(tls.ext_reg1))}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_mem_op_alloc_heap syscall + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_mem_op_alloc_heap(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + auto const previous_heap_virt{ext.alloc_heap(tls, bsl::to_umax(tls.ext_reg1))}; + if (bsl::unlikely(!previous_heap_virt)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.ext_reg0 = previous_heap_virt.get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Dispatches the bf_mem_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + dispatch_syscall_mem_op(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { + bsl::error() << "invalid handle " // -- + << bsl::hex(tls.ext_reg0) // -- + << bsl::endl // -- + << bsl::here(); // -- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_INVALID_HANDLE.get(); + return bsl::errc_failure; + } + + switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { + case syscall::BF_MEM_OP_ALLOC_PAGE_IDX_VAL.get(): { + ret = syscall_mem_op_alloc_page(tls, ext); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_MEM_OP_FREE_PAGE_IDX_VAL.get(): { + ret = syscall_mem_op_free_page(tls, ext); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_MEM_OP_ALLOC_HUGE_IDX_VAL.get(): { + ret = syscall_mem_op_alloc_huge(tls, ext); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_MEM_OP_FREE_HUGE_IDX_VAL.get(): { + ret = syscall_mem_op_free_huge(tls, ext); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_MEM_OP_ALLOC_HEAP_IDX_VAL.get(): { + ret = syscall_mem_op_alloc_heap(tls, ext); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + default: { + break; + } + } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; + } +} + +#endif diff --git a/kernel/src/dispatch_syscall_vm_op.hpp b/kernel/src/dispatch_syscall_vm_op.hpp index 5c040a53..573d268d 100644 --- a/kernel/src/dispatch_syscall_vm_op.hpp +++ b/kernel/src/dispatch_syscall_vm_op.hpp @@ -25,109 +25,130 @@ #ifndef DISPATCH_SYSCALL_VM_OP_HPP #define DISPATCH_SYSCALL_VM_OP_HPP -#include +#include +#include +#include +#include +#include +#include #include #include +#include #include #include namespace mk { - namespace details + /// + /// @brief Implements the bf_vm_op_create_vm syscall + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param vm_pool the VM pool to use + /// @param ext_pool the extension pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vm_op_create_vm( + tls_t &tls, page_pool_t &page_pool, vm_pool_t &vm_pool, ext_pool_t &ext_pool) noexcept + -> bsl::errc_type { - /// - /// @brief Implements the bf_vm_op_create_vm syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VM_POOL_CONCEPT defines the type of VM pool to use - /// @param tls the current TLS block - /// @param vm_pool the VM pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vm_op_create_vm(TLS_CONCEPT &tls, VM_POOL_CONCEPT &vm_pool) -> syscall::bf_status_t - { - auto const vmid{vm_pool.allocate()}; - if (bsl::unlikely(!vmid)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - tls.ext_reg0 = bsl::to_umax(vmid).get(); - return syscall::BF_STATUS_SUCCESS; + auto const vmid{vm_pool.allocate(tls, page_pool, ext_pool)}; + if (bsl::unlikely(!vmid)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; } - /// - /// @brief Implements the bf_vm_op_destroy_vm syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VM_POOL_CONCEPT defines the type of VM pool to use - /// @param tls the current TLS block - /// @param vm_pool the VM pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vm_op_destroy_vm(TLS_CONCEPT &tls, VM_POOL_CONCEPT &vm_pool) -> syscall::bf_status_t - { - if (bsl::unlikely(!vm_pool.deallocate(bsl::to_u16_unsafe(tls.ext_reg1)))) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } + constexpr auto mask{0xFFFFFFFFFFFF0000_umax}; + tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(vmid)).get(); - return syscall::BF_STATUS_SUCCESS; + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vm_op_destroy_vm syscall + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param vm_pool the VM pool to use + /// @param vp_pool the VP pool to use + /// @param ext_pool the extension pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vm_op_destroy_vm( + tls_t &tls, + page_pool_t &page_pool, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + ext_pool_t &ext_pool) noexcept -> bsl::errc_type + { + auto const vmid{bsl::to_u16_unsafe(tls.ext_reg1)}; + auto const ret{vm_pool.deallocate(tls, page_pool, vp_pool, ext_pool, vmid)}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } /// /// @brief Dispatches the bf_vm_op syscalls /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @tparam VM_POOL_CONCEPT defines the type of VM pool to use /// @param tls the current TLS block - /// @param ext the extension that made the syscall + /// @param page_pool the page pool to use /// @param vm_pool the VM pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. + /// @param vp_pool the VM pool to use + /// @param ext_pool the extension pool to use + /// @param ext the extension that made the syscall + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise /// - template [[nodiscard]] constexpr auto - dispatch_syscall_vm_op(TLS_CONCEPT &tls, EXT_CONCEPT const &ext, VM_POOL_CONCEPT &vm_pool) - -> syscall::bf_status_t + dispatch_syscall_vm_op( + tls_t &tls, + page_pool_t &page_pool, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + ext_pool_t &ext_pool, + ext_t &ext) -> bsl::errc_type { - syscall::bf_status_t ret{}; + bsl::errc_type ret{}; if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { - bsl::error() << "invalid handle: " // -- + bsl::error() << "invalid handle " // -- << bsl::hex(tls.ext_reg0) // -- << bsl::endl // -- << bsl::here(); // -- - return syscall::BF_STATUS_FAILURE_INVALID_HANDLE; + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_INVALID_HANDLE.get(); + return bsl::errc_failure; } if (bsl::unlikely(tls.ext != tls.ext_vmexit)) { - bsl::error() << "vm_ops not allowed by ext " // -- + bsl::error() << "vm ops are not allowed by ext " // -- << bsl::hex(ext.id()) // -- << " as it didn't register for vmexits" // -- << bsl::endl // -- << bsl::here(); // -- - return syscall::BF_STATUS_FAILURE_UNKNOWN; + tls.syscall_ret_status = syscall::BF_STATUS_INVALID_PERM_EXT.get(); + return bsl::errc_failure; } switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { case syscall::BF_VM_OP_CREATE_VM_IDX_VAL.get(): { - ret = details::syscall_vm_op_create_vm(tls, vm_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vm_op_create_vm(tls, page_pool, vm_pool, ext_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -136,8 +157,8 @@ namespace mk } case syscall::BF_VM_OP_DESTROY_VM_IDX_VAL.get(): { - ret = details::syscall_vm_op_destroy_vm(tls, vm_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vm_op_destroy_vm(tls, page_pool, vm_pool, vp_pool, ext_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -146,14 +167,17 @@ namespace mk } default: { - bsl::error() << "unknown syscall index: " //-- - << bsl::hex(tls.ext_syscall) //-- - << bsl::endl //-- - << bsl::here(); //-- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; + break; } } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; } } diff --git a/kernel/src/dispatch_syscall_vm_op_failure.hpp b/kernel/src/dispatch_syscall_vm_op_failure.hpp new file mode 100644 index 00000000..c36b4375 --- /dev/null +++ b/kernel/src/dispatch_syscall_vm_op_failure.hpp @@ -0,0 +1,152 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_SYSCALL_VM_OP_FAILURE_HPP +#define DISPATCH_SYSCALL_VM_OP_FAILURE_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Implements the bf_vm_op_create_vm syscall + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param vm_pool the VM pool to use + /// @param vp_pool the VP pool to use + /// @param ext_pool the extension pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vm_op_create_vm_failure( + tls_t &tls, + page_pool_t &page_pool, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + ext_pool_t &ext_pool) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + if (!tls.state_reversal_required) { + return bsl::errc_success; + } + + ret = vm_pool.deallocate(tls, page_pool, vp_pool, ext_pool, tls.log_vmid); + if (bsl::unlikely(!bsl::success_or_precondition(ret))) { + bsl::print() << bsl::here(); + return ret; + } + + ret = ext_pool.signal_vm_destroyed(tls, page_pool, tls.log_vmid); + if (bsl::unlikely(!bsl::success_or_precondition(ret))) { + bsl::print() << bsl::here(); + return ret; + } + + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vm_op_destroy_vm syscall + /// + /// + /// @param tls the current TLS block + /// @param vm_pool the VM pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vm_op_destroy_vm_failure(tls_t &tls, vm_pool_t &vm_pool) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + if (!tls.state_reversal_required) { + return bsl::errc_success; + } + + ret = vm_pool.zombify(bsl::to_u16_unsafe(tls.ext_reg1)); + if (bsl::unlikely(!bsl::success_or_precondition(ret))) { + bsl::print() << bsl::here(); + return ret; + } + + return bsl::errc_success; + } + + /// + /// @brief Dispatches the bf_vm_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param vm_pool the VM pool to use + /// @param vp_pool the VM pool to use + /// @param ext_pool the extension pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + dispatch_syscall_vm_op_failure( + tls_t &tls, + page_pool_t &page_pool, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + ext_pool_t &ext_pool) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { + case syscall::BF_VM_OP_CREATE_VM_IDX_VAL.get(): { + ret = syscall_vm_op_create_vm_failure(tls, page_pool, vm_pool, vp_pool, ext_pool); + return ret; + } + + case syscall::BF_VM_OP_DESTROY_VM_IDX_VAL.get(): { + ret = syscall_vm_op_destroy_vm_failure(tls, vm_pool); + return ret; + } + + default: { + break; + } + } + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/src/dispatch_syscall_vp_op.hpp b/kernel/src/dispatch_syscall_vp_op.hpp index 4ea84e94..6279b1ce 100644 --- a/kernel/src/dispatch_syscall_vp_op.hpp +++ b/kernel/src/dispatch_syscall_vp_op.hpp @@ -25,7 +25,11 @@ #ifndef DISPATCH_SYSCALL_VP_OP_HPP #define DISPATCH_SYSCALL_VP_OP_HPP -#include +#include +#include +#include +#include +#include #include #include @@ -34,100 +38,123 @@ namespace mk { - namespace details + /// + /// @brief Implements the bf_vp_op_create_vp syscall + /// + /// + /// @param tls the current TLS block + /// @param vp_pool the VP pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vp_op_create_vp(tls_t &tls, vp_pool_t &vp_pool) noexcept -> bsl::errc_type { - /// - /// @brief Implements the bf_vp_op_create_vp syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VP_POOL_CONCEPT defines the type of VP pool to use - /// @param tls the current TLS block - /// @param vp_pool the VP pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vp_op_create_vp(TLS_CONCEPT &tls, VP_POOL_CONCEPT &vp_pool) -> syscall::bf_status_t - { - auto const vpid{vp_pool.allocate()}; - if (bsl::unlikely(!vpid)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } + auto const vpid{vp_pool.allocate( + tls, bsl::to_u16_unsafe(tls.ext_reg1), bsl::to_u16_unsafe(tls.ext_reg2))}; - tls.ext_reg0 = bsl::to_umax(vpid).get(); - return syscall::BF_STATUS_SUCCESS; + if (bsl::unlikely(!vpid)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; } - /// - /// @brief Implements the bf_vp_op_destroy_vp syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VP_POOL_CONCEPT defines the type of VP pool to use - /// @param tls the current TLS block - /// @param vp_pool the VP pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vp_op_destroy_vp(TLS_CONCEPT &tls, VP_POOL_CONCEPT &vp_pool) -> syscall::bf_status_t - { - if (bsl::unlikely(!vp_pool.deallocate(bsl::to_u16_unsafe(tls.ext_reg1)))) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } + constexpr auto mask{0xFFFFFFFFFFFF0000_umax}; + tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(vpid)).get(); - return syscall::BF_STATUS_SUCCESS; + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vp_op_destroy_vp syscall + /// + /// + /// @param tls the current TLS block + /// @param vp_pool the VP pool to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vp_op_destroy_vp(tls_t &tls, vp_pool_t &vp_pool, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const ret{vp_pool.deallocate(tls, vps_pool, bsl::to_u16_unsafe(tls.ext_reg1))}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vp_op_migrate syscall + /// + /// + /// @param tls the current TLS block + /// @param vp_pool the VP pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vp_op_migrate(tls_t &tls, vp_pool_t &vp_pool) noexcept -> bsl::errc_type + { + auto const ret{vp_pool.migrate( + tls, bsl::to_u16_unsafe(tls.ext_reg1), bsl::to_u16_unsafe(tls.ext_reg2))}; + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } /// /// @brief Dispatches the bf_vp_op syscalls /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @tparam VP_POOL_CONCEPT defines the type of VP pool to use /// @param tls the current TLS block /// @param ext the extension that made the syscall /// @param vp_pool the VP pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise /// - template [[nodiscard]] constexpr auto - dispatch_syscall_vp_op(TLS_CONCEPT &tls, EXT_CONCEPT const &ext, VP_POOL_CONCEPT &vp_pool) - -> syscall::bf_status_t + dispatch_syscall_vp_op( + tls_t &tls, vp_pool_t &vp_pool, vps_pool_t &vps_pool, ext_t &ext) noexcept -> bsl::errc_type { - syscall::bf_status_t ret{}; + bsl::errc_type ret{}; if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { - bsl::error() << "invalid handle: " // -- + bsl::error() << "invalid handle " // -- << bsl::hex(tls.ext_reg0) // -- << bsl::endl // -- << bsl::here(); // -- - return syscall::BF_STATUS_FAILURE_INVALID_HANDLE; + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_INVALID_HANDLE.get(); + return bsl::errc_failure; } if (bsl::unlikely(tls.ext != tls.ext_vmexit)) { - bsl::error() << "vp_ops not allowed by ext " // -- + bsl::error() << "vp ops are not allowed by ext " // -- << bsl::hex(ext.id()) // -- << " as it didn't register for vmexits" // -- << bsl::endl // -- << bsl::here(); // -- - return syscall::BF_STATUS_FAILURE_UNKNOWN; + tls.syscall_ret_status = syscall::BF_STATUS_INVALID_PERM_EXT.get(); + return bsl::errc_failure; } switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { case syscall::BF_VP_OP_CREATE_VP_IDX_VAL.get(): { - ret = details::syscall_vp_op_create_vp(tls, vp_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vp_op_create_vp(tls, vp_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -136,8 +163,18 @@ namespace mk } case syscall::BF_VP_OP_DESTROY_VP_IDX_VAL.get(): { - ret = details::syscall_vp_op_destroy_vp(tls, vp_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vp_op_destroy_vp(tls, vp_pool, vps_pool); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_VP_OP_MIGRATE_IDX_VAL.get(): { + ret = syscall_vp_op_migrate(tls, vp_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -146,14 +183,17 @@ namespace mk } default: { - bsl::error() << "unknown syscall index: " //-- - << bsl::hex(tls.ext_syscall) //-- - << bsl::endl //-- - << bsl::here(); //-- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; + break; } } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; } } diff --git a/kernel/src/dispatch_syscall_vp_op_failure.hpp b/kernel/src/dispatch_syscall_vp_op_failure.hpp new file mode 100644 index 00000000..4056091b --- /dev/null +++ b/kernel/src/dispatch_syscall_vp_op_failure.hpp @@ -0,0 +1,136 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_SYSCALL_VP_OP_FAILURE_HPP +#define DISPATCH_SYSCALL_VP_OP_FAILURE_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Implements the bf_vp_op_create_vp syscall + /// + /// + /// @param tls the current TLS block + /// @param vp_pool the VP pool to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vp_op_create_vp_failure(tls_t &tls, vp_pool_t &vp_pool, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + bsl::errc_type ret{}; + + if (!tls.state_reversal_required) { + return bsl::errc_success; + } + + ret = vp_pool.deallocate(tls, vps_pool, tls.log_vpid); + if (bsl::unlikely(!bsl::success_or_precondition(ret))) { + bsl::print() << bsl::here(); + return ret; + } + + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vp_op_destroy_vp syscall + /// + /// + /// @param tls the current TLS block + /// @param vp_pool the VP pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vp_op_destroy_vp_failure(tls_t &tls, vp_pool_t &vp_pool) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + if (!tls.state_reversal_required) { + return bsl::errc_success; + } + + ret = vp_pool.zombify(bsl::to_u16_unsafe(tls.ext_reg1)); + if (bsl::unlikely(!bsl::success_or_precondition(ret))) { + bsl::print() << bsl::here(); + return ret; + } + + return bsl::errc_success; + } + + /// + /// @brief Dispatches the bf_vp_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param vp_pool the VP pool to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + dispatch_syscall_vp_op_failure(tls_t &tls, vp_pool_t &vp_pool, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + bsl::errc_type ret{}; + + switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { + case syscall::BF_VP_OP_CREATE_VP_IDX_VAL.get(): { + ret = syscall_vp_op_create_vp_failure(tls, vp_pool, vps_pool); + return ret; + } + + case syscall::BF_VP_OP_DESTROY_VP_IDX_VAL.get(): { + ret = syscall_vp_op_destroy_vp_failure(tls, vp_pool); + return ret; + } + + case syscall::BF_VP_OP_MIGRATE_IDX_VAL.get(): { + break; + } + + default: { + break; + } + } + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/src/dispatch_syscall_vps_op.hpp b/kernel/src/dispatch_syscall_vps_op.hpp index dc8b7ec0..954b25ea 100644 --- a/kernel/src/dispatch_syscall_vps_op.hpp +++ b/kernel/src/dispatch_syscall_vps_op.hpp @@ -25,541 +25,749 @@ #ifndef DISPATCH_SYSCALL_VPS_OP_HPP #define DISPATCH_SYSCALL_VPS_OP_HPP -#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include #include +#include #include #include namespace mk { - namespace details + /// + /// @brief Implements the bf_vps_op_create_vps syscall + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_create_vps( + tls_t &tls, page_pool_t &page_pool, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type { - /// - /// @brief Implements the bf_vps_op_create_vps syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_create_vps(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) - -> syscall::bf_status_t - { - auto const vpsid{vps_pool.allocate(tls)}; - if (bsl::unlikely(!vpsid)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } + auto const vpsid{vps_pool.allocate( + tls, + page_pool, + intrinsic, + bsl::to_u16_unsafe(tls.ext_reg1), + bsl::to_u16_unsafe(tls.ext_reg2))}; - tls.ext_reg0 = bsl::to_umax(vpsid).get(); - return syscall::BF_STATUS_SUCCESS; + if (bsl::unlikely(!vpsid)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; } - /// - /// @brief Implements the bf_vps_op_destroy_vps syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_destroy_vps(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) - -> syscall::bf_status_t - { - if (bsl::unlikely(!vps_pool.deallocate(bsl::to_u16_unsafe(tls.ext_reg1)))) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } + constexpr auto mask{0xFFFFFFFFFFFF0000_umax}; + tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(vpsid)).get(); - return syscall::BF_STATUS_SUCCESS; + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_destroy_vps syscall + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_destroy_vps(tls_t &tls, page_pool_t &page_pool, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const ret{vps_pool.deallocate(tls, page_pool, bsl::to_u16_unsafe(tls.ext_reg1))}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; } - /// - /// @brief Implements the bf_vps_op_init_as_root syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_init_as_root(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) - -> syscall::bf_status_t - { - auto const ret{vps_pool.state_save_to_vps( - tls, bsl::to_u16_unsafe(tls.ext_reg1), tls.root_vp_state)}; + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + /// + /// @brief Implements the bf_vps_op_init_as_root syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_init_as_root(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const ret{vps_pool.state_save_to_vps( + tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), *tls.root_vp_state)}; + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_read8 syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_read8(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const val{vps_pool.template read( + tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + + if (bsl::unlikely(!val)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + constexpr auto mask{0xFFFFFFFFFFFFFF00_umax}; + tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(val)).get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_read16 syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_read16(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const val{vps_pool.template read( + tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + + if (bsl::unlikely(!val)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + constexpr auto mask{0xFFFFFFFFFFFF0000_umax}; + tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(val)).get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_read32 syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_read32(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const val{vps_pool.template read( + tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + + if (bsl::unlikely(!val)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + constexpr auto mask{0xFFFFFFFFFFFFFF00_umax}; + tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(val)).get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_read64 syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_read64(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const val{vps_pool.template read( + tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + + if (bsl::unlikely(!val)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.ext_reg0 = val.get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_write8 syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_write8(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const ret{vps_pool.template write( + tls, + intrinsic, + bsl::to_u16_unsafe(tls.ext_reg1), + tls.ext_reg2, + bsl::to_u8_unsafe(tls.ext_reg3))}; + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_write16 syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_write16(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const ret{vps_pool.template write( + tls, + intrinsic, + bsl::to_u16_unsafe(tls.ext_reg1), + tls.ext_reg2, + bsl::to_u16_unsafe(tls.ext_reg3))}; + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_write32 syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_write32(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const ret{vps_pool.template write( + tls, + intrinsic, + bsl::to_u16_unsafe(tls.ext_reg1), + tls.ext_reg2, + bsl::to_u32_unsafe(tls.ext_reg3))}; + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_write64 syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_write64(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const ret{vps_pool.template write( + tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2, tls.ext_reg3)}; + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_read_reg syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_read_reg(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const val{vps_pool.read_reg( + tls, + intrinsic, + bsl::to_u16_unsafe(tls.ext_reg1), + static_cast(tls.ext_reg2))}; + + if (bsl::unlikely(!val)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.ext_reg0 = val.get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_write_reg syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_write_reg(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const ret{vps_pool.write_reg( + tls, + intrinsic, + bsl::to_u16_unsafe(tls.ext_reg1), + static_cast(tls.ext_reg2), + tls.ext_reg3)}; + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_run syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vm_pool the VM pool to use + /// @param vp_pool the VP pool to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_run( + tls_t &tls, + intrinsic_t &intrinsic, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + // --------------------------------------------------------------------- + // Gather Arguments + // --------------------------------------------------------------------- + + auto const vmid{bsl::to_u16_unsafe(tls.ext_reg1)}; + if (bsl::unlikely(syscall::BF_INVALID_ID == vmid)) { + bsl::error() << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid" // -- + << bsl::endl // -- + << bsl::here(); // -- + + tls.syscall_ret_status = syscall::BF_STATUS_INVALID_PARAMS1.get(); + return bsl::errc_failure; + } + + auto const vpid{bsl::to_u16_unsafe(tls.ext_reg2)}; + if (bsl::unlikely(syscall::BF_INVALID_ID == vpid)) { + bsl::error() << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid" // -- + << bsl::endl // -- + << bsl::here(); // -- + + tls.syscall_ret_status = syscall::BF_STATUS_INVALID_PARAMS2.get(); + return bsl::errc_failure; + } + + auto const vpsid{bsl::to_u16_unsafe(tls.ext_reg3)}; + if (bsl::unlikely(syscall::BF_INVALID_ID == vpsid)) { + bsl::error() << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid" // -- + << bsl::endl // -- + << bsl::here(); // -- + + tls.syscall_ret_status = syscall::BF_STATUS_INVALID_PARAMS3.get(); + return bsl::errc_failure; + } + + // --------------------------------------------------------------------- + // Validate Assignment + // --------------------------------------------------------------------- + + /// TODO: + /// - Add assignment checks here + + // --------------------------------------------------------------------- + // Migrate + // --------------------------------------------------------------------- + + /// TODO: + /// - Add migration here + + // --------------------------------------------------------------------- + // Activate VM + // --------------------------------------------------------------------- + + if (tls.active_vmid != vmid) { + if (syscall::BF_INVALID_ID != tls.active_vmid) { + ret = vm_pool.set_inactive(tls, tls.active_vmid); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + ret = vm_pool.set_active(tls, vmid); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; + return ret; } - return syscall::BF_STATUS_SUCCESS; + bsl::touch(); + } + else { + bsl::touch(); } - /// - /// @brief Implements the bf_vps_op_read8 syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_read8(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) -> syscall::bf_status_t - { - auto const ret{vps_pool.template read( - tls, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + // --------------------------------------------------------------------- + // Activate VP + // --------------------------------------------------------------------- + if (tls.active_vpid != vpid) { + if (syscall::BF_INVALID_ID != tls.active_vpid) { + ret = vp_pool.set_inactive(tls, tls.active_vpid); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + ret = vp_pool.set_active(tls, vpid); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; + return ret; } - constexpr bsl::safe_uintmax mask{0xFFFFFFFFFFFFFF00}; - tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(ret)).get(); - return syscall::BF_STATUS_SUCCESS; + bsl::touch(); + } + else { + bsl::touch(); } - /// - /// @brief Implements the bf_vps_op_read16 syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_read16(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) -> syscall::bf_status_t - { - auto const ret{vps_pool.template read( - tls, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + // --------------------------------------------------------------------- + // Activate VPS + // --------------------------------------------------------------------- + if (tls.active_vpsid != vpsid) { + if (syscall::BF_INVALID_ID != tls.active_vpsid) { + ret = vps_pool.set_inactive(tls, intrinsic, tls.active_vpsid); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + ret = vps_pool.set_active(tls, intrinsic, vpsid); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; + return ret; } - constexpr bsl::safe_uintmax mask{0xFFFFFFFFFFFF0000}; - tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(ret)).get(); - return syscall::BF_STATUS_SUCCESS; + bsl::touch(); + } + else { + bsl::touch(); } - /// - /// @brief Implements the bf_vps_op_read32 syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_read32(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) -> syscall::bf_status_t - { - auto const ret{vps_pool.template read( - tls, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + // --------------------------------------------------------------------- + // Done + // --------------------------------------------------------------------- - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } + return_to_mk(bsl::exit_success); - constexpr bsl::safe_uintmax mask{0xFFFFFFFF00000000}; - tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(ret)).get(); - return syscall::BF_STATUS_SUCCESS; + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_run_current syscall + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] inline auto + syscall_vps_op_run_current(tls_t &tls) noexcept -> bsl::errc_type + { + return_to_mk(bsl::exit_success); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_advance_ip syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_advance_ip(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const ret{vps_pool.advance_ip(tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1))}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; } - /// - /// @brief Implements the bf_vps_op_read64 syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_read64(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) -> syscall::bf_status_t - { - auto const ret{vps_pool.template read( - tls, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - tls.ext_reg0 = ret.get(); - return syscall::BF_STATUS_SUCCESS; + /// + /// @brief Implements the bf_vps_op_advance_ip_and_run_current syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_advance_ip_and_run_current( + tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + auto const ret{vps_pool.advance_ip(tls, intrinsic, tls.active_vpsid)}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; } - /// - /// @brief Implements the bf_vps_op_write8 syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_write8(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) -> syscall::bf_status_t - { - auto const ret{vps_pool.template write( - tls, - bsl::to_u16_unsafe(tls.ext_reg1), - tls.ext_reg2, - bsl::to_u8_unsafe(tls.ext_reg3))}; + return_to_mk(bsl::exit_success); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } - return syscall::BF_STATUS_SUCCESS; + /// + /// @brief Implements the bf_vps_op_promote syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_promote(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const ret{vps_pool.vps_to_state_save( + tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), *tls.root_vp_state)}; + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; } - /// - /// @brief Implements the bf_vps_op_write16 syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_write16(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) -> syscall::bf_status_t - { - auto const ret{vps_pool.template write( - tls, - bsl::to_u16_unsafe(tls.ext_reg1), - tls.ext_reg2, - bsl::to_u16_unsafe(tls.ext_reg3))}; + promote(tls.root_vp_state); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } - return syscall::BF_STATUS_SUCCESS; + /// + /// @brief Implements the bf_vps_op_clear_vps syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_clear_vps(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type + { + auto const ret{vps_pool.clear(tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1))}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; } - /// - /// @brief Implements the bf_vps_op_write32 syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_write32(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) -> syscall::bf_status_t - { - auto const ret{vps_pool.template write( - tls, - bsl::to_u16_unsafe(tls.ext_reg1), - tls.ext_reg2, - bsl::to_u32_unsafe(tls.ext_reg3))}; - - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - return syscall::BF_STATUS_SUCCESS; - } - - /// - /// @brief Implements the bf_vps_op_write64 syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_write64(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) -> syscall::bf_status_t - { - auto const ret{vps_pool.template write( - tls, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2, tls.ext_reg3)}; - - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - return syscall::BF_STATUS_SUCCESS; - } - - /// - /// @brief Implements the bf_vps_op_read_reg syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_read_reg(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) - -> syscall::bf_status_t - { - auto const ret{vps_pool.read_reg( - tls, - bsl::to_u16_unsafe(tls.ext_reg1), - static_cast(tls.ext_reg2))}; - - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - tls.ext_reg0 = ret.get(); - return syscall::BF_STATUS_SUCCESS; - } - - /// - /// @brief Implements the bf_vps_op_write_reg syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_write_reg(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) - -> syscall::bf_status_t - { - auto const ret{vps_pool.write_reg( - tls, - bsl::to_u16_unsafe(tls.ext_reg1), - static_cast(tls.ext_reg2), - tls.ext_reg3)}; - - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - return syscall::BF_STATUS_SUCCESS; - } - - /// - /// @brief Implements the bf_vps_op_run syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @param tls the current TLS block - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_run(TLS_CONCEPT &tls) -> syscall::bf_status_t - { - tls.active_vpsid = bsl::to_u16_unsafe(tls.ext_reg1).get(); - tls.set_vpid(bsl::to_u16_unsafe(tls.ext_reg2)); - tls.set_vmid(bsl::to_u16_unsafe(tls.ext_reg3)); - - /// TODO: - /// - Need to validate that the IDs are valid. Since this will - /// not be executed often, we can afford to check. - /// - - return_to_mk(bsl::ZERO_UMAX.get()); - return syscall::BF_STATUS_SUCCESS; - } - - /// - /// @brief Implements the bf_vps_op_run_current syscall - /// - /// - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - [[nodiscard]] inline auto - syscall_vps_op_run_current() -> syscall::bf_status_t - { - return_to_mk(bsl::ZERO_UMAX.get()); - return syscall::BF_STATUS_SUCCESS; - } - - /// - /// @brief Implements the bf_vps_op_advance_ip syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_advance_ip(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) - -> syscall::bf_status_t - { - auto const ret{vps_pool.advance_ip(tls, bsl::to_u16_unsafe(tls.ext_reg1))}; - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - return syscall::BF_STATUS_SUCCESS; - } - - /// - /// @brief Implements the bf_vps_op_advance_ip_and_run_current syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_advance_ip_and_run_current(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) - -> syscall::bf_status_t - { - auto const ret{vps_pool.advance_ip(tls, tls.active_vpsid)}; - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - return_to_mk(bsl::ZERO_UMAX.get()); - return syscall::BF_STATUS_SUCCESS; - } - - /// - /// @brief Implements the bf_vps_op_promote syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @param tls the current TLS block - /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_vps_op_promote(TLS_CONCEPT &tls, VPS_POOL_CONCEPT &vps_pool) -> syscall::bf_status_t - { - auto const ret{vps_pool.vps_to_state_save( - tls, bsl::to_u16_unsafe(tls.ext_reg1), tls.root_vp_state)}; - - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - promote(tls.root_vp_state); - return syscall::BF_STATUS_SUCCESS; - } + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; } /// /// @brief Dispatches the bf_vps_op syscalls /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use /// @param tls the current TLS block /// @param ext the extension that made the syscall + /// @param intrinsic the intrinsics to use + /// @param page_pool the page pool to use + /// @param vm_pool the VM pool to use + /// @param vp_pool the VP pool to use /// @param vps_pool the VPS pool to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise /// - template [[nodiscard]] constexpr auto - dispatch_syscall_vps_op(TLS_CONCEPT &tls, EXT_CONCEPT const &ext, VPS_POOL_CONCEPT &vps_pool) - -> syscall::bf_status_t + dispatch_syscall_vps_op( + tls_t &tls, + page_pool_t &page_pool, + intrinsic_t &intrinsic, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + ext_t &ext) noexcept -> bsl::errc_type { - syscall::bf_status_t ret{}; + bsl::errc_type ret{}; if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { - bsl::error() << "invalid handle: " // -- + bsl::error() << "invalid handle " // -- << bsl::hex(tls.ext_reg0) // -- << bsl::endl // -- << bsl::here(); // -- - return syscall::BF_STATUS_FAILURE_INVALID_HANDLE; + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_INVALID_HANDLE.get(); + return bsl::errc_failure; } if (bsl::unlikely(tls.ext != tls.ext_vmexit)) { - bsl::error() << "vps_ops not allowed by ext " // -- + bsl::error() << "vps ops are not allowed by ext " // -- << bsl::hex(ext.id()) // -- << " as it didn't register for vmexits" // -- << bsl::endl // -- << bsl::here(); // -- - return syscall::BF_STATUS_FAILURE_UNKNOWN; + tls.syscall_ret_status = syscall::BF_STATUS_INVALID_PERM_EXT.get(); + return bsl::errc_failure; } switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { case syscall::BF_VPS_OP_CREATE_VPS_IDX_VAL.get(): { - ret = details::syscall_vps_op_create_vps(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_create_vps(tls, page_pool, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -568,8 +776,8 @@ namespace mk } case syscall::BF_VPS_OP_DESTROY_VPS_IDX_VAL.get(): { - ret = details::syscall_vps_op_destroy_vps(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_destroy_vps(tls, page_pool, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -578,8 +786,8 @@ namespace mk } case syscall::BF_VPS_OP_INIT_AS_ROOT_IDX_VAL.get(): { - ret = details::syscall_vps_op_init_as_root(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_init_as_root(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -588,8 +796,8 @@ namespace mk } case syscall::BF_VPS_OP_READ8_IDX_VAL.get(): { - ret = details::syscall_vps_op_read8(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_read8(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -598,8 +806,8 @@ namespace mk } case syscall::BF_VPS_OP_READ16_IDX_VAL.get(): { - ret = details::syscall_vps_op_read16(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_read16(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -608,8 +816,8 @@ namespace mk } case syscall::BF_VPS_OP_READ32_IDX_VAL.get(): { - ret = details::syscall_vps_op_read32(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_read32(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -618,8 +826,8 @@ namespace mk } case syscall::BF_VPS_OP_READ64_IDX_VAL.get(): { - ret = details::syscall_vps_op_read64(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_read64(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -628,8 +836,8 @@ namespace mk } case syscall::BF_VPS_OP_WRITE8_IDX_VAL.get(): { - ret = details::syscall_vps_op_write8(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_write8(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -638,8 +846,8 @@ namespace mk } case syscall::BF_VPS_OP_WRITE16_IDX_VAL.get(): { - ret = details::syscall_vps_op_write16(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_write16(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -648,8 +856,8 @@ namespace mk } case syscall::BF_VPS_OP_WRITE32_IDX_VAL.get(): { - ret = details::syscall_vps_op_write32(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_write32(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -658,8 +866,8 @@ namespace mk } case syscall::BF_VPS_OP_WRITE64_IDX_VAL.get(): { - ret = details::syscall_vps_op_write64(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_write64(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -668,8 +876,8 @@ namespace mk } case syscall::BF_VPS_OP_READ_REG_IDX_VAL.get(): { - ret = details::syscall_vps_op_read_reg(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_read_reg(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -678,8 +886,8 @@ namespace mk } case syscall::BF_VPS_OP_WRITE_REG_IDX_VAL.get(): { - ret = details::syscall_vps_op_write_reg(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_write_reg(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -688,8 +896,8 @@ namespace mk } case syscall::BF_VPS_OP_RUN_IDX_VAL.get(): { - ret = details::syscall_vps_op_run(tls); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_run(tls, intrinsic, vm_pool, vp_pool, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -698,8 +906,8 @@ namespace mk } case syscall::BF_VPS_OP_RUN_CURRENT_IDX_VAL.get(): { - ret = details::syscall_vps_op_run_current(); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_run_current(tls); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -708,8 +916,8 @@ namespace mk } case syscall::BF_VPS_OP_ADVANCE_IP_IDX_VAL.get(): { - ret = details::syscall_vps_op_advance_ip(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_advance_ip(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -718,8 +926,8 @@ namespace mk } case syscall::BF_VPS_OP_ADVANCE_IP_AND_RUN_CURRENT_IDX_VAL.get(): { - ret = details::syscall_vps_op_advance_ip_and_run_current(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_advance_ip_and_run_current(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -728,8 +936,18 @@ namespace mk } case syscall::BF_VPS_OP_PROMOTE_IDX_VAL.get(): { - ret = details::syscall_vps_op_promote(tls, vps_pool); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { + ret = syscall_vps_op_promote(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_VPS_OP_CLEAR_VPS_IDX_VAL.get(): { + ret = syscall_vps_op_clear_vps(tls, intrinsic, vps_pool); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -738,14 +956,17 @@ namespace mk } default: { - bsl::error() << "unknown syscall index: " //-- - << bsl::hex(tls.ext_syscall) //-- - << bsl::endl //-- - << bsl::here(); //-- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; + break; } } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; } } diff --git a/kernel/src/dispatch_syscall_vps_op_failure.hpp b/kernel/src/dispatch_syscall_vps_op_failure.hpp new file mode 100644 index 00000000..6fb2f718 --- /dev/null +++ b/kernel/src/dispatch_syscall_vps_op_failure.hpp @@ -0,0 +1,868 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_SYSCALL_VPS_FAILURE_OP_HPP +#define DISPATCH_SYSCALL_VPS_FAILURE_OP_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Implements the bf_vps_op_create_vps syscall + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_create_vps_failure( + tls_t &tls, page_pool_t &page_pool, vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + if (!tls.state_reversal_required) { + return bsl::errc_success; + } + + ret = vps_pool.deallocate(tls, page_pool, tls.log_vpsid); + if (bsl::unlikely(!bsl::success_or_precondition(ret))) { + bsl::print() << bsl::here(); + return ret; + } + + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_vps_op_destroy_vps syscall + /// + /// + /// @param tls the current TLS block + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + syscall_vps_op_destroy_vps_failure(tls_t &tls, vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + if (!tls.state_reversal_required) { + return bsl::errc_success; + } + + ret = vps_pool.zombify(bsl::to_u16_unsafe(tls.ext_reg1)); + if (bsl::unlikely(!bsl::success_or_precondition(ret))) { + bsl::print() << bsl::here(); + return ret; + } + + return bsl::errc_success; + } + + // /// + // /// @brief Implements the bf_vps_op_init_as_root syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_init_as_root_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const ret{vps_pool.state_save_to_vps( + // tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), *tls.root_vp_state)}; + + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_read8 syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_read8_failure(tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const val{vps_pool.template read( + // tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + + // if (bsl::unlikely(!val)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // constexpr bsl::safe_uintmax mask{0xFFFFFFFFFFFFFF00U}; + // tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(val)).get(); + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_read16 syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_read16_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const val{vps_pool.template read( + // tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + + // if (bsl::unlikely(!val)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // constexpr bsl::safe_uintmax mask{0xFFFFFFFFFFFF0000U}; + // tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(val)).get(); + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_read32 syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_read32_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const val{vps_pool.template read( + // tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + + // if (bsl::unlikely(!val)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // constexpr bsl::safe_uintmax mask{0xFFFFFFFF00000000U}; + // tls.ext_reg0 = ((tls.ext_reg0 & mask) | bsl::to_umax(val)).get(); + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_read64 syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_read64_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const val{vps_pool.template read( + // tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2)}; + + // if (bsl::unlikely(!val)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // tls.ext_reg0 = val.get(); + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_write8 syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_write8_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const ret{vps_pool.template write( + // tls, + // intrinsic, + // bsl::to_u16_unsafe(tls.ext_reg1), + // tls.ext_reg2, + // bsl::to_u8_unsafe(tls.ext_reg3))}; + + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_write16 syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_write16_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const ret{vps_pool.template write( + // tls, + // intrinsic, + // bsl::to_u16_unsafe(tls.ext_reg1), + // tls.ext_reg2, + // bsl::to_u16_unsafe(tls.ext_reg3))}; + + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_write32 syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_write32_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const ret{vps_pool.template write( + // tls, + // intrinsic, + // bsl::to_u16_unsafe(tls.ext_reg1), + // tls.ext_reg2, + // bsl::to_u32_unsafe(tls.ext_reg3))}; + + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_write64 syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_write64_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const ret{vps_pool.template write( + // tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), tls.ext_reg2, tls.ext_reg3)}; + + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_read_reg syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_read_reg_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const val{vps_pool.read_reg( + // tls, + // intrinsic, + // bsl::to_u16_unsafe(tls.ext_reg1), + // static_cast(tls.ext_reg2))}; + + // if (bsl::unlikely(!val)) { + // bsl::print() << bsl::here(); + // return bsl::errc_failure; + // } + + // tls.ext_reg0 = val.get(); + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_write_reg syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_write_reg_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const ret{vps_pool.write_reg( + // tls, + // intrinsic, + // bsl::to_u16_unsafe(tls.ext_reg1), + // static_cast(tls.ext_reg2), + // tls.ext_reg3)}; + + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_run syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vm_pool the VM pool to use + // /// @param vp_pool the VP pool to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_run_failure( + // tls_t &tls, + // intrinsic_t &intrinsic, + // vm_pool_t &vm_pool, + // vp_pool_t &vp_pool, + // vps_pool_t &vps_pool) noexcept -> bsl::errc_type + // { + // bsl::errc_type ret{}; + + // // --------------------------------------------------------------------- + // // Gather Arguments + // // --------------------------------------------------------------------- + + // auto const vmid{bsl::to_u16_unsafe(tls.ext_reg1)}; + // if (bsl::unlikely(syscall::BF_INVALID_ID == vmid)) { + // bsl::error() << "vmid " // -- + // << bsl::hex(vmid) // -- + // << " is invalid" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // tls.syscall_ret_status = syscall::BF_STATUS_INVALID_PARAMS1.get(); + // return bsl::errc_failure; + // } + + // auto const vpid{bsl::to_u16_unsafe(tls.ext_reg2)}; + // if (bsl::unlikely(syscall::BF_INVALID_ID == vpid)) { + // bsl::error() << "vpid " // -- + // << bsl::hex(vpid) // -- + // << " is invalid" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // tls.syscall_ret_status = syscall::BF_STATUS_INVALID_PARAMS2.get(); + // return bsl::errc_failure; + // } + + // auto const vpsid{bsl::to_u16_unsafe(tls.ext_reg3)}; + // if (bsl::unlikely(syscall::BF_INVALID_ID == vpsid)) { + // bsl::error() << "vpsid " // -- + // << bsl::hex(vpsid) // -- + // << " is invalid" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // tls.syscall_ret_status = syscall::BF_STATUS_INVALID_PARAMS3.get(); + // return bsl::errc_failure; + // } + + // // --------------------------------------------------------------------- + // // Validate Assignment + // // --------------------------------------------------------------------- + + // /// TODO: + // /// - Add assignment checks here + + // // --------------------------------------------------------------------- + // // Migrate + // // --------------------------------------------------------------------- + + // /// TODO: + // /// - Add migration here + + // // --------------------------------------------------------------------- + // // Activate VM + // // --------------------------------------------------------------------- + + // if (tls.active_vmid != vmid) { + // if (syscall::BF_INVALID_ID != tls.active_vmid) { + // ret = vm_pool.set_inactive(tls, tls.active_vmid); + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // bsl::touch(); + // } + // else { + // bsl::touch(); + // } + + // ret = vm_pool.set_active(tls, vmid); + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // bsl::touch(); + // } + // else { + // bsl::touch(); + // } + + // // --------------------------------------------------------------------- + // // Activate VP + // // --------------------------------------------------------------------- + + // if (tls.active_vpid != vpid) { + // if (syscall::BF_INVALID_ID != tls.active_vpid) { + // ret = vp_pool.set_inactive(tls, tls.active_vpid); + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // bsl::touch(); + // } + // else { + // bsl::touch(); + // } + + // ret = vp_pool.set_active(tls, vpid); + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // bsl::touch(); + // } + // else { + // bsl::touch(); + // } + + // // --------------------------------------------------------------------- + // // Activate VPS + // // --------------------------------------------------------------------- + + // if (tls.active_vpsid != vpsid) { + // if (syscall::BF_INVALID_ID != tls.active_vpsid) { + // ret = vps_pool.set_inactive(tls, intrinsic, tls.active_vpsid); + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // bsl::touch(); + // } + // else { + // bsl::touch(); + // } + + // ret = vps_pool.set_active(tls, intrinsic, vpsid); + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // bsl::touch(); + // } + // else { + // bsl::touch(); + // } + + // // --------------------------------------------------------------------- + // // Done + // // --------------------------------------------------------------------- + + // return_to_mk(bsl::exit_success); + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_run_current syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] inline auto + // syscall_vps_op_run_current_failure(tls_t &tls) noexcept -> bsl::errc_type + // { + // return_to_mk(bsl::exit_success); + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_advance_ip syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_advance_ip_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const ret{vps_pool.advance_ip(tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1))}; + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_advance_ip_and_run_current syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_advance_ip_and_run_current_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const ret{vps_pool.advance_ip(tls, intrinsic, tls.active_vpsid)}; + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // return_to_mk(bsl::exit_success); + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_promote syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_promote_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const ret{vps_pool.vps_to_state_save( + // tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1), *tls.root_vp_state)}; + + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // promote(tls.root_vp_state); + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + // /// + // /// @brief Implements the bf_vps_op_clear_vps syscall + // /// + // /// + // /// @param tls the current TLS block + // /// @param intrinsic the intrinsics to use + // /// @param vps_pool the VPS pool to use + // /// @return Returns bsl::errc_success on success, bsl::errc_failure + // /// otherwise + // /// + // [[nodiscard]] constexpr auto + // syscall_vps_op_clear_vps_failure( + // tls_t &tls, intrinsic_t &intrinsic, vps_pool_t &vps_pool) noexcept + // -> bsl::errc_type + // { + // auto const ret{vps_pool.clear(tls, intrinsic, bsl::to_u16_unsafe(tls.ext_reg1))}; + // if (bsl::unlikely(!ret)) { + // bsl::print() << bsl::here(); + // return ret; + // } + + // tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + // return bsl::errc_success; + // } + + /// + /// @brief Dispatches the bf_vps_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @param intrinsic the intrinsics to use + /// @param page_pool the page pool to use + /// @param vm_pool the VM pool to use + /// @param vp_pool the VP pool to use + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + dispatch_syscall_vps_op_failure( + tls_t &tls, + page_pool_t &page_pool, + intrinsic_t &intrinsic, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + ext_t &ext) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + bsl::discard(tls); + bsl::discard(ext); + bsl::discard(intrinsic); + bsl::discard(page_pool); + bsl::discard(vm_pool); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { + case syscall::BF_VPS_OP_CREATE_VPS_IDX_VAL.get(): { + ret = syscall_vps_op_create_vps_failure(tls, page_pool, vps_pool); + return ret; + } + + case syscall::BF_VPS_OP_DESTROY_VPS_IDX_VAL.get(): { + ret = syscall_vps_op_destroy_vps_failure(tls, vps_pool); + return ret; + } + + // case syscall::BF_VPS_OP_INIT_AS_ROOT_IDX_VAL.get(): { + // ret = syscall_vps_op_init_as_root_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_READ8_IDX_VAL.get(): { + // ret = syscall_vps_op_read8_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_READ16_IDX_VAL.get(): { + // ret = syscall_vps_op_read16_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_READ32_IDX_VAL.get(): { + // ret = syscall_vps_op_read32_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_READ64_IDX_VAL.get(): { + // ret = syscall_vps_op_read64_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_WRITE8_IDX_VAL.get(): { + // ret = syscall_vps_op_write8_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_WRITE16_IDX_VAL.get(): { + // ret = syscall_vps_op_write16_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_WRITE32_IDX_VAL.get(): { + // ret = syscall_vps_op_write32_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_WRITE64_IDX_VAL.get(): { + // ret = syscall_vps_op_write64_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_READ_REG_IDX_VAL.get(): { + // ret = syscall_vps_op_read_reg_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_WRITE_REG_IDX_VAL.get(): { + // ret = syscall_vps_op_write_reg_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_RUN_IDX_VAL.get(): { + // ret = syscall_vps_op_run_failure(tls, intrinsic, vm_pool, vp_pool, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_RUN_CURRENT_IDX_VAL.get(): { + // ret = syscall_vps_op_run_current_failure(tls); + // return ret; + // } + + // case syscall::BF_VPS_OP_ADVANCE_IP_IDX_VAL.get(): { + // ret = syscall_vps_op_advance_ip_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_ADVANCE_IP_AND_RUN_CURRENT_IDX_VAL.get(): { + // ret = syscall_vps_op_advance_ip_and_run_current_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_PROMOTE_IDX_VAL.get(): { + // ret = syscall_vps_op_promote_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + // case syscall::BF_VPS_OP_CLEAR_VPS_IDX_VAL.get(): { + // ret = syscall_vps_op_clear_vps_failure(tls, intrinsic, vps_pool); + // return ret; + // } + + default: { + break; + } + } + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/src/ext_pool_t.hpp b/kernel/src/ext_pool_t.hpp index 17dfc870..3ac0d29f 100644 --- a/kernel/src/ext_pool_t.hpp +++ b/kernel/src/ext_pool_t.hpp @@ -25,6 +25,13 @@ #ifndef EXT_POOL_T_HPP #define EXT_POOL_T_HPP +#include +#include +#include +#include +#include +#include + #include #include #include @@ -39,96 +46,54 @@ namespace mk /// @class mk::ext_pool_t /// /// - /// @brief TODO + /// @brief Defines the microkernel's extension pool /// - /// - /// @tparam EXT_CONCEPT the type of ext_t that this class manages. - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use - /// @tparam ROOT_PAGE_TABLE_CONCEPT defines the type of RPT pool to use - /// @tparam MAX_EXTENSIONS the max number of extensions supported - /// - template< - typename EXT_CONCEPT, - typename INTRINSIC_CONCEPT, - typename PAGE_POOL_CONCEPT, - typename ROOT_PAGE_TABLE_CONCEPT, - bsl::uintmax MAX_EXTENSIONS> class ext_pool_t final { - /// @brief stores a reference to the intrinsics to use - INTRINSIC_CONCEPT &m_intrinsic; - /// @brief stores a reference to the page pool to use - PAGE_POOL_CONCEPT &m_page_pool; - /// @brief stores system RPT provided by the loader - ROOT_PAGE_TABLE_CONCEPT &m_system_rpt; /// @brief stores all of the extensions. - bsl::array m_ext_pool; + bsl::array m_pool{}; public: - /// @brief an alias for EXT_CONCEPT - using ext_type = EXT_CONCEPT; - /// @brief an alias for INTRINSIC_CONCEPT - using intrinsic_type = INTRINSIC_CONCEPT; - /// @brief an alias for PAGE_POOL_CONCEPT - using page_pool_type = PAGE_POOL_CONCEPT; - /// @brief an alias for ROOT_PAGE_TABLE_CONCEPT - using root_page_table_type = ROOT_PAGE_TABLE_CONCEPT; - - /// - /// @brief Creates a ext_pool_t - /// - /// - /// @param intrinsic the intrinsics to use - /// @param page_pool the page pool to use - /// @param system_rpt the system RPT provided by the loader - /// - explicit constexpr ext_pool_t( - INTRINSIC_CONCEPT &intrinsic, - PAGE_POOL_CONCEPT &page_pool, - ROOT_PAGE_TABLE_CONCEPT &system_rpt) noexcept - : m_intrinsic{intrinsic}, m_page_pool{page_pool}, m_system_rpt{system_rpt}, m_ext_pool{} - {} - /// /// @brief Initializes this ext_pool_t /// /// - /// @tparam EXT_ELF_FILES_CONCEPT the type of array containing the - /// ext_elf_files provided by the loader + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param system_rpt the system RPT provided by the loader /// @param ext_elf_files the ext_elf_files provided by the loader - /// @param online_pps the total number of PPs that are online /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - initialize(EXT_ELF_FILES_CONCEPT const &ext_elf_files, bsl::safe_uint16 const &online_pps) - &noexcept -> bsl::errc_type + initialize( + tls_t &tls, + page_pool_t &page_pool, + root_page_table_t &system_rpt, + loader::ext_elf_files_type const &ext_elf_files) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (bsl::unlikely(ext_elf_files.size() != m_ext_pool.size())) { + if (bsl::unlikely(ext_elf_files.size() != m_pool.size())) { bsl::error() << "invalid ext_elf_file\n" << bsl::here(); return bsl::errc_failure; } - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); + bsl::finally release_on_error{[this, &tls, &page_pool]() noexcept -> void { + this->release(tls, page_pool); }}; - for (auto const ext : m_ext_pool) { + for (auto const ext : m_pool) { if (ext_elf_files.at_if(ext.index)->empty()) { break; } ret = ext.data->initialize( - &m_intrinsic, - &m_page_pool, + tls, + page_pool, bsl::to_u16(ext.index), *ext_elf_files.at_if(ext.index), - online_pps, - &m_system_rpt); + system_rpt); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); @@ -145,71 +110,88 @@ namespace mk /// /// @brief Release the ext_pool_t /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// constexpr void - release() &noexcept + release(tls_t &tls, page_pool_t &page_pool) noexcept { - for (auto const ext : m_ext_pool) { - ext.data->release(); + for (auto const ext : m_pool) { + ext.data->release(tls, page_pool); } } /// - /// @brief Destroyes a previously created ext_pool_t - /// - constexpr ~ext_pool_t() noexcept = default; - - /// - /// @brief copy constructor + /// @brief Tells each extension that a VM was created so that it + /// can initialize it's VM specific resources. /// /// - /// @param o the object being copied + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param vmid the VMID of the VM that was created. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise /// - constexpr ext_pool_t(ext_pool_t const &o) noexcept = delete; + [[nodiscard]] constexpr auto + signal_vm_created(tls_t &tls, page_pool_t &page_pool, bsl::safe_uint16 const &vmid) noexcept + -> bsl::errc_type + { + for (auto const ext : m_pool) { + if (bsl::unlikely(!ext.data->signal_vm_created(tls, page_pool, vmid))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + + return bsl::errc_success; + } /// - /// @brief move constructor + /// @brief Tells each extension that a VM was destroyed so that it + /// can release it's VM specific resources. /// /// - /// @param o the object being moved + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param vmid the VMID of the VM that was destroyed. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise /// - constexpr ext_pool_t(ext_pool_t &&o) noexcept = default; + [[nodiscard]] constexpr auto + signal_vm_destroyed( + tls_t &tls, page_pool_t &page_pool, bsl::safe_uint16 const &vmid) noexcept + -> bsl::errc_type + { + for (auto const ext : m_pool) { + if (bsl::unlikely(!ext.data->signal_vm_destroyed(tls, page_pool, vmid))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(ext_pool_t const &o) &noexcept - -> ext_pool_t & = delete; + bsl::touch(); + } - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(ext_pool_t &&o) &noexcept - -> ext_pool_t & = default; + return bsl::errc_success; + } /// /// @brief Starts this ext_pool_t by calling all of the /// extension's _start entry points. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsic_t to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - start(TLS_CONCEPT &tls) &noexcept -> bsl::errc_type + start(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { - for (auto const ext : m_ext_pool) { - if (bsl::unlikely(!ext.data->start(tls))) { + for (auto const ext : m_pool) { + if (bsl::unlikely(!ext.data->start(tls, intrinsic))) { bsl::print() << bsl::here(); return bsl::errc_failure; } @@ -225,17 +207,16 @@ namespace mk /// registered bootstrap callbacks for each extension. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsic_t to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - bootstrap(TLS_CONCEPT &tls) &noexcept -> bsl::errc_type + bootstrap(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { - for (auto const ext : m_ext_pool) { - if (bsl::unlikely(!ext.data->bootstrap(tls))) { + for (auto const ext : m_pool) { + if (bsl::unlikely(!ext.data->bootstrap(tls, intrinsic))) { bsl::print() << bsl::here(); return bsl::errc_failure; } @@ -243,24 +224,36 @@ namespace mk bsl::touch(); } - if (bsl::unlikely(nullptr == tls.ext_vmexit)) { - bsl::error() << "a vmexit handler has not been registered" // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - if (bsl::unlikely(nullptr == tls.ext_fail)) { - bsl::error() << "a fast fail handler has not been registered" // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - return bsl::errc_success; } + + /// + /// @brief Dumps the requested extension + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param extid the ID of the extension to dump + /// + constexpr void + dump(tls_t &tls, page_pool_t &page_pool, bsl::safe_uint16 const &extid) noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + + auto *const ext{m_pool.at_if(bsl::to_umax(extid))}; + if (bsl::unlikely(nullptr == ext)) { + bsl::error() << "invalid extid " // -- + << bsl::hex(extid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return; + } + + ext->dump(tls, page_pool); + } }; } diff --git a/kernel/src/ext_t.hpp b/kernel/src/ext_t.hpp index e34176d3..6739deaf 100644 --- a/kernel/src/ext_t.hpp +++ b/kernel/src/ext_t.hpp @@ -25,108 +25,118 @@ #ifndef EXT_T_HPP #define EXT_T_HPP +#include +#include +#include +#include +#include +#include #include -#include -#include -#include +#include +#include +#include +#include #include -#include +#include +#include +#include +#include +#include #include #include #include +#include + +/// TODO: +/// - Add support for multiple extensions. For this to work, we will need +/// support for PCID and the global flag should be turned off. This will +/// ensure that swaps to another extension (which require a CR3 change), +/// will not destroy performance. To ensure the hypervisor can support +/// systems without PCID, projects that use more than one extension like +/// MicroV should compile the additional extensions into both the main +/// extension, and the additional ones. On systems that don't have PCID, +/// it would call itself. Systems with PCID would call through IPC. You +/// could then have compile/runtime flags for forcing one path over the +/// other in situations where performace or security take precedence. +/// - Since the microkernel doesn't have a timer, the only way another +/// extension will execute is from some sort of IPC interface where an +/// extension calls into another extension to perform an action and then +/// returns a result. The best way to handle this would be to use an +/// instruction sequence similar to a VMCall and VMExit. The extension +/// would execute bf_ipc_op_call, which could take at most 6 arguments +/// that match the SysV calling conventions. The additional extension +/// would execute and then return using bf_ipc_op_return. There would +/// need to be some logic in the syscall code to make sure that this +/// return function was used properly (meaning you cannot return unless +/// you have been called, and you cannot run if you have been called). +/// From there, all that is finally needed is some way to share memory. +/// There are two options here. Shared memory, or a memcpy ABI. IMO, we +/// should use a memcpy ABI as shared memory really complicates things. +/// If shared memory is used, we should make sure, that like freeing a +/// page, unmapping shared memory is optional, meaning the microkernel +/// is nor required to honor the request. +/// - The TLS block that we use for the general purpose registers will need +/// to be shared as it is currently a problem. This way, a swap to another +/// extension only has to update the extension ID in that block, and then +/// swap CR3. The best way to handle this would be to have the extension +/// pool can allocate the shared portion of the TLS blocks for all of the +/// online PPs and then give this page to each extension as it initializes. +/// Then all we have to do is make sure that there is no state in there that +/// would be a problem for the extensions to share, which right now is just +/// the extension ID. If additional state is added to the ABI that is a +/// problem, we will either have to copy the entire block on each swap, +/// or make add a second page to the ABI, one that is shared, and one that +/// is not. namespace mk { - /// @brief defines the value of an invalid EXTID - constexpr bsl::safe_uint16 INVALID_EXTID{bsl::to_u16(0xFFFFU)}; - /// @class mk::ext_t /// /// - /// @brief TODO + /// @brief Defines an extension WRT to the microkernel. Whenever an + /// executes, it must go through this class to do so. This class + /// also maintains all of the resources given to an extension, as + /// well as the extension's memory map, ELF file, stack, TLS blocks, + /// and all of it's memory map functions. /// - /// - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use - /// @tparam ROOT_PAGE_TABLE_CONCEPT defines the type of RPT pool to use - /// @tparam PAGE_SIZE defines the size of a page - /// @tparam MAX_PPS the max number of PPs supported - /// @tparam EXT_STACK_ADDR the address of the extension's stack - /// @tparam EXT_STACK_SIZE the size of the extension's stack - /// @tparam EXT_CODE_ADDR the address of the extension's code - /// @tparam EXT_CODE_SIZE the size of the extension's code - /// @tparam EXT_TLS_ADDR the address of the extension's TLS block - /// @tparam EXT_TLS_SIZE the size of the extension's TLS block - /// @tparam EXT_PAGE_POOL_ADDR the address of the extension's page pool - /// @tparam EXT_PAGE_POOL_SIZE the size of the extension's page pool - /// @tparam EXT_HEAP_POOL_ADDR the address of the extension's heap pool - /// @tparam EXT_HEAP_POOL_SIZE the size of the extension's heap pool - /// - template< - typename INTRINSIC_CONCEPT, - typename PAGE_POOL_CONCEPT, - typename ROOT_PAGE_TABLE_CONCEPT, - bsl::uintmax PAGE_SIZE, - bsl::uintmax MAX_PPS, - bsl::uintmax EXT_STACK_ADDR, - bsl::uintmax EXT_STACK_SIZE, - bsl::uintmax EXT_CODE_ADDR, - bsl::uintmax EXT_CODE_SIZE, - bsl::uintmax EXT_TLS_ADDR, - bsl::uintmax EXT_TLS_SIZE, - bsl::uintmax EXT_PAGE_POOL_ADDR, - bsl::uintmax EXT_PAGE_POOL_SIZE, - bsl::uintmax EXT_HEAP_POOL_ADDR, - bsl::uintmax EXT_HEAP_POOL_SIZE> class ext_t final { - /// @brief stores true if initialized() has been executed - bool m_initialized{}; /// @brief stores true if start() has been executed bool m_started{}; - /// @brief stores true if bootstrap() has been executed - bool m_bootstrapped{}; - /// @brief stores a reference to the intrinsics to use - INTRINSIC_CONCEPT *m_intrinsic{}; - /// @brief stores a reference to the page pool to use - PAGE_POOL_CONCEPT *m_page_pool{}; /// @brief stores the ID associated with this ext_t - bsl::safe_uint16 m_id{bsl::safe_uint16::zero(true)}; - /// @brief stores an extension's ELF file - bsl::span m_elf_file{}; - /// @brief stores the total number of online PPs - bsl::safe_uint16 m_online_pps{bsl::safe_uint16::zero(true)}; - /// @brief stores the root page table for the microkernel. - ROOT_PAGE_TABLE_CONCEPT const *m_system_rpt{}; + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; - /// @brief stores rpt used by main() and bootstrap_ip - ROOT_PAGE_TABLE_CONCEPT m_main_rpt{}; + /// @brief stores the main rpt + root_page_table_t m_main_rpt{}; + /// @brief stores the direct map rpts + bsl::array m_direct_map_rpts{}; /// @brief stores the main IP registered by the extension - bsl::safe_uintmax m_main_ip{bsl::safe_uintmax::zero(true)}; + bsl::safe_uintmax m_entry_ip{bsl::safe_uintmax::failure()}; /// @brief stores the bootstrap IP registered by the extension - bsl::safe_uintmax m_bootstrap_ip{bsl::safe_uintmax::zero(true)}; + bsl::safe_uintmax m_bootstrap_ip{bsl::safe_uintmax::failure()}; /// @brief stores the vmexit IP registered by the extension - bsl::safe_uintmax m_vmexit_ip{bsl::safe_uintmax::zero(true)}; + bsl::safe_uintmax m_vmexit_ip{bsl::safe_uintmax::failure()}; /// @brief stores the fail IP registered by the extension - bsl::safe_uintmax m_fail_ip{bsl::safe_uintmax::zero(true)}; + bsl::safe_uintmax m_fail_ip{bsl::safe_uintmax::failure()}; /// @brief stores the extension's handle - bsl::safe_uintmax m_handle{bsl::safe_uintmax::zero(true)}; - /// @brief stores the extension's page pool cursor - bsl::safe_uintmax m_page_pool_cursor{bsl::to_umax(EXT_PAGE_POOL_ADDR)}; - /// @brief stores the extension's heap pool cursor - bsl::safe_uintmax m_heap_pool_cursor{bsl::to_umax(EXT_HEAP_POOL_ADDR)}; + bsl::safe_uintmax m_handle{bsl::safe_uintmax::failure()}; + /// @brief stores the extension's heap cursor + bsl::safe_uintmax m_heap_crsr{}; /// /// @brief Validates the provided pt_load segment. /// /// /// @param phdr the pt_load segment to validate + /// @param elf_file the ELF file to validate against /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - [[nodiscard]] constexpr auto - validate_pt_load(bfelf::elf64_phdr_t const *const phdr) &noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + validate_pt_load( + bfelf::elf64_phdr_t const *const phdr, + bsl::span const &elf_file) noexcept -> bsl::errc_type { if ((bsl::to_u32(phdr->p_flags) & bfelf::PF_X).is_pos()) { if (bsl::unlikely((bsl::to_u32(phdr->p_flags) & bfelf::PF_W).is_pos())) { @@ -152,34 +162,35 @@ namespace mk bsl::touch(); } - if (bsl::unlikely(bsl::to_umax(phdr->p_offset) > m_elf_file.size())) { + if (bsl::unlikely(bsl::to_umax(phdr->p_offset) > elf_file.size())) { bsl::error() << "ELF code segment offset invalid\n" << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(bsl::to_umax(phdr->p_vaddr) < EXT_CODE_ADDR)) { + if (bsl::unlikely(bsl::to_umax(phdr->p_vaddr) < HYPERVISOR_EXT_CODE_ADDR)) { bsl::error() << "ELF code segment virtual address not supported\n" << bsl::here(); return bsl::errc_failure; } auto const required_memsz{bsl::to_umax(phdr->p_vaddr) + bsl::to_umax(phdr->p_memsz)}; - if (bsl::unlikely(required_memsz > (EXT_CODE_ADDR + EXT_CODE_SIZE))) { + if (bsl::unlikely( + required_memsz > (HYPERVISOR_EXT_CODE_ADDR + HYPERVISOR_EXT_CODE_SIZE))) { bsl::error() << "ELF code segment virtual address not supported\n" << bsl::here(); return bsl::errc_failure; } auto const required_filesz{bsl::to_umax(phdr->p_filesz) + bsl::to_umax(phdr->p_offset)}; - if (bsl::unlikely(required_filesz > m_elf_file.size())) { + if (bsl::unlikely(required_filesz > elf_file.size())) { bsl::error() << "ELF code segment filesz invalid\n" << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(bsl::to_umax(phdr->p_memsz) > EXT_CODE_SIZE)) { + if (bsl::unlikely(bsl::to_umax(phdr->p_memsz) > HYPERVISOR_EXT_CODE_SIZE)) { bsl::error() << "ELF code segment memsz invalid\n" << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(phdr->p_align != PAGE_SIZE)) { + if (bsl::unlikely(phdr->p_align != HYPERVISOR_PAGE_SIZE)) { bsl::error() << "ELF code segment alignment not supported\n" << bsl::here(); return bsl::errc_failure; } @@ -193,10 +204,10 @@ namespace mk /// /// @param phdr the pt_gnu_stack segment to validate /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - [[nodiscard]] constexpr auto - validate_pt_gnu_stack(bfelf::elf64_phdr_t const *const phdr) &noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + validate_pt_gnu_stack(bfelf::elf64_phdr_t const *const phdr) noexcept -> bsl::errc_type { if (bsl::unlikely((bsl::to_u32(phdr->p_flags) & bfelf::PF_X).is_pos())) { bsl::error() << "Executable stacks are not supported\n" << bsl::here(); @@ -211,40 +222,44 @@ namespace mk /// /// /// @param phdr the pt_tls segment to validate + /// @param elf_file the ELF file to validate against /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - [[nodiscard]] constexpr auto - validate_pt_tls(bfelf::elf64_phdr_t const *const phdr) &noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + validate_pt_tls( + bfelf::elf64_phdr_t const *const phdr, + bsl::span const &elf_file) noexcept -> bsl::errc_type { if (bsl::unlikely((bsl::to_u32(phdr->p_flags) & bfelf::PF_X).is_pos())) { bsl::error() << "Executable TLS blocks are not supported\n" << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(bsl::to_umax(phdr->p_offset) > m_elf_file.size())) { + if (bsl::unlikely(bsl::to_umax(phdr->p_offset) > elf_file.size())) { bsl::error() << "ELF TLS segment offset invalid\n" << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(bsl::to_umax(phdr->p_vaddr) < EXT_CODE_ADDR)) { + if (bsl::unlikely(bsl::to_umax(phdr->p_vaddr) < HYPERVISOR_EXT_CODE_ADDR)) { bsl::error() << "ELF TLS segment virtual address not supported\n" << bsl::here(); return bsl::errc_failure; } auto const required_memsz{bsl::to_umax(phdr->p_vaddr) + bsl::to_umax(phdr->p_memsz)}; - if (bsl::unlikely(required_memsz > (EXT_CODE_ADDR + EXT_CODE_SIZE))) { + if (bsl::unlikely( + required_memsz > (HYPERVISOR_EXT_CODE_ADDR + HYPERVISOR_EXT_CODE_SIZE))) { bsl::error() << "ELF TLS segment virtual address not supported\n" << bsl::here(); return bsl::errc_failure; } auto const required_filesz{bsl::to_umax(phdr->p_filesz) + bsl::to_umax(phdr->p_offset)}; - if (bsl::unlikely(required_filesz > m_elf_file.size())) { + if (bsl::unlikely(required_filesz > elf_file.size())) { bsl::error() << "ELF TLS segment filesz invalid\n" << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(bsl::to_umax(phdr->p_memsz) > PAGE_SIZE)) { + if (bsl::unlikely(bsl::to_umax(phdr->p_memsz) > HYPERVISOR_PAGE_SIZE)) { bsl::error() << "ELF TLS segment memsz invalid\n" << bsl::here(); return bsl::errc_failure; } @@ -256,18 +271,23 @@ namespace mk /// @brief Validates the provided ELF file. /// /// + /// @param elf_file the ELF file to validate against /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - [[nodiscard]] constexpr auto - validate() &noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + validate(bsl::span const &elf_file) noexcept -> bsl::errc_type { - if (bsl::unlikely(!bfelf::validate_elf64_ehdr(m_elf_file))) { + if constexpr (BSL_RELEASE_MODE) { + return bsl::errc_success; + } + + if (bsl::unlikely(!bfelf::validate_elf64_ehdr(elf_file))) { bsl::print() << bsl::here(); return bsl::errc_failure; } - auto const phdrtab{bfelf::get_elf64_phdrtab(m_elf_file)}; + auto const phdrtab{bfelf::get_elf64_phdrtab(elf_file)}; if (bsl::unlikely(phdrtab.empty())) { bsl::print() << bsl::here(); return bsl::errc_failure; @@ -285,7 +305,7 @@ namespace mk switch (elem.data->p_type) { case bfelf::PT_LOAD.get(): { found_pt_load = true; - if (bsl::unlikely(!this->validate_pt_load(elem.data))) { + if (bsl::unlikely(!validate_pt_load(elem.data, elf_file))) { bsl::print() << bsl::here(); return bsl::errc_failure; } @@ -294,7 +314,7 @@ namespace mk case bfelf::PT_GNU_STACK.get(): { found_pt_gnu_stack = true; - if (bsl::unlikely(!this->validate_pt_gnu_stack(elem.data))) { + if (bsl::unlikely(!validate_pt_gnu_stack(elem.data))) { bsl::print() << bsl::here(); return bsl::errc_failure; } @@ -302,7 +322,7 @@ namespace mk } case bfelf::PT_TLS.get(): { - if (bsl::unlikely(!this->validate_pt_tls(elem.data))) { + if (bsl::unlikely(!validate_pt_tls(elem.data, elf_file))) { bsl::print() << bsl::here(); return bsl::errc_failure; } @@ -333,16 +353,23 @@ namespace mk /// the provided root page table. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param rpt the root page table to add too + /// @param elf_file the ELF file that contains the segment info /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - [[nodiscard]] constexpr auto - add_segments(ROOT_PAGE_TABLE_CONCEPT &rpt) &noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + add_segments( + tls_t &tls, + page_pool_t &page_pool, + root_page_table_t &rpt, + bsl::span const &elf_file) noexcept -> bsl::errc_type { - bsl::span page{}; + bsl::span page{}; - auto const phdrtab{bfelf::get_elf64_phdrtab(m_elf_file)}; + auto const phdrtab{bfelf::get_elf64_phdrtab(elf_file)}; for (auto const elem : phdrtab) { auto const *const phdr{elem.data}; @@ -353,8 +380,9 @@ namespace mk bsl::safe_uintmax const bytes_to_allocate{phdr->p_memsz}; bsl::safe_uintmax bytes_to_copy{phdr->p_filesz}; - bsl::safe_uintmax bytes_to_next_page{PAGE_SIZE}; - bsl::safe_uintmax bytes_into_page{phdr->p_vaddr & (PAGE_SIZE - bsl::ONE_UMAX)}; + constexpr auto offset{1_umax}; + bsl::safe_uintmax bytes_to_next_page{HYPERVISOR_PAGE_SIZE}; + bsl::safe_uintmax bytes_into_page{phdr->p_vaddr & (HYPERVISOR_PAGE_SIZE - offset)}; if (bytes_into_page.is_pos()) { bytes_to_next_page -= bytes_into_page; @@ -366,23 +394,35 @@ namespace mk bsl::safe_uintmax bytes{}; while (bytes < bytes_to_allocate) { - if (bytes_to_next_page == PAGE_SIZE) { + if (bytes_to_next_page == HYPERVISOR_PAGE_SIZE) { if ((phdr->p_flags & bfelf::PF_X).is_pos()) { - page = bsl::as_writable_t( - rpt.allocate_rx(phdr->p_vaddr + bytes), PAGE_SIZE); + page = bsl::as_writable_t( + rpt.allocate_page_rx( + tls, + page_pool, + phdr->p_vaddr + bytes, + MAP_PAGE_AUTO_RELEASE_ELF), + HYPERVISOR_PAGE_SIZE); } else { - page = bsl::as_writable_t( - rpt.allocate_rw(phdr->p_vaddr + bytes), PAGE_SIZE); + page = bsl::as_writable_t( + rpt.allocate_page_rw( + tls, + page_pool, + phdr->p_vaddr + bytes, + MAP_PAGE_AUTO_RELEASE_ELF), + HYPERVISOR_PAGE_SIZE); } if (bsl::unlikely(!page)) { bsl::print() << bsl::here(); return bsl::errc_failure; } + + bsl::touch(); } else { - if (bsl::unlikely(!page)) { + if (bsl::unlikely_assert(!page)) { bsl::error() << "The first ELF segment is invalid\n" << bsl::here(); return bsl::errc_failure; } @@ -400,13 +440,13 @@ namespace mk } auto *const dst_addr{page.at_if(bytes_into_page)}; - if (bsl::unlikely(nullptr == dst_addr)) { + if (bsl::unlikely_assert(nullptr == dst_addr)) { bsl::print() << bsl::here(); return bsl::errc_failure; } - auto const *const src_addr{m_elf_file.at_if(phdr->p_offset + bytes)}; - if (bsl::unlikely(nullptr == src_addr)) { + auto const *const src_addr{elf_file.at_if(phdr->p_offset + bytes)}; + if (bsl::unlikely_assert(nullptr == src_addr)) { bsl::print() << bsl::here(); return bsl::errc_failure; } @@ -418,9 +458,10 @@ namespace mk bsl::touch(); } + constexpr auto reset{0_umax}; bytes += bytes_to_next_page; - bytes_to_next_page = PAGE_SIZE; - bytes_into_page = bsl::ZERO_UMAX; + bytes_to_next_page = HYPERVISOR_PAGE_SIZE; + bytes_into_page = reset; } } @@ -432,17 +473,24 @@ namespace mk /// provided root page table at the provided address. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param rpt the root page table to add too /// @param addr the address of where to put the stack /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - [[nodiscard]] constexpr auto - add_stack(ROOT_PAGE_TABLE_CONCEPT &rpt, bsl::safe_uintmax const &addr) &noexcept - -> bsl::errc_type + [[nodiscard]] static constexpr auto + add_stack( + tls_t &tls, + page_pool_t &page_pool, + root_page_table_t &rpt, + bsl::safe_uintmax const &addr) noexcept -> bsl::errc_type { - for (bsl::safe_uintmax bytes{}; bytes < EXT_STACK_SIZE; bytes += PAGE_SIZE) { - void *page{rpt.allocate_rw(addr + bytes)}; + for (bsl::safe_uintmax bytes{}; bytes < HYPERVISOR_EXT_STACK_SIZE; + bytes += HYPERVISOR_PAGE_SIZE) { + auto const *const page{rpt.allocate_page_rw( + tls, page_pool, addr + bytes, MAP_PAGE_AUTO_RELEASE_STACK)}; if (bsl::unlikely(nullptr == page)) { bsl::print() << bsl::here(); return bsl::errc_failure; @@ -459,21 +507,26 @@ namespace mk /// root page table. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param rpt the root page table to add too /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - add_stacks(ROOT_PAGE_TABLE_CONCEPT &rpt) &noexcept -> bsl::errc_type + add_stacks(tls_t &tls, page_pool_t &page_pool, root_page_table_t &rpt) noexcept + -> bsl::errc_type { - for (bsl::safe_uintmax pp{}; pp < bsl::to_umax(m_online_pps); ++pp) { - auto const offs{(EXT_STACK_SIZE + PAGE_SIZE) * pp}; - auto const addr{(EXT_STACK_ADDR + offs)}; + for (bsl::safe_uintmax pp{}; pp < bsl::to_umax(tls.online_pps); ++pp) { + auto const offs{(HYPERVISOR_EXT_STACK_SIZE + HYPERVISOR_PAGE_SIZE) * pp}; + auto const addr{(HYPERVISOR_EXT_STACK_ADDR + offs)}; - if (bsl::unlikely(!this->add_stack(rpt, addr))) { + if (bsl::unlikely(!this->add_stack(tls, page_pool, rpt, addr))) { bsl::print() << bsl::here(); return bsl::errc_failure; } + + bsl::touch(); } return bsl::errc_success; @@ -484,28 +537,38 @@ namespace mk /// provided root page table at the provided address. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param rpt the root page table to add too /// @param addr_usr the address the user's portion of the TLS block /// @param addr_abi the address the ABI's portion of the TLS block + /// @param elf_file the ELF file that contains the TLS info /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - [[nodiscard]] constexpr auto + [[nodiscard]] static constexpr auto add_tls_block( - ROOT_PAGE_TABLE_CONCEPT &rpt, + tls_t &tls, + page_pool_t &page_pool, + root_page_table_t &rpt, bsl::safe_uintmax const &addr_usr, - bsl::safe_uintmax const &addr_abi) &noexcept -> bsl::errc_type + bsl::safe_uintmax const &addr_abi, + bsl::span const &elf_file) noexcept -> bsl::errc_type { bsl::span page_usr{}; bsl::span page_abi{}; - page_usr = bsl::as_writable_t(rpt.allocate_rw(addr_usr), PAGE_SIZE); + page_usr = bsl::as_writable_t( + rpt.allocate_page_rw(tls, page_pool, addr_usr, MAP_PAGE_AUTO_RELEASE_TLS), + HYPERVISOR_PAGE_SIZE); if (bsl::unlikely(!page_usr)) { bsl::print() << bsl::here(); return bsl::errc_failure; } - page_abi = bsl::as_writable_t(rpt.allocate_rw(addr_abi), PAGE_SIZE); + page_abi = bsl::as_writable_t( + rpt.allocate_page_rw(tls, page_pool, addr_abi, MAP_PAGE_AUTO_RELEASE_TLS), + HYPERVISOR_PAGE_SIZE); if (bsl::unlikely(!page_abi)) { bsl::print() << bsl::here(); return bsl::errc_failure; @@ -513,7 +576,7 @@ namespace mk *page_abi.front_if() = addr_abi.get(); - auto const phdrtab{bfelf::get_elf64_phdrtab(m_elf_file)}; + auto const phdrtab{bfelf::get_elf64_phdrtab(elf_file)}; for (auto const elem : phdrtab) { auto const *const phdr{elem.data}; @@ -521,8 +584,8 @@ namespace mk continue; } - auto const *const src_addr{m_elf_file.at_if(phdr->p_offset)}; - auto const dst_index{PAGE_SIZE - bsl::to_umax(phdr->p_memsz)}; + auto const *const src_addr{elf_file.at_if(phdr->p_offset)}; + auto const dst_index{HYPERVISOR_PAGE_SIZE - bsl::to_umax(phdr->p_memsz)}; bsl::builtin_memcpy(page_usr.at_if(dst_index), src_addr, phdr->p_memsz); return bsl::errc_success; @@ -536,21 +599,34 @@ namespace mk /// root page table. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param rpt the root page table to add too + /// @param elf_file the ELF file that contains the TLS info /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - add_tls_blocks(ROOT_PAGE_TABLE_CONCEPT &rpt) &noexcept -> bsl::errc_type + add_tls_blocks( + tls_t &tls, + page_pool_t &page_pool, + root_page_table_t &rpt, + bsl::span const &elf_file) noexcept -> bsl::errc_type { - for (bsl::safe_uintmax pp{}; pp < bsl::to_umax(m_online_pps); ++pp) { - auto const offs{(EXT_TLS_SIZE + PAGE_SIZE) * pp}; - auto const addr{(EXT_TLS_ADDR + offs)}; + bsl::errc_type ret{}; - if (bsl::unlikely(!this->add_tls_block(rpt, addr, addr + PAGE_SIZE))) { + for (bsl::safe_uintmax pp{}; pp < bsl::to_umax(tls.online_pps); ++pp) { + auto const offs{(HYPERVISOR_EXT_TLS_SIZE + HYPERVISOR_PAGE_SIZE) * pp}; + auto const addr{(HYPERVISOR_EXT_TLS_ADDR + offs)}; + + ret = this->add_tls_block( + tls, page_pool, rpt, addr, addr + HYPERVISOR_PAGE_SIZE, elf_file); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return bsl::errc_failure; } + + bsl::touch(); } return bsl::errc_success; @@ -561,38 +637,48 @@ namespace mk /// of this extension. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param rpt the root page table to initialize + /// @param system_rpt the system root page table to initialize with + /// @param elf_file the ELF file that contains the segment and TLS + /// info need to initialize the provided rpt /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - initialize_rpt(ROOT_PAGE_TABLE_CONCEPT &rpt) &noexcept -> bsl::errc_type + initialize_rpt( + tls_t &tls, + page_pool_t &page_pool, + root_page_table_t &rpt, + root_page_table_t const &system_rpt, + bsl::span const &elf_file) noexcept -> bsl::errc_type { - if (bsl::unlikely(!rpt.initialize(m_intrinsic, m_page_pool))) { + if (bsl::unlikely(!rpt.initialize(tls, page_pool))) { bsl::print() << bsl::here(); return bsl::errc_failure; } - bsl::finally release_on_error{[&rpt]() noexcept -> void { - rpt.release(); + bsl::finally release_on_error{[&tls, &rpt, &page_pool]() noexcept -> void { + rpt.release(tls, page_pool); }}; - if (bsl::unlikely(!rpt.add_tables(*m_system_rpt))) { + if (bsl::unlikely(!rpt.add_tables(tls, system_rpt))) { bsl::print() << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(!this->add_segments(rpt))) { + if (bsl::unlikely(!this->add_segments(tls, page_pool, rpt, elf_file))) { bsl::print() << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(!this->add_stacks(rpt))) { + if (bsl::unlikely(!this->add_stacks(tls, page_pool, rpt))) { bsl::print() << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(!this->add_tls_blocks(rpt))) { + if (bsl::unlikely(!this->add_tls_blocks(tls, page_pool, rpt, elf_file))) { bsl::print() << bsl::here(); return bsl::errc_failure; } @@ -601,6 +687,125 @@ namespace mk return bsl::errc_success; } + /// + /// @brief Initializes a direct map root page table to support the + /// execution of this extension (with the inclusion of a direct + /// map). + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param rpt the root page table to initialize + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize_direct_map_rpt( + tls_t &tls, page_pool_t &page_pool, root_page_table_t &rpt) noexcept -> bsl::errc_type + { + if (bsl::unlikely(!rpt.initialize(tls, page_pool))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::finally release_on_error{[&tls, &rpt, &page_pool]() noexcept -> void { + rpt.release(tls, page_pool); + }}; + + if (bsl::unlikely(!rpt.add_tables(tls, m_main_rpt))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + release_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief There are three different types of memory that an + /// extension can allocate: page, huge and heap. The page and + /// huge memory are allocated into the direct map, which provides + /// the extension with the ability to do virtual address to + /// physical address conversions. The heap is different in that it + /// must be virtual contiguous, which means that a virtual address + /// to physical address conversion would require a page walk, and + /// we really want to discourage that. + /// + /// There are also two different ways to map memory into an + /// extension. You can map the memory in using m_main_rpt, which + /// is the RPT that is shared between all VMs. Meaning, no matter + /// which VM is executing, the extension will always be able to + /// use memory mapped into this RPT. The second RPT is the direct + /// map RPTs. Extensions ALWAYS uses a direct map RPT to execute + /// By default, VM 0 is used unless the extension runs another VM. + /// + /// To map in page, huge or heap memory, we have two options: map + /// the memory into m_main_rpt or m_direct_map_rpts. ALL memory + /// that is mapped into the direct map must be mapped using the + /// m_direct_map_rpts. The reason is, the PML4 entries associated + /// with the direct map CANNOT be mapped into the m_main_rpt. + /// Doing so would cause the extension to be able to see most, if + /// not all of the direct mapped memory that has nothing to do + /// with the page and huge memory allocations. The problem is + /// if a page is allocated into a direct map, when a VM is deleted, + /// what do we do? How do we know when to actually release the + /// allocated memory back to the microkernel's page/huge pools. + /// + /// To handle this issue, we map all memory that is allocated + /// using the page/huge memory into the direct map for VM 0. + /// The extension is not allowed to destroy VM 0. In addition, + /// since this memory is allocated into VM 0, when an extension + /// attempts to access this memory from a different VM, it will + /// generate a page fault. This memory address is however a direct + /// map address, and as such, the extension will map in this + /// memory the same way it would for any other direct map address, + /// with auto_release turned off. When the extension is finally + /// removed, we remove the direct maps, including VM 0, and the + /// memory is properly freed. + /// + /// All we have left to do is deal with heap memory. We cannot + /// allocate this memory into the direct map because it needs + /// to be virtually contiguous. This means that we HAVE to map + /// this memory into m_main_rpt. The problem is, this RPT is + /// created when the extension is initialized, and then it is + /// only used when you initialize a direct map. But what if an + /// extension allocates heap memory after the direct map is + /// initialized? That's where this function comes into play. It's + /// job is to make sure that we add any PML4 entires from + /// m_main_rpt that may have been added back into the direct + /// maps that are active so that any changes to m_main_rpt are + /// properly accounted for. + /// + /// Just as a reminder, the way that these RPTs are layed out, + /// is each PML4 is dedicated to a specific purpose, and these + /// cannot be shared. For example, some PML4s are dedicated to + /// the microkernel's memory, some for the extension, the stacks + /// the TLS blocks, etc... You cannot mix and match. + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + update_direct_map_rpts(tls_t &tls) noexcept -> bsl::errc_type + { + for (auto const rpt : m_direct_map_rpts) { + if (!rpt.data->is_initialized()) { + continue; + } + + if (bsl::unlikely(!rpt.data->add_tables(tls, m_main_rpt))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + bsl::touch(); + } + + return bsl::errc_success; + } + /// /// @brief Executes the extension given an instruction pointer to /// execute the extension at, a stack pointer to execute the @@ -608,43 +813,64 @@ namespace mk /// layout to execute the extension with. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsic_t to use /// @param ip the instruction pointer defining where in the /// extension to start execution at. - /// @param rpt the root page table defining the memory layout to - /// execute the extension with /// @param arg0 the first argument to pass the extension /// @param arg1 the second argument to pass the extension /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto execute( - TLS_CONCEPT &tls, + tls_t &tls, + intrinsic_t &intrinsic, bsl::safe_uintmax const &ip, - ROOT_PAGE_TABLE_CONCEPT const &rpt, bsl::safe_uintmax const &arg0 = {}, - bsl::safe_uintmax const &arg1 = {}) &noexcept -> bsl::errc_type + bsl::safe_uintmax const &arg1 = {}) noexcept -> bsl::errc_type { - if (bsl::unlikely(!m_initialized)) { + if (bsl::unlikely_assert(!m_id)) { bsl::error() << "ext_t not initialized\n" << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(!ip)) { + if (bsl::unlikely_assert(!ip)) { bsl::error() << "invalid instruction pointer\n" << bsl::here(); return bsl::errc_failure; } - if (tls.ext != this) { - tls.ext = this; - tls.set_extid(m_id); - rpt.activate(); + auto *const rpt{m_direct_map_rpts.at_if(bsl::to_umax(tls.active_vmid))}; + if (bsl::unlikely_assert(nullptr == rpt)) { + bsl::error() << "invalid active_vmid " // -- + << bsl::hex(tls.active_vmid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; } - auto const ret{call_ext(ip.get(), tls.sp, arg0.get(), arg1.get())}; + if (tls.active_rpt != rpt) { + if (bsl::unlikely_assert(!rpt->activate(intrinsic))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.active_rpt = rpt; + } + else { + bsl::touch(); + } + + if (tls.ext != this) { + tls.ext = this; + tls.active_extid = m_id.get(); + } + else { + bsl::touch(); + } + + bsl::exit_code const ret{call_ext(ip.get(), tls.sp, arg0.get(), arg1.get())}; if (bsl::unlikely(ret != bsl::exit_success)) { bsl::print() << bsl::here(); return bsl::errc_failure; @@ -654,157 +880,92 @@ namespace mk } public: - /// @brief an alias for INTRINSIC_CONCEPT - using intrinsic_type = INTRINSIC_CONCEPT; - /// @brief an alias for PAGE_POOL_CONCEPT - using page_pool_type = PAGE_POOL_CONCEPT; - /// @brief an alias for ROOT_PAGE_TABLE_CONCEPT - using root_page_table_type = ROOT_PAGE_TABLE_CONCEPT; - - /// - /// @brief Default constructor - /// - constexpr ext_t() noexcept = default; - /// /// @brief Initializes this ext_t /// /// - /// @param intrinsic the intrinsics to use - /// @param page_pool the page pool to use + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param i the ID for this ext_t /// @param ext_elf_file the ELF file for this ext_t - /// @param online_pps the total number of PPs that are online /// @param system_rpt the system RPT provided by the loader /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto initialize( - INTRINSIC_CONCEPT *const intrinsic, - PAGE_POOL_CONCEPT *const page_pool, + tls_t &tls, + page_pool_t &page_pool, bsl::safe_uint16 const &i, - bsl::span const &ext_elf_file, - bsl::safe_uint16 const &online_pps, - ROOT_PAGE_TABLE_CONCEPT const *const system_rpt) &noexcept -> bsl::errc_type + loader::ext_elf_file_type const &ext_elf_file, + root_page_table_t const &system_rpt) noexcept -> bsl::errc_type { - if (bsl::unlikely(m_initialized)) { + bsl::errc_type ret{}; + + if (bsl::unlikely_assert(m_id)) { bsl::error() << "ext_t already initialized\n" << bsl::here(); return bsl::errc_failure; } - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); + bsl::finally release_on_error{[this, &tls, &page_pool]() noexcept -> void { + this->release(tls, page_pool); }}; - m_intrinsic = intrinsic; - if (bsl::unlikely(nullptr == intrinsic)) { - bsl::error() << "invalid intrinsic\n" << bsl::here(); - return bsl::errc_failure; - } - - m_page_pool = page_pool; - if (bsl::unlikely(nullptr == page_pool)) { - bsl::error() << "invalid page_pool\n" << bsl::here(); - return bsl::errc_failure; - } - - m_id = i; - if (bsl::unlikely(!i)) { + if (bsl::unlikely_assert(!i)) { bsl::error() << "invalid id\n" << bsl::here(); return bsl::errc_failure; } - m_elf_file = ext_elf_file; - if (bsl::unlikely(!this->validate())) { + if (bsl::unlikely_assert(!validate(ext_elf_file))) { bsl::print() << bsl::here(); return bsl::errc_failure; } - m_online_pps = online_pps; - if (bsl::unlikely(!online_pps)) { - bsl::error() << "invalid online_pps\n" << bsl::here(); - return bsl::errc_failure; - } - - m_system_rpt = system_rpt; - if (bsl::unlikely(!this->initialize_rpt(m_main_rpt))) { + ret = this->initialize_rpt(tls, page_pool, m_main_rpt, system_rpt, ext_elf_file); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return bsl::errc_failure; } - m_main_ip = bfelf::get_elf64_ip(ext_elf_file); + m_entry_ip = bfelf::get_elf64_ip(ext_elf_file); + if (bsl::unlikely_assert(!m_entry_ip)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } release_on_error.ignore(); - m_initialized = true; + m_id = i; return bsl::errc_success; } /// /// @brief Release the ext_t /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// constexpr void - release() &noexcept + release(tls_t &tls, page_pool_t &page_pool) noexcept { - m_heap_pool_cursor = bsl::to_umax(EXT_HEAP_POOL_ADDR); - m_page_pool_cursor = bsl::to_umax(EXT_PAGE_POOL_ADDR); - m_handle = bsl::safe_uintmax::zero(true); - m_fail_ip = bsl::safe_uintmax::zero(true); - m_vmexit_ip = bsl::safe_uintmax::zero(true); - m_bootstrap_ip = bsl::safe_uintmax::zero(true); - m_main_ip = bsl::safe_uintmax::zero(true); - m_main_rpt.release(); - m_system_rpt = {}; - m_online_pps = bsl::safe_uint16::zero(true); - m_elf_file = {}; - m_id = bsl::safe_uint16::zero(true); - m_page_pool = {}; - m_intrinsic = {}; - m_bootstrapped = {}; + m_heap_crsr = {}; + m_handle = bsl::safe_uintmax::failure(); + m_fail_ip = bsl::safe_uintmax::failure(); + m_vmexit_ip = bsl::safe_uintmax::failure(); + m_bootstrap_ip = bsl::safe_uintmax::failure(); + m_entry_ip = bsl::safe_uintmax::failure(); + + for (auto const rpt : m_direct_map_rpts) { + rpt.data->release(tls, page_pool); + } + + m_main_rpt.release(tls, page_pool); + + m_id = bsl::safe_uint16::failure(); m_started = {}; - m_initialized = {}; } - /// - /// @brief Destructor - /// - constexpr ~ext_t() noexcept = default; - - /// - /// @brief copy constructor - /// - /// - /// @param o the object being copied - /// - constexpr ext_t(ext_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr ext_t(ext_t &&o) noexcept = default; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(ext_t const &o) &noexcept -> ext_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(ext_t &&o) &noexcept -> ext_t & = default; - /// /// @brief Returns the ID of this ext_t /// @@ -812,7 +973,7 @@ namespace mk /// @return Returns the ID of this ext_t /// [[nodiscard]] constexpr auto - id() const &noexcept -> bsl::safe_uint16 const & + id() const noexcept -> bsl::safe_uint16 const & { return m_id; } @@ -824,7 +985,7 @@ namespace mk /// @return Returns the bootstrap IP for this extension. /// [[nodiscard]] constexpr auto - bootstrap_ip() const &noexcept -> bsl::safe_uintmax const & + bootstrap_ip() const noexcept -> bsl::safe_uintmax const & { return m_bootstrap_ip; } @@ -839,7 +1000,7 @@ namespace mk /// @param ip the bootstrap IP to use /// constexpr void - set_bootstrap_ip(bsl::safe_uintmax const &ip) &noexcept + set_bootstrap_ip(bsl::safe_uintmax const &ip) noexcept { m_bootstrap_ip = ip; } @@ -851,7 +1012,7 @@ namespace mk /// @return Returns the VMExit IP for this extension. /// [[nodiscard]] constexpr auto - vmexit_ip() const &noexcept -> bsl::safe_uintmax const & + vmexit_ip() const noexcept -> bsl::safe_uintmax const & { return m_vmexit_ip; } @@ -866,7 +1027,7 @@ namespace mk /// @param ip the VMExit IP to use /// constexpr void - set_vmexit_ip(bsl::safe_uintmax const &ip) &noexcept + set_vmexit_ip(bsl::safe_uintmax const &ip) noexcept { m_vmexit_ip = ip; } @@ -878,7 +1039,7 @@ namespace mk /// @return Returns the fast fail IP for this extension. /// [[nodiscard]] constexpr auto - fail_ip() const &noexcept -> bsl::safe_uintmax const & + fail_ip() const noexcept -> bsl::safe_uintmax const & { return m_fail_ip; } @@ -893,7 +1054,7 @@ namespace mk /// @param ip the fail IP to use /// constexpr void - set_fail_ip(bsl::safe_uintmax const &ip) &noexcept + set_fail_ip(bsl::safe_uintmax const &ip) noexcept { m_fail_ip = ip; } @@ -905,14 +1066,15 @@ namespace mk /// @return Opens a handle and returns the resulting handle /// [[nodiscard]] constexpr auto - open_handle() &noexcept -> bsl::safe_uintmax + open_handle() noexcept -> bsl::safe_uintmax { if (bsl::unlikely(m_handle)) { bsl::error() << "handle already opened\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); + return bsl::safe_uintmax::failure(); } - m_handle = bsl::to_umax(this->id()) + bsl::ONE_UMAX; + constexpr auto offset{1_umax}; + m_handle = bsl::to_umax(this->id()) + offset; return m_handle; } @@ -920,9 +1082,21 @@ namespace mk /// @brief Closes a previously opened handle /// constexpr void - close_handle() &noexcept + close_handle() noexcept { - m_handle = bsl::safe_uintmax::zero(true); + m_handle = bsl::safe_uintmax::failure(); + } + + /// + /// @brief Returns true if the extension's handle is open. + /// + /// + /// @return Returns true if the extension's handle is open. + /// + [[nodiscard]] constexpr auto + is_handle_open() const noexcept -> bool + { + return !!m_handle; } /// @@ -933,86 +1107,461 @@ namespace mk /// @return Returns true if provided handle is valid /// [[nodiscard]] constexpr auto - is_handle_valid(bsl::safe_uintmax const &handle) const &noexcept -> bool + is_handle_valid(bsl::safe_uintmax const &handle) const noexcept -> bool { return handle == m_handle; } /// - /// @brief Allocates a page and maps it into the extension's - /// address space. The resulting page is not accessible by the - /// microkernel, even though the virtual address is the same - /// for both the microkernel and the extension. This is to ensure - /// protections against transient execution attacks. + /// @brief Returns true if the extension's main function has + /// completed it's execution. /// /// - /// @return Returns a page_t containing the virtual address and + /// @return Returns true if the extension's main function has + /// completed it's execution. + /// + [[nodiscard]] constexpr auto + is_started() const noexcept -> bool + { + return m_started; + } + + /// + /// @brief Allocates a page and maps it into the extension's + /// address space. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @return Returns a alloc_page_t containing the virtual address and /// physical address of the page. If an error occurs, this /// function will return an invalid virtual and physical address. /// [[nodiscard]] constexpr auto - alloc_page() &noexcept -> page_t + alloc_page(tls_t &tls, page_pool_t &page_pool) noexcept -> alloc_page_t { - if (bsl::unlikely(!m_initialized)) { + bsl::errc_type ret{}; + + if (bsl::unlikely_assert(!m_id)) { bsl::error() << "ext_t not initialized\n" << bsl::here(); - return {bsl::safe_uintmax::zero(true), bsl::safe_uintmax::zero(true)}; + return {bsl::safe_uintmax::failure(), bsl::safe_uintmax::failure()}; } - if (bsl::unlikely(m_bootstrapped)) { - bsl::error() << "allocations not supported after initialization\n" << bsl::here(); - return {bsl::safe_uintmax::zero(true), bsl::safe_uintmax::zero(true)}; - } - - if (!(m_page_pool_cursor < EXT_PAGE_POOL_ADDR + EXT_PAGE_POOL_SIZE)) { - bsl::error() << "ext_t page pool at max capacity\n" << bsl::here(); - return {bsl::safe_uintmax::zero(true), bsl::safe_uintmax::zero(true)}; - } - - auto *const ptr{m_main_rpt.allocate_rw(m_page_pool_cursor)}; - if (bsl::unlikely(nullptr == ptr)) { + auto const *const page{ + page_pool.allocate(tls, ALLOCATE_TAG_BF_MEM_OP_ALLOC_PAGE)}; + if (bsl::unlikely(nullptr == page)) { bsl::print() << bsl::here(); - return {bsl::safe_uintmax::zero(true), bsl::safe_uintmax::zero(true)}; + return {bsl::safe_uintmax::failure(), bsl::safe_uintmax::failure()}; } - auto const phys{m_page_pool->virt_to_phys(ptr)}; - if (bsl::unlikely(!phys)) { + auto const page_phys{page_pool.virt_to_phys(page)}; + if (bsl::unlikely_assert(!page_phys)) { bsl::print() << bsl::here(); - return {bsl::safe_uintmax::zero(true), bsl::safe_uintmax::zero(true)}; + return {bsl::safe_uintmax::failure(), bsl::safe_uintmax::failure()}; } - /// TODO: - /// - Unmap the page from the microkernel's page tables. Note that - /// this should 0 the 4k PTE (and not simply change its present - /// bit), and it should also + auto const page_virt{HYPERVISOR_EXT_PAGE_POOL_ADDR + page_phys}; + if (bsl::unlikely_assert(!page_virt)) { + bsl::print() << bsl::here(); + return {bsl::safe_uintmax::failure(), bsl::safe_uintmax::failure()}; + } + + /// NOTE: + /// - See update_direct_map_rpts for more details on how this + /// works, but the TL;DR is, we map the page into VM 0's direct + /// map. VM 0 cannot be destroyed, so auto_release works as + /// expected here as destroying any other VM will not attempt + /// to free the page we are mapping here. The extension can + /// access this memory from any VM as this is direct map memory + /// so any attempt to access this memory when a VM is active + /// that is not #0 will result in a page fault, and the page + /// handler will direct map the address into that VM as it + /// would any other physical address. /// - m_page_pool_cursor += PAGE_SIZE; - return {bsl::to_umax(ptr), phys}; + ret = m_direct_map_rpts.front().map_page( + tls, + page_pool, + page_virt, + page_phys, + MAP_PAGE_READ | MAP_PAGE_WRITE, + MAP_PAGE_AUTO_RELEASE_ALLOC_PAGE); + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return {bsl::safe_uintmax::failure(), bsl::safe_uintmax::failure()}; + } + + return {page_virt, page_phys}; } /// - /// @brief Converts a virtual address to a physical address given - /// the current set of page tables used by the extension. + /// @brief Frees a page that was mapped it into the extension's + /// address space. /// /// - /// @param virt the virtual address to convert - /// @return Returns the physical address of the page. + /// @param page_virt the virtual address to free + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + free_page(bsl::safe_uintmax const &page_virt) noexcept -> bsl::errc_type + { + bsl::discard(page_virt); + + bsl::error() << "free_page is currently unsupported\n" << bsl::here(); + return bsl::errc_failure; + } + + /// + /// @brief Allocates a physically contiguous block of memory and maps + /// it into the extension's address space. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param huge_pool the huge_pool_t to use + /// @param size the total number of bytes to allocate + /// @return Returns a huge_t containing the virtual address and + /// physical address of the memory block. If an error occurs, this + /// function will return an invalid virtual and physical address. /// [[nodiscard]] constexpr auto - virt_to_phys(bsl::safe_uintmax const &virt) &noexcept -> bsl::safe_uintmax + alloc_huge( + tls_t &tls, + page_pool_t &page_pool, + huge_pool_t &huge_pool, + bsl::safe_uintmax const &size) noexcept -> alloc_huge_t { - if (bsl::unlikely(!m_initialized)) { + bsl::errc_type ret{}; + + if (bsl::unlikely_assert(!m_id)) { bsl::error() << "ext_t not initialized\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); + return {bsl::safe_uintmax::failure(), bsl::safe_uintmax::failure()}; } - auto const phys{m_main_rpt.virt_to_phys(virt)}; - if (bsl::unlikely(!phys)) { + constexpr auto aligned{0_umax}; + if (bsl::unlikely((size % HYPERVISOR_PAGE_SIZE) != aligned)) { + bsl::error() << "invalid size " // -- + << bsl::hex(size) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return {bsl::safe_uintmax::failure(), bsl::safe_uintmax::failure()}; + } + + auto const huge{huge_pool.allocate(tls, size)}; + if (bsl::unlikely(!huge)) { bsl::print() << bsl::here(); - return phys; + return {bsl::safe_uintmax::failure(), bsl::safe_uintmax::failure()}; } - return phys; + auto const huge_phys{huge_pool.virt_to_phys(huge.data())}; + if (bsl::unlikely_assert(!huge_phys)) { + bsl::print() << bsl::here(); + return {bsl::safe_uintmax::failure(), bsl::safe_uintmax::failure()}; + } + + auto const huge_virt{HYPERVISOR_EXT_PAGE_POOL_ADDR + huge_phys}; + if (bsl::unlikely_assert(!huge_virt)) { + bsl::print() << bsl::here(); + return {bsl::safe_uintmax::failure(), bsl::safe_uintmax::failure()}; + } + + /// NOTE: + /// - See update_direct_map_rpts for more details on how this + /// works, but the TL;DR is, we map the page into VM 0's direct + /// map. VM 0 cannot be destroyed, so auto_release works as + /// expected here as destroying any other VM will not attempt + /// to free the page we are mapping here. The extension can + /// access this memory from any VM as this is direct map memory + /// so any attempt to access this memory when a VM is active + /// that is not #0 will result in a page fault, and the page + /// handler will direct map the address into that VM as it + /// would any other physical address. + /// + + for (bsl::safe_uintmax i{}; i < size; i += HYPERVISOR_PAGE_SIZE) { + ret = m_direct_map_rpts.front().map_page( + tls, + page_pool, + huge_virt + i, + huge_phys + i, + MAP_PAGE_READ | MAP_PAGE_WRITE, + MAP_PAGE_AUTO_RELEASE_ALLOC_HUGE); + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return {bsl::safe_uintmax::failure(), bsl::safe_uintmax::failure()}; + } + + bsl::touch(); + } + + return {huge_virt, huge_phys}; + } + + /// + /// @brief Frees a physically contiguous block of memory that was + /// mapped it into the extension's address space. + /// + /// + /// @param huge_virt the virtual address to free + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + free_huge(bsl::safe_uintmax const &huge_virt) noexcept -> bsl::errc_type + { + bsl::discard(huge_virt); + + bsl::error() << "free_huge is currently unsupported\n" << bsl::here(); + return bsl::errc_failure; + } + + /// + /// @brief Allocates heap memory and maps it into the extension's + /// address space. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param size the total number of bytes to allocate and add + /// to the heap. + /// @return On success, alloc_heap returns the previous address + /// virtual address of the heap. If an error occurs, this + /// function returns bsl::safe_uintmax::failure(). + /// + [[nodiscard]] constexpr auto + alloc_heap(tls_t &tls, page_pool_t &page_pool, bsl::safe_uintmax const &size) noexcept + -> bsl::safe_uintmax + { + bsl::errc_type ret{}; + + constexpr auto pool_addr{HYPERVISOR_EXT_HEAP_POOL_ADDR}; + constexpr auto pool_size{HYPERVISOR_EXT_HEAP_POOL_SIZE}; + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "ext_t not initialized\n" << bsl::here(); + return bsl::safe_uintmax::failure(); + } + + if (bsl::unlikely(!size)) { + bsl::error() << "invalid size " // -- + << bsl::hex(size) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + constexpr auto aligned{0_umax}; + auto pages{size / HYPERVISOR_PAGE_SIZE}; + + if ((size % HYPERVISOR_PAGE_SIZE) != aligned) { + ++pages; + } + else { + bsl::touch(); + } + + if (bsl::unlikely((m_heap_crsr + (pages * HYPERVISOR_PAGE_SIZE)) > pool_size)) { + bsl::error() << "the extension's heap pool is out of memory" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + auto const previous_heap_virt{m_heap_crsr + pool_addr}; + if (bsl::unlikely_assert(!previous_heap_virt)) { + bsl::print() << bsl::here(); + return bsl::safe_uintmax::failure(); + } + + for (bsl::safe_uintmax i{}; i < pages; ++i) { + auto const *const page{ + page_pool.allocate(tls, ALLOCATE_TAG_BF_MEM_OP_ALLOC_HEAP)}; + if (bsl::unlikely(nullptr == page)) { + bsl::print() << bsl::here(); + return bsl::safe_uintmax::failure(); + } + + auto const page_phys{page_pool.virt_to_phys(page)}; + if (bsl::unlikely_assert(!page_phys)) { + bsl::print() << bsl::here(); + return bsl::safe_uintmax::failure(); + } + + auto const page_virt{m_heap_crsr + pool_addr}; + if (bsl::unlikely_assert(!page_virt)) { + bsl::print() << bsl::here(); + return bsl::safe_uintmax::failure(); + } + + ret = m_main_rpt.map_page( + tls, + page_pool, + page_virt, + page_phys, + MAP_PAGE_READ | MAP_PAGE_WRITE, + MAP_PAGE_AUTO_RELEASE_ALLOC_HEAP); + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::safe_uintmax::failure(); + } + + m_heap_crsr += HYPERVISOR_PAGE_SIZE; + } + + ret = this->update_direct_map_rpts(tls); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::safe_uintmax::failure(); + } + + return previous_heap_virt; + } + + /// + /// @brief Maps a page into the direct map portion of the current + /// direct map root page table that is active. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param page_virt the virtual address to map the physical address too + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + map_page_direct( + tls_t &tls, page_pool_t &page_pool, bsl::safe_uintmax const &page_virt) noexcept + -> bsl::errc_type + { + bsl::errc_type ret{}; + + constexpr auto dm_addr{HYPERVISOR_EXT_DIRECT_MAP_ADDR}; + constexpr auto dm_size{HYPERVISOR_EXT_DIRECT_MAP_SIZE}; + + constexpr auto offset{1_umax}; + constexpr auto min_dm_addr{dm_addr}; + constexpr auto max_dm_addr{dm_addr + (dm_size - offset)}; + + if (bsl::unlikely(page_virt < min_dm_addr)) { + return bsl::errc_failure; + } + + if (bsl::unlikely(page_virt > max_dm_addr)) { + return bsl::errc_failure; + } + + auto *const direct_map_rpt{m_direct_map_rpts.at_if(bsl::to_umax(tls.active_vmid))}; + if (bsl::unlikely(nullptr == direct_map_rpt)) { + bsl::error() << "invalid active_vmid " // -- + << bsl::hex(tls.active_vmid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + ret = direct_map_rpt->map_page_unaligned( + tls, + page_pool, + page_virt, + page_virt - min_dm_addr, + MAP_PAGE_READ | MAP_PAGE_WRITE, + MAP_PAGE_NO_AUTO_RELEASE); + + if (ret == bsl::errc_already_exists) { + return bsl::errc_success; + } + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + /// + /// @brief Tells the extension that a VM was created so that it + /// can initialize it's VM specific resources. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param vmid the VMID of the VM that was created. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + signal_vm_created(tls_t &tls, page_pool_t &page_pool, bsl::safe_uint16 const &vmid) noexcept + -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "ext_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + auto *const rpt{m_direct_map_rpts.at_if(bsl::to_umax(vmid))}; + if (bsl::unlikely_assert(nullptr == rpt)) { + bsl::error() << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!this->initialize_direct_map_rpt(tls, page_pool, *rpt))) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Tells the extension that a VM was destroyed so that it + /// can release it's VM specific resources. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param vmid the VMID of the VM that was destroyed. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + signal_vm_destroyed( + tls_t &tls, page_pool_t &page_pool, bsl::safe_uint16 const &vmid) noexcept + -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "ext_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + auto *const rpt{m_direct_map_rpts.at_if(bsl::to_umax(vmid))}; + if (bsl::unlikely_assert(nullptr == rpt)) { + bsl::error() << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + rpt->release(tls, page_pool); + return bsl::errc_success; } /// @@ -1021,17 +1570,16 @@ namespace mk /// return bsl::errc_success. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsic_t to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - start(TLS_CONCEPT &tls) &noexcept -> bsl::errc_type + start(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { auto const arg{bsl::to_umax(syscall::BF_ALL_SPECS_SUPPORTED_VAL)}; - auto const ret{this->execute(tls, m_main_ip, m_main_rpt, arg)}; + auto const ret{this->execute(tls, intrinsic, m_entry_ip, arg)}; if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return bsl::errc_failure; @@ -1047,23 +1595,26 @@ namespace mk /// will return bsl::errc_success. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsic_t to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - bootstrap(TLS_CONCEPT &tls) &noexcept -> bsl::errc_type + bootstrap(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { - auto const arg{bsl::to_umax(tls.ppid())}; - auto const ret{this->execute(tls, m_bootstrap_ip, m_main_rpt, arg)}; + if (bsl::unlikely(!m_bootstrap_ip)) { + bsl::error() << "a bootstrap handler was never registered\n" << bsl::here(); + return bsl::errc_failure; + } + + auto const arg{bsl::to_umax(tls.ppid)}; + auto const ret{this->execute(tls, intrinsic, m_bootstrap_ip, arg)}; if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return bsl::errc_failure; } - m_bootstrapped = true; return bsl::errc_success; } @@ -1073,20 +1624,20 @@ namespace mk /// will return bsl::errc_success. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsic_t to use /// @param exit_reason the reason for the VMExit /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - vmexit(TLS_CONCEPT &tls, bsl::safe_uintmax const &exit_reason) &noexcept -> bsl::errc_type + vmexit(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uintmax const &exit_reason) noexcept + -> bsl::errc_type { bsl::safe_uintmax arg0{bsl::to_umax(tls.active_vpsid)}; bsl::safe_uintmax arg1{exit_reason}; - auto const ret{this->execute(tls, m_vmexit_ip, m_main_rpt, arg0, arg1)}; + auto const ret{this->execute(tls, intrinsic, m_vmexit_ip, arg0, arg1)}; if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; @@ -1101,18 +1652,17 @@ namespace mk /// will return bsl::errc_success. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsic_t to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - fail(TLS_CONCEPT &tls) &noexcept -> bsl::errc_type + fail(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { bsl::safe_uintmax arg0{syscall::BF_STATUS_FAILURE_UNKNOWN}; - auto const ret{this->execute(tls, m_fail_ip, m_main_rpt, arg0)}; + auto const ret{this->execute(tls, intrinsic, m_fail_ip, arg0)}; if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; @@ -1120,6 +1670,188 @@ namespace mk return ret; } + + /// + /// @brief Dumps the vm_t + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// + constexpr void + dump(tls_t &tls, page_pool_t &page_pool) const noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + + if (bsl::unlikely_assert(!m_id)) { + bsl::print() << "[error]" << bsl::endl; + return; + } + + bsl::print() << bsl::mag << "ext ["; + bsl::print() << bsl::rst << bsl::hex(m_id); + bsl::print() << bsl::mag << "] dump: "; + bsl::print() << bsl::rst << bsl::endl; + + /// Header + /// + + bsl::print() << bsl::ylw << "+------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^14s", "description "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^19s", "value "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + /// Started + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<14s", "started "}; + bsl::print() << bsl::ylw << "| "; + if (m_started) { + bsl::print() << bsl::grn << bsl::fmt{"^19s", "yes "}; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^19s", "no "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Active + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<14s", "active "}; + bsl::print() << bsl::ylw << "| "; + if (tls.active_extid == m_id) { + bsl::print() << bsl::grn << bsl::fmt{"^19s", "yes "}; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^19s", "no "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Entry IP + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<14s", "entry ip "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::hex(m_entry_ip) << ' '; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Bootstrap IP + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<14s", "bootstrap ip "}; + bsl::print() << bsl::ylw << "| "; + if (m_bootstrap_ip) { + bsl::print() << bsl::rst << bsl::hex(m_bootstrap_ip) << ' '; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^19s", "not registered "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// VMExit IP + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<14s", "vmexit ip "}; + bsl::print() << bsl::ylw << "| "; + if (m_vmexit_ip) { + bsl::print() << bsl::rst << bsl::hex(m_vmexit_ip) << ' '; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^19s", "not registered "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Fail IP + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<14s", "fail ip "}; + bsl::print() << bsl::ylw << "| "; + if (m_fail_ip) { + bsl::print() << bsl::rst << bsl::hex(m_fail_ip) << ' '; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^19s", "not registered "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Handle + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<14s", "handle "}; + bsl::print() << bsl::ylw << "| "; + if (m_handle) { + bsl::print() << bsl::rst << bsl::hex(m_handle) << ' '; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^19s", "not opened "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Heap Cursor + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<14s", "heap cursor "}; + bsl::print() << bsl::ylw << "| "; + if (!m_heap_crsr.is_zero()) { + bsl::print() << bsl::rst << bsl::hex(m_heap_crsr) << ' '; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^19s", "not allocated "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Footer + /// + + bsl::print() << bsl::ylw << "+------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + auto const *const direct_map_rpt{ + m_direct_map_rpts.at_if(bsl::to_umax(tls.active_vmid))}; + if (bsl::unlikely(nullptr == direct_map_rpt)) { + bsl::error() << "invalid active_vmid " // -- + << bsl::hex(tls.active_vmid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return; + } + + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::mag << "ext ["; + bsl::print() << bsl::rst << bsl::hex(m_id); + bsl::print() << bsl::mag << "] direct map dump: "; + bsl::print() << bsl::rst << bsl::endl; + + direct_map_rpt->dump(page_pool); + } }; } diff --git a/kernel/src/fast_fail.hpp b/kernel/src/fast_fail.hpp index 598d76f2..1f9b525f 100644 --- a/kernel/src/fast_fail.hpp +++ b/kernel/src/fast_fail.hpp @@ -25,7 +25,9 @@ #ifndef FAST_FAIL_HPP #define FAST_FAIL_HPP +#include #include +#include #include #include @@ -40,25 +42,20 @@ namespace mk /// or a halt() will occur. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use /// @param tls the current TLS block - /// @param ext_fail the ext_t to handle the VMExit - /// @return Returns bsl::exit_success on success and bsl::exit_failure - /// otherwise + /// @param intrinsic the intrinsic_t to use + /// @param ext the ext_t to handle the fail + /// @return Returns bsl::exit_success if the fail was handled, + /// bsl::exit_failure otherwise. /// - template [[nodiscard]] constexpr auto - fast_fail(TLS_CONCEPT &tls, EXT_CONCEPT *const ext_fail) noexcept -> bsl::exit_code + fast_fail(tls_t &tls, intrinsic_t &intrinsic, ext_t *const ext) noexcept -> bsl::exit_code { - bsl::print() << bsl::endl // -- - << bsl::bold_red // -- - << "fast failing:" // -- - << bsl::reset_color // -- - << bsl::endl; // -- + bsl::print() << bsl::red << "\nfast failing:"; + bsl::print() << bsl::rst << bsl::endl; - if (nullptr != ext_fail) { - auto const ret{ext_fail->fail(tls)}; + if (nullptr != ext) { + auto const ret{ext->fail(tls, intrinsic)}; if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return bsl::exit_failure; diff --git a/kernel/src/global_resources.hpp b/kernel/src/global_resources.hpp deleted file mode 100644 index 2e6afb06..00000000 --- a/kernel/src/global_resources.hpp +++ /dev/null @@ -1,168 +0,0 @@ -/// @copyright -/// Copyright (C) 2020 Assured Information Security, Inc. -/// -/// @copyright -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// @copyright -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// @copyright -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -/// SOFTWARE. - -#ifndef GLOBAL_RESOURCES_HPP -#define GLOBAL_RESOURCES_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/// NOTE: -/// - Do not include this file. The only files that should include this -/// one are main entry points (like _start, a trampoline, etc...). -/// Instead, define a template and get these types through a template -/// type. This ensures testing is simple. -/// - -namespace mk -{ - /// @brief defines the VPS type to use - using mk_vps_type = vps_t< // -- - intrinsic_t, // -- - page_pool_t>; // -- - - /// @brief defines the VPS pool type to use - using mk_vps_pool_type = vps_pool_t< // -- - mk_vps_type, // -- - intrinsic_t, // -- - page_pool_t, // -- - HYPERVISOR_MAX_VPSS>; // -- - - /// @brief defines the VP type to use - using mk_vp_type = vp_t< // -- - page_pool_t>; // -- - - /// @brief defines the VP pool type to use - using mk_vp_pool_type = vp_pool_t< // -- - mk_vp_type, // -- - page_pool_t, // -- - HYPERVISOR_MAX_VPS>; // -- - - /// @brief defines the VM type to use - using mk_vm_type = vm_t< // -- - page_pool_t>; // -- - - /// @brief defines the VM pool type to use - using mk_vm_pool_type = vm_pool_t< // -- - mk_vm_type, // -- - page_pool_t, // -- - HYPERVISOR_MAX_VMS>; // -- - - /// @brief defines the root page table type - using mk_root_page_table_type = root_page_table_t< // -- - intrinsic_t, // -- - page_pool_t, // -- - HYPERVISOR_PAGE_SIZE, // -- - HYPERVISOR_PAGE_SHIFT>; // -- - - /// @brief defines the extension type to use - using mk_ext_type = ext_t< // -- - intrinsic_t, // -- - page_pool_t, // -- - mk_root_page_table_type, // -- - HYPERVISOR_PAGE_SIZE, // -- - HYPERVISOR_MAX_PPS, // -- - HYPERVISOR_EXT_STACK_ADDR, // -- - HYPERVISOR_EXT_STACK_SIZE, // -- - HYPERVISOR_EXT_CODE_ADDR, // -- - HYPERVISOR_EXT_CODE_SIZE, // -- - HYPERVISOR_EXT_TLS_ADDR, // -- - HYPERVISOR_EXT_TLS_SIZE, // -- - HYPERVISOR_EXT_PAGE_POOL_ADDR, // -- - HYPERVISOR_EXT_PAGE_POOL_SIZE, // -- - HYPERVISOR_EXT_HEAP_POOL_ADDR, // -- - HYPERVISOR_EXT_HEAP_POOL_SIZE>; // -- - - /// @brief defines the extension pool type to use - using mk_ext_pool_type = ext_pool_t< // -- - mk_ext_type, // -- - intrinsic_t, // -- - page_pool_t, // -- - mk_root_page_table_type, // -- - HYPERVISOR_MAX_EXTENSIONS>; // -- - - /// @brief defines the extension pool type to use - using mk_main_type = mk_main< // -- - intrinsic_t, - page_pool_t, - huge_pool_t, - mk_root_page_table_type, - mk_vps_pool_type, - mk_vp_pool_type, - mk_vm_pool_type, - mk_ext_pool_type, - HYPERVISOR_PAGE_SIZE, // -- - HYPERVISOR_EXT_STACK_ADDR, // -- - HYPERVISOR_EXT_STACK_SIZE, // -- - HYPERVISOR_EXT_TLS_ADDR, // -- - HYPERVISOR_EXT_TLS_SIZE>; // -- - - /// @brief stores the intrinsics used by the microkernel - constinit inline intrinsic_t g_intrinsic{}; - - /// @brief stores the page pool used by the microkernel - constinit inline page_pool_t g_page_pool{}; - - /// @brief stores the huge pool used by the microkernel - constinit inline huge_pool_t g_huge_pool{}; - - /// @brief stores the vps_t pool used by the microkernel - constinit inline mk_vps_pool_type g_vps_pool{g_intrinsic, g_page_pool}; - - /// @brief stores the vp_t pool used by the microkernel - constinit inline mk_vp_pool_type g_vp_pool{g_page_pool}; - - /// @brief stores the vm_t pool used by the microkernel - constinit inline mk_vm_pool_type g_vm_pool{g_page_pool}; - - /// @brief stores the system RPT provided by the loader - constinit inline mk_root_page_table_type g_system_rpt{}; - - /// @brief stores the ext_t pool used by the microkernel - constinit inline mk_ext_pool_type g_ext_pool{g_intrinsic, g_page_pool, g_system_rpt}; - - /// @brief stores the microkernel's main class - constinit inline mk_main_type g_mk_main{ - g_intrinsic, - g_page_pool, - g_huge_pool, - g_system_rpt, - g_vps_pool, - g_vp_pool, - g_vm_pool, - g_ext_pool}; -} - -#endif diff --git a/kernel/src/huge_pool_t.hpp b/kernel/src/huge_pool_t.hpp index bf0a8964..5849180e 100644 --- a/kernel/src/huge_pool_t.hpp +++ b/kernel/src/huge_pool_t.hpp @@ -25,12 +25,16 @@ #ifndef HUGE_POOL_T_HPP #define HUGE_POOL_T_HPP -#include +#include +#include +#include + #include -#include -#include +#include +#include #include #include +#include #include namespace mk @@ -38,131 +42,238 @@ namespace mk /// @class mk::huge_pool_t /// /// - /// @brief TODO + /// @brief The huge pool provides access to physically contiguous + /// memory. The amount of memory that is available is really, really + /// small (likely no more than 1 MB), but some is needed for different + /// architectures that require it like AMD. This memory is only needed + /// by the extensions, and we currently do not support the ability + /// to free memory, so there is no need to over complicate how this + /// allocator works. We simply use a cursor that is always increasing. + /// Once you allocate all of the memory, that is it. /// class huge_pool_t final { - /// @brief stores true if initialized() has been executed - bool m_initialized{}; /// @brief stores the range of memory used by this allocator - bsl::span m_pool{}; - /// @brief stores the virtual address base of the page pool. - bsl::safe_uintmax m_base_virt{}; + bsl::span m_pool{}; /// @brief stores the huge pool's cursor - bsl::safe_uintmax m_cursor{}; + bsl::safe_uintmax m_crsr{}; + /// @brief safe guards operations on the pool. + mutable spinlock_t m_lock{}; public: /// - /// @brief Default constructor - /// - constexpr huge_pool_t() noexcept = default; - - /// - /// @brief Creates the page pool given a mutable_buffer_t to - /// the page pool as well as the virtual address base of the - /// page pool which is used for virt to phys translations. + /// @brief Creates the huge pool given a mutable_buffer_t to + /// the huge pool as well as the virtual address base of the + /// huge pool which is used for virt to phys translations. /// /// - /// @param pool the mutable_buffer_t of the page pool - /// @param base_virt the base virtual address base of the page pool - /// constexpr bsl::errc_type - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise - /// - [[nodiscard]] constexpr auto - initialize(bsl::span &pool, bsl::safe_uintmax const &base_virt) &noexcept - -> bsl::errc_type - { - if (bsl::unlikely(m_initialized)) { - bsl::error() << "huge_pool_t already initialized\n" << bsl::here(); - return bsl::errc_failure; - } - - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); - }}; - - if (bsl::unlikely(pool.empty())) { - m_pool = {}; - m_base_virt = bsl::safe_uintmax::zero(true); - m_cursor = bsl::safe_uintmax::zero(true); - - bsl::error() << "pool is empty\n" << bsl::here(); - return bsl::errc_failure; - } - - if (bsl::unlikely(base_virt.is_zero())) { - m_pool = {}; - m_base_virt = bsl::safe_uintmax::zero(true); - m_cursor = bsl::safe_uintmax::zero(true); - - bsl::error() << "base_virt is 0 or invalid\n" << bsl::here(); - return bsl::errc_failure; - } - - m_pool = pool; - m_base_virt = base_virt; - m_cursor = bsl::ZERO_UMAX; - - release_on_error.ignore(); - m_initialized = true; - - return bsl::errc_success; - } - - /// - /// @brief Release the huge_pool_t + /// @param pool the mutable_buffer_t of the huge pool /// constexpr void - release() &noexcept + initialize(bsl::span &pool) noexcept { - m_cursor = bsl::safe_uintmax::zero(true); - m_base_virt = bsl::safe_uintmax::zero(true); - m_pool = {}; - - m_initialized = {}; + m_pool = pool; } /// - /// @brief Destroyes a previously created huge_pool_t - /// - constexpr ~huge_pool_t() noexcept = default; - - /// - /// @brief copy constructor + /// @brief Allocates memory from the huge pool. /// /// - /// @param o the object being copied + /// @param tls the current TLS block + /// @param size the total number of bytes to allocate. + /// @return Returns bsl::span containing the allocated memory /// - constexpr huge_pool_t(huge_pool_t const &o) noexcept = delete; + [[nodiscard]] constexpr auto + allocate(tls_t &tls, bsl::safe_uintmax const &size) noexcept -> bsl::span + { + lock_guard_t lock{tls, m_lock}; + + if (bsl::unlikely(!size)) { + bsl::error() << "invalid size " // -- + << bsl::hex(size) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return {}; + } + + auto bytes{size}; + auto pages{size / HYPERVISOR_PAGE_SIZE}; + + constexpr auto aligned{0_umax}; + if ((bytes % HYPERVISOR_PAGE_SIZE) != aligned) { + ++pages; + bytes = pages * HYPERVISOR_PAGE_SIZE; + } + else { + bsl::touch(); + } + + auto buf{m_pool.subspan(m_crsr, bytes)}; + if (bsl::unlikely(buf.size() != bytes)) { + bsl::error() << "huge pool out of memory\n" << bsl::here(); + return {}; + } + + m_crsr += bytes; + bsl::builtin_memset(buf.data(), '\0', buf.size()); + + return buf; + } /// - /// @brief move constructor + /// @brief Not supported /// /// - /// @param o the object being moved + /// @param tls the current TLS block + /// @param buf the bsl::span containing the memory to deallocate /// - constexpr huge_pool_t(huge_pool_t &&o) noexcept = default; + constexpr void + deallocate(tls_t &tls, bsl::span const &buf) noexcept + { + lock_guard_t lock{tls, m_lock}; + bsl::discard(buf); + + /// NOTE: + /// - If this function is implemented, we will have to deal with + /// deallocations being a page in size. Specifically, right now + /// a huge page is allocated and mapped into the page tables + /// one page at a time. When is is time to deallocate, this + /// memory is released one page at a time. If the page tables + /// are deallocating one page of a larger physically contiguous + /// memory region, it should be assumed that the entire region + /// will be freed, it will just happen in page increments. + /// - What this means is this function could see a free for the + /// same physically contiguous block of memory (one for each + /// page in the block). We could ignore the extras, or we + /// could set up the allocator so that it frees one page at a + /// time. Just depends on how we want to do this... but in + /// general, I would suggest using the later as a buddy allocator + /// can support this without any added overhead. + /// + } /// - /// @brief copy assignment + /// @brief Converts a virtual address to a physical address for + /// any memory allocated by the huge pool. If the provided ptr + /// was not allocated using the allocate function by the same + /// huge pool, this results of this function are UB. It should + /// be noted that any virtual address may be used meaning the + /// provided address does not have to be page aligned, it simply + /// needs to be allocated using the same huge pool. /// /// - /// @param o the object being copied - /// @return a reference to *this + /// @tparam T defines the type of virtual address being converted + /// @param virt the virtual address to convert + /// @return the resulting physical address /// - [[maybe_unused]] constexpr auto operator=(huge_pool_t const &o) &noexcept - -> huge_pool_t & = delete; + template + [[nodiscard]] constexpr auto + virt_to_phys(T const *const virt) const noexcept -> bsl::safe_uintmax + { + return bsl::to_umax(virt) - HYPERVISOR_MK_HUGE_POOL_ADDR; + } /// - /// @brief move assignment + /// @brief Converts a physical address to a virtual address for + /// any memory allocated by the huge pool. If the provided address + /// was not allocated using the allocate function by the same + /// huge pool, this results of this function are UB. It should + /// be noted that any physical address may be used meaning the + /// provided address does not have to be page aligned, it simply + /// needs to be allocated using the same huge pool. /// /// - /// @param o the object being moved - /// @return a reference to *this + /// @tparam T defines the type of virtual address to convert to + /// @param phys the physical address to convert + /// @return the resulting virtual address /// - [[maybe_unused]] constexpr auto operator=(huge_pool_t &&o) &noexcept - -> huge_pool_t & = default; + template + [[nodiscard]] constexpr auto + phys_to_virt(bsl::safe_uintmax const &phys) const noexcept -> T * + { + return bsl::to_ptr(phys + HYPERVISOR_MK_HUGE_POOL_ADDR); + } + + /// + /// @brief Dumps the page_pool_t + /// + constexpr void + dump() const noexcept + { + constexpr auto kb{1024_umax}; + constexpr auto mb{kb * kb}; + + bsl::print() << bsl::mag << "huge pool dump: "; + bsl::print() << bsl::rst << bsl::endl; + + /// Header + /// + + bsl::print() << bsl::ylw << "+-----------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^12s", "description "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^8s", "value "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+-----------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + /// Total + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<12s", "total "}; + bsl::print() << bsl::ylw << "| "; + if ((m_pool.size() / mb).is_zero()) { + bsl::print() << bsl::rst << bsl::fmt{"4d", m_pool.size() / kb} << " KB "; + } + else { + bsl::print() << bsl::rst << bsl::fmt{"4d", m_pool.size() / mb} << " MB "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Used + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<12s", "used "}; + bsl::print() << bsl::ylw << "| "; + if ((m_crsr / mb).is_zero()) { + bsl::print() << bsl::rst << bsl::fmt{"4d", m_crsr / kb} << " KB "; + } + else { + bsl::print() << bsl::rst << bsl::fmt{"4d", m_crsr / mb} << " MB "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Remaining + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<12s", "remaining "}; + bsl::print() << bsl::ylw << "| "; + if (((m_pool.size() - m_crsr) / mb).is_zero()) { + bsl::print() << bsl::rst << bsl::fmt{"4d", (m_pool.size() - m_crsr) / kb} << " KB "; + } + else { + bsl::print() << bsl::rst << bsl::fmt{"4d", (m_pool.size() - m_crsr) / mb} << " MB "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Footer + /// + + bsl::print() << bsl::ylw << "+-----------------------+"; + bsl::print() << bsl::rst << bsl::endl; + } }; } diff --git a/kernel/src/lock_guard_t.hpp b/kernel/src/lock_guard_t.hpp new file mode 100644 index 00000000..b41e8ba9 --- /dev/null +++ b/kernel/src/lock_guard_t.hpp @@ -0,0 +1,121 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef LOCK_GUARD_T_HPP +#define LOCK_GUARD_T_HPP + +#include + +namespace mk +{ + /// @class mk::lock_guard_t + /// + /// + /// @brief Implements a lock_guard_t. Unlike the std::lock_guard_t this lock + /// guard is aware of which PP has acquired the lock. If the same + /// PP attempts to acquire the lock, the lock is ignored, and a + /// warning is outputted. This prevents deadlock, for example, when + /// a lock was not released due to a hardware exception, or when + /// the programmer makes a mistake. + /// + /// + /// @tparam T the type of mutex being locked + /// + template + class lock_guard_t final + { + /// @brief stores the TLS that owns the lock + tls_t const &m_tls; + /// @brief stores the lock that is being guarded + T &m_lock; + + public: + /// + /// @brief Creates a lock_guard_t, locking the provided + /// spinlock/mutex on construction. + /// + /// + /// @param tls the current TLS block + /// @param lck the spinlock/mutex to guard + /// + constexpr lock_guard_t(tls_t const &tls, T &lck) noexcept // -- + : m_tls{tls}, m_lock{lck} + { + m_lock.lock(m_tls); + } + + /// + /// @brief Do not allow temporaries. + /// + /// + /// @param tls the current TLS block + /// @param lck the spinlock/mutex to guard + /// + constexpr lock_guard_t(tls_t const &tls, T const &lck) noexcept = delete; + + /// + /// @brief Destructor + /// + constexpr ~lock_guard_t() noexcept + { + m_lock.unlock(m_tls); + } + + /// + /// @brief copy constructor + /// + /// + /// @param o the object being copied + /// + constexpr lock_guard_t(lock_guard_t const &o) noexcept = delete; + + /// + /// @brief move constructor + /// + /// + /// @param o the object being moved + /// + constexpr lock_guard_t(lock_guard_t &&o) noexcept = default; + + /// + /// @brief copy assignment + /// + /// + /// @param o the object being copied + /// @return a reference to *this + /// + [[maybe_unused]] auto operator=(lock_guard_t const &o) &noexcept -> lock_guard_t & = delete; + + /// + /// @brief move assignment + /// + /// + /// @param o the object being moved + /// @return a reference to *this + /// + [[maybe_unused]] auto operator=(lock_guard_t &&o) &noexcept -> lock_guard_t & = default; + }; +} + +#endif diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp new file mode 100644 index 00000000..af835a0f --- /dev/null +++ b/kernel/src/main.cpp @@ -0,0 +1,209 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace mk +{ + /// @brief stores the TLS blocks used by the microkernel. + extern "C" constinit bsl::array g_tls_blocks{}; + + /// @brief stores a pointer to the debug ring provided by the loader + extern "C" constinit loader::debug_ring_t *g_debug_ring{}; + + /// @brief stores the vmexit log used by the microkernel + constinit inline vmexit_log_t g_vmexit_log{}; + + /// @brief stores the page pool used by the microkernel + constinit inline page_pool_t g_page_pool{}; + + /// @brief stores the huge pool used by the microkernel + constinit inline huge_pool_t g_huge_pool{}; + + /// @brief stores the intrinsics used by the microkernel + constinit inline intrinsic_t g_intrinsic{}; + + /// @brief stores the vm pool used by the microkernel + constinit inline vm_pool_t g_vm_pool{}; + + /// @brief stores the vp pool used by the microkernel + constinit inline vp_pool_t g_vp_pool{}; + + /// @brief stores the vps pool used by the microkernel + constinit inline vps_pool_t g_vps_pool{}; + + /// @brief stores the ext pool used by the microkernel + constinit inline ext_pool_t g_ext_pool{}; + + /// @brief stores the system RPT provided by the loader + constinit inline root_page_table_t g_system_rpt{}; + + /// @brief stores the microkernel's main class + constinit inline mk_main_t g_mk_main{}; + + /// + /// @brief Remove me + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::exit_success if the exception was handled, + /// bsl::exit_failure otherwise + /// + extern "C" [[nodiscard]] auto + dispatch_esr_trampoline(tls_t *const tls) noexcept -> bsl::exit_code + { + auto *const ext{static_cast(tls->ext)}; + return dispatch_esr(*tls, g_page_pool, g_intrinsic, ext); + } + + /// + /// @brief remove me + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::exit_success on success, bsl::exit_failure + /// otherwise + /// + [[nodiscard]] extern "C" auto + dispatch_syscall_trampoline(tls_t *const tls) noexcept -> bsl::exit_code + { + auto *const ext{static_cast(tls->ext)}; + + return dispatch_syscall( + *tls, + g_page_pool, + g_huge_pool, + g_intrinsic, + g_vm_pool, + g_vp_pool, + g_vps_pool, + g_ext_pool, + *ext, + g_vmexit_log); + } + + /// + /// @brief remove me + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::exit_success on success, bsl::exit_failure + /// otherwise + /// + [[nodiscard]] extern "C" auto + dispatch_syscall_trampoline_failure(tls_t *const tls) noexcept -> bsl::exit_code + { + auto *const ext{static_cast(tls->ext)}; + + return dispatch_syscall_failure( + *tls, + g_page_pool, + g_huge_pool, + g_intrinsic, + g_vm_pool, + g_vp_pool, + g_vps_pool, + g_ext_pool, + *ext, + g_vmexit_log); + } + + /// + /// @brief remove me + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::exit_success on success, bsl::exit_failure + /// otherwise + /// + extern "C" [[nodiscard]] auto + vmexit_loop_trampoline(tls_t *const tls) noexcept -> bsl::exit_code + { + auto *const ext{static_cast(tls->ext)}; + return vmexit_loop(*tls, g_intrinsic, g_vps_pool, *ext, g_vmexit_log); + } + + /// + /// @brief remove me + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::exit_success if the fail was handled, + /// bsl::exit_failure otherwise. + /// + extern "C" [[nodiscard]] auto + fast_fail_trampoline(tls_t *const tls) noexcept -> bsl::exit_code + { + auto *const ext{static_cast(tls->ext)}; + return fast_fail(*tls, g_intrinsic, ext); + } + + /// + /// @brief Provides the main entry point of the microkernel. This + /// function is called by the loader and is responsible for starting + /// the hypervisor on a specific core + /// + /// + /// @param args the loader provided arguments to the microkernel. + /// @param tls the current TLS block + /// @return Returns bsl::exit_success on success, bsl::exit_failure + /// otherwise + /// + [[nodiscard]] extern "C" auto + mk_main(loader::mk_args_t *const args, tls_t *const tls) noexcept -> bsl::exit_code + { + return g_mk_main.process( + *tls, + g_page_pool, + g_huge_pool, + g_intrinsic, + g_vm_pool, + g_vp_pool, + g_vps_pool, + g_ext_pool, + g_system_rpt, + args); + } +} diff --git a/kernel/src/mk_main.hpp b/kernel/src/mk_main.hpp deleted file mode 100644 index a5bb1560..00000000 --- a/kernel/src/mk_main.hpp +++ /dev/null @@ -1,455 +0,0 @@ -/// @copyright -/// Copyright (C) 2020 Assured Information Security, Inc. -/// -/// @copyright -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// @copyright -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// @copyright -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -/// SOFTWARE. - -#ifndef MK_MAIN_HPP -#define MK_MAIN_HPP - -#include - -#include -#include -#include -#include -#include -#include - -namespace mk -{ - /// @class mk::mk_main - /// - /// - /// @brief Provide the main entry point for the microkernel. The - /// microkernel actually starts in the _start function, and immediately - /// creates this class and calls its process() function to boot the - /// microkernel, start the extensions and eventually demote the CPU. - /// Like the other main classes, this class serves to encapsulate - /// the entry logic into something that can be easily tested with no - /// dependencies on global resources. - /// - /// - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use - /// @tparam HUGE_POOL_CONCEPT defines the type of huge pool to use - /// @tparam ROOT_PAGE_TABLE_CONCEPT defines the type of RPT pool to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use - /// @tparam VP_POOL_CONCEPT defines the type of VP pool to use - /// @tparam VM_POOL_CONCEPT defines the type of VM pool to use - /// @tparam EXT_POOL_CONCEPT defines the type of extension pool to use - /// @tparam PAGE_SIZE defines the size of a page - /// @tparam EXT_STACK_ADDR the address of the extension's stack - /// @tparam EXT_STACK_SIZE the size of the extension's stack - /// @tparam EXT_TLS_ADDR the address of the extension's TLS block - /// @tparam EXT_TLS_SIZE the size of the extension's TLS block - /// - template< - typename INTRINSIC_CONCEPT, - typename PAGE_POOL_CONCEPT, - typename HUGE_POOL_CONCEPT, - typename ROOT_PAGE_TABLE_CONCEPT, - typename VPS_POOL_CONCEPT, - typename VP_POOL_CONCEPT, - typename VM_POOL_CONCEPT, - typename EXT_POOL_CONCEPT, - bsl::uintmax PAGE_SIZE, - bsl::uintmax EXT_STACK_ADDR, - bsl::uintmax EXT_STACK_SIZE, - bsl::uintmax EXT_TLS_ADDR, - bsl::uintmax EXT_TLS_SIZE> - class mk_main final - { - /// @brief stores a reference to the intrinsics to use - INTRINSIC_CONCEPT &m_intrinsic; - /// @brief stores a reference to the page pool to use - PAGE_POOL_CONCEPT &m_page_pool; - /// @brief stores a reference to the huge pool to use - HUGE_POOL_CONCEPT &m_huge_pool; - /// @brief stores system RPT provided by the loader - ROOT_PAGE_TABLE_CONCEPT &m_system_rpt; - /// @brief stores a reference to the VPS pool to use - VPS_POOL_CONCEPT &m_vps_pool; - /// @brief stores a reference to the VP pool to use - VP_POOL_CONCEPT &m_vp_pool; - /// @brief stores a reference to the VM pool to use - VM_POOL_CONCEPT &m_vm_pool; - /// @brief stores a reference to the extension pool to use - EXT_POOL_CONCEPT &m_ext_pool; - - /// @brief stores the extension pool's initialization status - bool m_initialized; - - /// - /// @brief Sets the extension stack pointer given a TLS block, - /// based on what PP we are currently executing on. - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @param tls the current TLS block - /// - template - constexpr void - set_extension_sp(TLS_CONCEPT &tls) noexcept - { - constexpr bsl::safe_uintmax stack_addr{EXT_STACK_ADDR}; - constexpr bsl::safe_uintmax stack_size{EXT_STACK_SIZE}; - - auto const offs{(stack_size + PAGE_SIZE) * bsl::to_umax(tls.ppid())}; - tls.sp = (stack_addr + offs + stack_size).get(); - } - - /// - /// @brief Sets the extension TLS pointer given a TLS block, - /// based on what PP we are currently executing on. - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @param tls the current TLS block - /// - template - constexpr void - set_extension_tp(TLS_CONCEPT &tls) noexcept - { - constexpr bsl::safe_uintmax tls_addr{EXT_TLS_ADDR}; - constexpr bsl::safe_uintmax tls_size{EXT_TLS_SIZE}; - - auto const offs{(tls_size + PAGE_SIZE) * bsl::to_umax(tls.ppid())}; - tls.tp = (tls_addr + offs + PAGE_SIZE).get(); - - m_intrinsic.set_tp(tls.tp); - } - - public: - /// @brief an alias for INTRINSIC_CONCEPT - using intrinsic_type = INTRINSIC_CONCEPT; - /// @brief an alias for PAGE_POOL_CONCEPT - using page_pool_type = PAGE_POOL_CONCEPT; - /// @brief an alias for HUGE_POOL_CONCEPT - using huge_pool_type = HUGE_POOL_CONCEPT; - /// @brief an alias for ROOT_PAGE_TABLE_CONCEPT - using root_page_table_type = ROOT_PAGE_TABLE_CONCEPT; - /// @brief an alias for VPS_POOL_CONCEPT - using vps_pool_type = VPS_POOL_CONCEPT; - /// @brief an alias for VP_POOL_CONCEPT - using vp_pool_type = VP_POOL_CONCEPT; - /// @brief an alias for VM_POOL_CONCEPT - using vm_pool_type = VM_POOL_CONCEPT; - /// @brief an alias for EXT_POOL_CONCEPT - using ext_pool_type = EXT_POOL_CONCEPT; - - /// - /// @brief Creates the microkernel's main class given the global - /// resources that the microkernel will rely on. - /// - /// - /// @param intrinsic the intrinsics to use - /// @param page_pool the page pool to use - /// @param huge_pool the huge pool to use - /// @param system_rpt the system RPT provided by the loader - /// @param vps_pool the vps pool to use - /// @param vp_pool the vp pool to use - /// @param vm_pool the vm pool to use - /// @param ext_pool the extension pool to use - /// - constexpr mk_main( - INTRINSIC_CONCEPT &intrinsic, - PAGE_POOL_CONCEPT &page_pool, - HUGE_POOL_CONCEPT &huge_pool, - ROOT_PAGE_TABLE_CONCEPT &system_rpt, - VPS_POOL_CONCEPT &vps_pool, - VP_POOL_CONCEPT &vp_pool, - VM_POOL_CONCEPT &vm_pool, - EXT_POOL_CONCEPT &ext_pool) noexcept - : m_intrinsic{intrinsic} - , m_page_pool{page_pool} - , m_huge_pool{huge_pool} - , m_system_rpt{system_rpt} - , m_vps_pool{vps_pool} - , m_vp_pool{vp_pool} - , m_vm_pool{vm_pool} - , m_ext_pool{ext_pool} - , m_initialized{} - {} - - /// - /// @brief Initialize all of the global resources the microkernel - /// depends on. - /// - /// - /// @tparam MK_ARGS_CONCEPT the type of mk_args to use - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @param args the loader provided arguments to the microkernel. - /// @param tls the current TLS block - /// @return If the user provided command succeeds, this function - /// will return bsl::exit_success, otherwise this function - /// will return bsl::exit_failure. - /// - template - [[nodiscard]] constexpr auto - initialize(MK_ARGS_CONCEPT *const args, TLS_CONCEPT &tls) noexcept -> bsl::errc_type - { - bsl::errc_type ret{}; - - if (m_initialized) { - m_system_rpt.activate(); - return bsl::errc_success; - } - - bsl::print() << bsl::bold_magenta; - bsl::print() << " ___ __ _ _ \n"; - bsl::print() << "| _ ) __ _ _ _ ___ / _| |__ _ _ _ | |__ \n"; - bsl::print() << "| _ \\/ _` | '_/ -_) _| / _` | ' \\| / / \n"; - bsl::print() << "|___/\\__,_|_| \\___|_| |_\\__,_|_||_|_\\_\\ \n"; - bsl::print() << "\n"; - bsl::print() << bsl::bold_green; - bsl::print() << "Please give us a star on: "; - bsl::print() << bsl::bold_white; - bsl::print() << "https://github.com/Bareflank/hypervisor\n"; - bsl::print() << bsl::reset_color; - bsl::print() << "================================="; - bsl::print() << "================================="; - bsl::print() << "\n"; - bsl::print() << "\n"; - - ret = m_page_pool.initialize(args->page_pool, args->page_pool_base_virt); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - ret = m_huge_pool.initialize(args->huge_pool, args->huge_pool_base_virt); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - ret = m_system_rpt.initialize(&m_intrinsic, &m_page_pool); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - ret = m_system_rpt.add_tables(args->rpt); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - m_system_rpt.activate(); - - ret = m_vps_pool.initialize(); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - ret = m_vp_pool.initialize(); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - ret = m_vm_pool.initialize(); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - ret = m_ext_pool.initialize(args->ext_elf_files, args->online_pps); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - ret = m_ext_pool.start(tls); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - m_initialized = true; - return bsl::errc_success; - } - - /// - /// @brief Process the mk_args_t provided by the loader. - /// If the user provided command succeeds, this function - /// will return bsl::exit_success, otherwise this function - /// will return bsl::exit_failure. - /// - /// - /// @tparam MK_ARGS_CONCEPT the type of mk_args to use - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @param args the loader provided arguments to the microkernel. - /// @param tls the current TLS block - /// @return If the user provided command succeeds, this function - /// will return bsl::exit_success, otherwise this function - /// will return bsl::exit_failure. - /// - template - [[nodiscard]] constexpr auto - process(MK_ARGS_CONCEPT *const args, TLS_CONCEPT &tls) &noexcept -> bsl::exit_code - { - set_extension_sp(tls); - set_extension_tp(tls); - - /// TODO: - /// - Verify the incomings args - /// - - if (bsl::unlikely(!this->initialize(args, tls))) { - bsl::print() << bsl::here(); - return bsl::exit_failure; - } - - if (bsl::unlikely(!m_ext_pool.bootstrap(tls))) { - bsl::print() << bsl::here(); - return bsl::exit_failure; - } - - /// TODO: - /// - Need a way to ensure that vps_run was executed before - /// getting here. Otherwise, nothing at this point makes - /// any sense. - /// - - if (bsl::unlikely(vmexit_loop_entry() != bsl::exit_success)) { - bsl::print() << bsl::here(); - return bsl::exit_failure; - } - - return bsl::exit_success; - - // Tasks: - // [x] implement page_pool_t - // [x] implement page_t - // [x] implement tls_t - // [x] implement thread_id for debugging in BSL - // [x] implement dump_vmm - // [x] implement ELF loader in C++ - // [x] implement vps_pool_t - // [x] implement vps_t - // [x] implement vp_pool_t - // [x] implement vp_t - // [x] implement vm_pool_t - // [x] implement vm_t - // [x] implement root_page_table_t - // [x] implement configurable constants from CMake - // [x] implement clang-format to reorder headers - // [x] implement smep/smap lock - // [x] implement mk stack for syscalls - // [x] implement bsl::hex - // [x] implement _start for extensions - // [x] implement bsl platform logic for extensions - // [x] implement simple debug ops - // [x] implement control ops - // [x] implement handle ops - // [x] implement ext_pool_t - // [x] implement ext_t - // [x] implement exception handlers - // [x] implement syscall exception safety - // [x] implement extension failure reporting to call_ext - // [x] implement esr error code logic - // [x] implement esr.hpp - // [x] implement extension ELF TLS support - // [x] implement some refactoring on the ext_t class - // [x] implement unwind routines for all functions as needed - // [x] implement ELF verification for sanity checking - // [x] implement TLS blocks for each PP - // [x] implement intrinsic class - // [x] implement system_rpt - // [x] implement extension call back for bootstrapping - // [x] implement extension call back wait for events - // [x] implement extension call back for vmexit - // [x] implement creation of VMs - // [x] implement creation of VPs - // [x] implement creation of VPs - // [x] implement creation of VPSs - // [x] implement init VPS as root - // [x] implement read/write VPS state - // [x] implement continued execution with no exits - // [x] implement vps_run / vmexit handler - // [x] implement stopping the hypervisor - // [x] implement fast fail for extension failing before vmrun - // [x] implement fast fail for extension failing after vmrun - // [x] implement fast fail for extension not calling bf_vps_run_op - // [x] implement fast fail callback for extensions - // [x] implement __stack_chk_fail - // [x] implement dump_cpu_state for exception handler - // [x] implement per-PP extension stacks - // [x] implement multicore - // [x] implement removal of extra IDs in syscall interface - // [x] implement active VM - // [x] implement active VP - // [x] implement active VPS - // [x] implement nmi support during demote - // [x] implement per-PP extension TLS blocks - // [x] implement intrinsics syscalls - // [x] implement filtering of GPs for invalid MSR read/write - // [x] implement nmi ESR with an rex64.IRET in the loader - // [x] implement Intel support - // [x] implement nmi support during microkernel execution for Intel - // [x] implement version information using main() args. - // [x] implement fs:xxx for extensions for register/exit data. - // [x] implement run with an error code - // [x] implement simplify the example as much as possible - // [x] implement error on VMX instructions on Intel - // [x] implement error on SVM instructions on AMD - // [x] implement fix for vmexit first crash (vmxoff and check state) - // [x] implement fix for 128 cores on Windows - // [x] implement alloc page - // [ ] implement free page - // [ ] implement TLS functions for ext_id, vmid, vpid and vpsid - // [x] implement virt_to_phys - // [ ] implement debugging mutex/transaction support - // [x] implement Windows support - // [x] implement UEFI support - // [ ] implement huge_pool - // [ ] implement huge - // [ ] implement alloc physically contiguous page - // [ ] implement free physically contiguous page - // [ ] implement per-VM direct maps - // [x] implement reduce the size of the TLS block - // [ ] implement optimizations for release builds - // [ ] implement dump function for AMD vps - // [ ] implement dump functions for all types - // [ ] implement contants for all of the asm logic - // [ ] implement all debug ops - // [ ] implement some basic unit tests - // [ ] implement some basic syscall tests - - // [ ] implement configuration validation - // [ ] implement lock down which MSRs can be read/written - // [ ] implement reproduceable builds - // [ ] implement complete unit tests - // [ ] implement complete syscall tests - // [ ] implement heap support - // [ ] implement IPC support - // [ ] implement nmi support during promote - // [ ] implement remaining todos - // [ ] implement c extension example - // [ ] implement mitigations for transient execution vulnerabilities - } - }; -} - -#endif diff --git a/kernel/src/mk_main_t.hpp b/kernel/src/mk_main_t.hpp new file mode 100644 index 00000000..484bed74 --- /dev/null +++ b/kernel/src/mk_main_t.hpp @@ -0,0 +1,622 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MK_MAIN_HPP +#define MK_MAIN_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace mk +{ + /// @class mk::mk_main_t + /// + /// + /// @brief Provide the main entry point for the microkernel. The + /// microkernel actually starts in the _start function, and immediately + /// creates this class and calls its process() function to boot the + /// microkernel, start the extensions and eventually demote the CPU. + /// Like the other main classes, this class serves to encapsulate + /// the entry logic into something that can be easily tested with no + /// dependencies on global resources. + /// + class mk_main_t final + { + /// @brief stores the root VMID + bsl::safe_uint16 m_root_vmid{}; + /// @brief stores the registered VMExit handler + void *m_ext_vmexit{}; + /// @brief stores the registered fast fail handler + void *m_ext_fail{}; + + /// + /// @brief Verifies that the args and the resulting TLS block + /// make sense. The trampoline code has to fill in a lot of + /// the TLS block to bootstrap, so this provides some simple + /// sanity checks where possible. + /// + /// + /// @param args the loader provided arguments to the microkernel. + /// @param tls the current TLS block + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + verify_args(loader::mk_args_t *const args, tls_t &tls) noexcept -> bsl::errc_type + { + if (args->ppid == syscall::BF_BS_PPID) { + if (bsl::unlikely_assert(syscall::BF_INVALID_ID != tls.active_vmid)) { + bsl::error() << "cannot initialize the BSP more than once" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + if (bsl::unlikely_assert(syscall::BF_INVALID_ID != tls.active_vmid)) { + bsl::error() << "cannot initialize the AP more than once" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(!m_root_vmid)) { + bsl::error() << "cannot initialize an AP due to previous failure" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + bsl::touch(); + } + + if (bsl::unlikely_assert(bsl::to_u16(tls.ppid) != args->ppid)) { + bsl::error() << "tls.ppid [" // -- + << bsl::hex(tls.ppid) // -- + << "] doesn't match the args->ppid [" // -- + << bsl::hex(args->ppid) // -- + << "]" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == tls.ppid)) { + bsl::error() << "tls.ppid [" // -- + << bsl::hex(tls.ppid) // -- + << "] doesn't match the args->ppid [" // -- + << bsl::hex(args->ppid) // -- + << "]" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(bsl::to_u16(tls.online_pps) != args->online_pps)) { + bsl::error() << "tls.online_pps [" // -- + << bsl::hex(tls.online_pps) // -- + << "] doesn't match the args->online_pps [" // -- + << bsl::hex(args->online_pps) // -- + << "]" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(tls.online_pps > bsl::to_u16(HYPERVISOR_MAX_PPS))) { + bsl::error() << "tls.online_pps [" // -- + << bsl::hex(tls.online_pps) // -- + << "] is not less or equal to than the max [" // -- + << bsl::hex(HYPERVISOR_MAX_PPS) // -- + << "]" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(!(bsl::to_u16(args->ppid) < args->online_pps))) { + bsl::error() << "the args->ppid [" // -- + << bsl::hex(args->ppid) // -- + << "] is not less than args->online_pps [" // -- + << bsl::hex(args->online_pps) // -- + << "]" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(nullptr == args->mk_state)) { + bsl::error() << "args->mk_state is null" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(nullptr == args->root_vp_state)) { + bsl::error() << "args->root_vp_state is null" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(nullptr == args->debug_ring)) { + bsl::error() << "args->debug_ring is null" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(args->mk_elf_file.empty())) { + bsl::error() << "args->mk_elf_file is empty" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(args->mk_elf_file.size().is_zero())) { + bsl::error() << "args->mk_elf_file's size is zero" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(!(args->mk_elf_file.size() < HYPERVISOR_MK_CODE_SIZE))) { + bsl::error() << "args->mk_elf_file's size is too big" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(args->ext_elf_files.front().empty())) { + bsl::error() << "args->ext_elf_files.front() is empty" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(args->ext_elf_files.front().size().is_zero())) { + bsl::error() << "args->ext_elf_files.front()'s size is zero" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert( + !(args->ext_elf_files.front().size() < HYPERVISOR_MK_CODE_SIZE))) { + bsl::error() << "args->ext_elf_files.front()'s size is too big" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(nullptr == args->rpt)) { + bsl::error() << "args->rpt is null" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + constexpr auto null_address{0_umax}; + if (bsl::unlikely_assert(null_address == args->rpt_phys)) { + bsl::error() << "args->rpt_phys is 0" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(args->page_pool.empty())) { + bsl::error() << "args->page_pool is empty" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(args->page_pool.size().is_zero())) { + bsl::error() << "args->page_pool's size is zero" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(args->page_pool.size() < HYPERVISOR_PAGE_SIZE)) { + bsl::error() << "args->page_pool's size is too small" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(args->huge_pool.empty())) { + bsl::error() << "args->huge_pool is empty" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(args->huge_pool.size().is_zero())) { + bsl::error() << "args->huge_pool's size is zero" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(args->huge_pool.size() < HYPERVISOR_PAGE_SIZE)) { + bsl::error() << "args->huge_pool's size is too small" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Sets the extension stack pointer given a TLS block, + /// based on what PP we are currently executing on. + /// + /// + /// @param tls the current TLS block + /// + static constexpr void + set_extension_sp(tls_t &tls) noexcept + { + constexpr auto stack_addr{HYPERVISOR_EXT_STACK_ADDR}; + constexpr auto stack_size{HYPERVISOR_EXT_STACK_SIZE}; + + auto const offs{(stack_size + HYPERVISOR_PAGE_SIZE) * bsl::to_umax(tls.ppid)}; + tls.sp = (stack_addr + offs + stack_size).get(); + } + + /// + /// @brief Sets the extension TLS pointer given a TLS block, + /// based on what PP we are currently executing on. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsic_t to use + /// + static constexpr void + set_extension_tp(tls_t &tls, intrinsic_t &intrinsic) noexcept + { + constexpr auto tls_addr{HYPERVISOR_EXT_TLS_ADDR}; + constexpr auto tls_size{HYPERVISOR_EXT_TLS_SIZE}; + + auto const offs{(tls_size + HYPERVISOR_PAGE_SIZE) * bsl::to_umax(tls.ppid)}; + tls.tp = (tls_addr + offs + HYPERVISOR_PAGE_SIZE).get(); + + intrinsic.set_tp(tls.tp); + } + + /// + /// @brief Initialize all of the global resources the microkernel + /// depends on. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param huge_pool the huge_pool_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vm_pool the vm_pool_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param ext_pool the ext_pool_t to use + /// @param system_rpt the system RPT provided by the loader + /// @param args the loader provided arguments to the microkernel. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + tls_t &tls, + page_pool_t &page_pool, + huge_pool_t &huge_pool, + intrinsic_t &intrinsic, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + ext_pool_t &ext_pool, + root_page_table_t &system_rpt, + loader::mk_args_t *const args) noexcept -> bsl::errc_type + { + bsl::errc_type ret{}; + + bsl::print() << bsl::mag << R"( ___ __ _ _ )" + << bsl::endl; + bsl::print() << bsl::mag << R"(| _ ) __ _ _ _ ___ / _| |__ _ _ _ | |__ )" + << bsl::endl; + bsl::print() << bsl::mag << R"(| _ \/ _` | '_/ -_) _| / _` | ' \| / / )" + << bsl::endl; + bsl::print() << bsl::mag << R"(|___/\__,_|_| \___|_| |_\__,_|_||_|_\_\ )" + << bsl::endl; + bsl::print() << bsl::rst << bsl::endl; + bsl::print() << bsl::grn << "Please give us a star on: "; + bsl::print() << bsl::rst << "https://github.com/Bareflank/hypervisor"; + bsl::print() << bsl::rst << bsl::endl; + bsl::print() << bsl::ylw << "================================="; + bsl::print() << bsl::ylw << "================================="; + bsl::print() << bsl::rst << bsl::endl; + bsl::print() << bsl::rst << bsl::endl; + + page_pool.initialize(args->page_pool); + huge_pool.initialize(args->huge_pool); + + ret = system_rpt.initialize(tls, page_pool); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = system_rpt.add_tables(tls, args->rpt); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = vps_pool.initialize(tls, page_pool); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = vp_pool.initialize(tls, vps_pool); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = ext_pool.initialize(tls, page_pool, system_rpt, args->ext_elf_files); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = vm_pool.initialize(tls, page_pool, ext_pool, vp_pool); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + m_root_vmid = vm_pool.allocate(tls, page_pool, ext_pool); + if (bsl::unlikely(!m_root_vmid)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = vm_pool.set_active(tls, m_root_vmid); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + ret = ext_pool.start(tls, intrinsic); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + public: + /// + /// @brief Process the mk_args_t provided by the loader. + /// If the user provided command succeeds, this function + /// will return bsl::exit_success, otherwise this function + /// will return bsl::exit_failure. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param huge_pool the huge_pool_t to use + /// @param intrinsic the intrinsic_t to use + /// @param vm_pool the vm_pool_t to use + /// @param vp_pool the vp_pool_t to use + /// @param vps_pool the vps_pool_t to use + /// @param ext_pool the ext_pool_t to use + /// @param system_rpt the system RPT provided by the loader + /// @param args the loader provided arguments to the microkernel. + /// @return If the user provided command succeeds, this function + /// will return bsl::exit_success, otherwise this function + /// will return bsl::exit_failure. + /// + [[nodiscard]] constexpr auto + process( + tls_t &tls, + page_pool_t &page_pool, + huge_pool_t &huge_pool, + intrinsic_t &intrinsic, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool, + ext_pool_t &ext_pool, + root_page_table_t &system_rpt, + loader::mk_args_t *const args) noexcept -> bsl::exit_code + { + bsl::errc_type ret{}; + + bsl::finally_assert reset_root_vmid_on_error{[this]() noexcept -> void { + m_root_vmid = bsl::safe_uint16::failure(); + }}; + + ret = this->verify_args(args, tls); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::exit_failure; + } + + set_extension_sp(tls); + set_extension_tp(tls, intrinsic); + + if (args->ppid == syscall::BF_BS_PPID) { + ret = this->initialize( + tls, + page_pool, + huge_pool, + intrinsic, + vm_pool, + vp_pool, + vps_pool, + ext_pool, + system_rpt, + args); + + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::exit_failure; + } + + m_ext_vmexit = tls.ext_vmexit; + if (bsl::unlikely(nullptr == m_ext_vmexit)) { + bsl::error() << "a vmexit handler has not been registered" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::exit_failure; + } + + m_ext_fail = tls.ext_fail; + if (bsl::unlikely(nullptr == m_ext_fail)) { + bsl::error() << "a fast fail handler has not been registered" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::exit_failure; + } + + bsl::touch(); + } + else { + ret = vm_pool.set_active(tls, m_root_vmid); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::exit_failure; + } + + tls.ext_vmexit = m_ext_vmexit; + tls.ext_fail = m_ext_fail; + } + + ret = ext_pool.bootstrap(tls, intrinsic); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::exit_failure; + } + + if (bsl::unlikely(syscall::BF_INVALID_ID == tls.active_extid)) { + bsl::error() << "bf_vps_op_run was never executed by an extension" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::exit_failure; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == tls.active_vmid)) { + bsl::error() << "bf_vps_op_run was never executed by an extension" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::exit_failure; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == tls.active_vpid)) { + bsl::error() << "bf_vps_op_run was never executed by an extension" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::exit_failure; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == tls.active_vpsid)) { + bsl::error() << "bf_vps_op_run was never executed by an extension" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::exit_failure; + } + + if (bsl::unlikely_assert(nullptr == tls.active_rpt)) { + bsl::error() << "bf_vps_op_run was never executed by an extension" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::exit_failure; + } + + if (bsl::unlikely(vmexit_loop_entry() != bsl::exit_success)) { + bsl::print() << bsl::here(); + return bsl::exit_failure; + } + + // Unreachable. Only used for unit testing + + reset_root_vmid_on_error.ignore(); + return bsl::exit_success; + } + }; +} + +#endif diff --git a/kernel/src/mk_main_trampoline.cpp b/kernel/src/mk_main_trampoline.cpp deleted file mode 100644 index fd40cc59..00000000 --- a/kernel/src/mk_main_trampoline.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/// @copyright -/// Copyright (C) 2020 Assured Information Security, Inc. -/// -/// @copyright -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// @copyright -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// @copyright -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -/// SOFTWARE. - -#include -#include -#include - -#include -#include -#include -#include -#include - -extern "C" -{ - /// @brief stores the TLS blocks used by the microkernel. - constinit bsl::array g_tls_blocks{}; - - /// @brief provides the stack guard - constinit bsl::uintmax __stack_chk_guard{0xDEADBEEFDEADBEEF}; // NOLINT - - /// TODO: - /// - Find out how the compiler is compiling memset and memcpy and make - /// sure there isn't a faster way to implement these (without SSE). - /// - - /// - /// @brief Same as std::memset. - /// - /// - /// @param dst a pointer to the memory to set - /// @param ch the value to set the memory to - /// @param num the total number of bytes to set - /// @return Returns the same result as std::memset. - /// - [[maybe_unused]] extern "C" auto - memset(void *const dst, bsl::char_type const ch, bsl::uintmax const num) noexcept -> void * - { - return bsl::builtin_memset(dst, ch, num); - } - - /// - /// @brief Same as std::memcpy. - /// - /// - /// @param dst a pointer to the memory to copy to - /// @param src a pointer to the memory to copy from - /// @param count the total number of bytes to copy - /// @return Returns the same result as std::memcpy. - /// - [[maybe_unused]] extern "C" auto - memcpy(void *const dst, void const *const src, bsl::uintmax const count) noexcept -> void * - { - return bsl::builtin_memcpy(dst, src, count); - } -} - -namespace mk -{ - /// - /// @brief Provides the main entry point of the microkernel. This - /// function is called by the loader and is responsible for starting - /// the hypervisor on a specific core - /// - /// - /// @param args the loader provided arguments to the microkernel. - /// @param tls the current TLS block - /// @return Returns bsl::exit_success on success and bsl::exit_failure - /// otherwise - /// - [[nodiscard]] extern "C" auto - mk_main_trampoline(loader::mk_args_t *const args, tls_t *const tls) noexcept -> bsl::exit_code - { - return g_mk_main.process(args, *tls); - } -} diff --git a/kernel/src/msg_halt.cpp b/kernel/src/msg_halt.cpp index c30bca0c..87e8af3a 100644 --- a/kernel/src/msg_halt.cpp +++ b/kernel/src/msg_halt.cpp @@ -33,6 +33,8 @@ namespace mk extern "C" void msg_halt() noexcept { - bsl::print() << " --> " << bsl::bold_red << "Halting!!!\n" << bsl::reset_color; + bsl::print() << bsl::rst << " --> "; + bsl::print() << bsl::red << "Halting!!!"; + bsl::print() << bsl::rst << bsl::endl; } } diff --git a/kernel/src/msg_stack_chk_fail.cpp b/kernel/src/msg_stack_chk_fail.cpp index 7d513bb4..af303e9f 100644 --- a/kernel/src/msg_stack_chk_fail.cpp +++ b/kernel/src/msg_stack_chk_fail.cpp @@ -33,7 +33,7 @@ namespace mk extern "C" void msg_stack_chk_fail() noexcept { - bsl::print() << bsl::bold_red << "...\n\n" << bsl::reset_color; + bsl::print() << bsl::red << "...\n\n" << bsl::rst; bsl::error() << "Stack Overflow Detected!!!\n"; } } diff --git a/kernel/src/page_pool_t.hpp b/kernel/src/page_pool_t.hpp index 18f0fcd0..3d2faa3a 100644 --- a/kernel/src/page_pool_t.hpp +++ b/kernel/src/page_pool_t.hpp @@ -25,93 +25,51 @@ #ifndef PAGE_POOL_T_HPP #define PAGE_POOL_T_HPP +#include +#include +#include +#include +#include + +#include #include #include #include #include -#include -#include -#include -#include -#include +#include +#include #include +#include +#include #include #include namespace mk { + /// @brief stores the max number of records the page pool can store + constexpr auto PAGE_POOL_MAX_RECORDS{9_umax}; + /// @class mk::page_pool_t /// /// /// @brief The page pool is responsible for allocating and freeing - /// pages. The page pool exists in the MK's direct map and so the - /// page pool can also return the physical address of any page - /// that it has allocated. The page pool itself is actually initalized - /// by the loader, which has all of the information about each page - /// in the pool as well as what it's physical address is, which is - /// encoded in the resulting virtual address, thus creating a - /// direct map. The way that the loader sets this page pool up is - /// as follows: + /// pages. The loader provides a linked list with the pages that + /// this code will allocate as requested. Each page exists in the + /// direct map, so all virt to phys translations of allocated pages + /// can be done using simple arithmetic. /// - /// ---------- ---------- ---------- - /// | [] ----|------>| [] ----|------>| | - /// | | | | | | - /// | | | | | | - /// ---------- ---------- ---------- - /// - /// The head (a void *) is actually a pointer to another void *. Each - /// pointer actually points to a page, and it assumes that the first - /// 64bits in the page are a pointer to the next page. This is - /// repeated until the last page is linked which stores a nullptr. - /// To allocate, all you have to do is pop off of the head of the - /// stack and set the new head to the page the popped page was - /// storing. To deallocate, all you have to do is set the page being - /// deallocated to point to the current head, and then set the head - /// to this newly deallocated page. This ensures the page pool can - /// allocate and deallocate in O(1), and there is no metadata that - /// is needed, so no additional overhead. - /// - /// To handle virt to phys and phys to virt conversions, each page - /// is mapped into the microkernel's address space at the physical - /// address + some offset. This means that virt to phys conversions - /// can all be done with simple arithmetic (i.e., no lookups are - /// needed). This is what is typically called a direct map. In other - /// kernels, the direct map has been an issue with respect to attacks - /// like Spectre/Meltdown. In the case of this microkernel, the only - /// memory in the direct map is memory used by the page/huge pools, - /// all of which do not store secrects or VM memory, but instead - /// are used by the microkernel for internal resources, hardware - /// resources and memory to back extensions, all of which should not - /// have secrects in them. On the flip side, kernels typically have - /// more conventional userspace processes and their associated memory - /// as well as kernel memory all mapped into the direct map, which - /// could include secrets like encryption keys, passwords, etc. If - /// secrets are needed, they should be stored in global or stack based - /// memory in the microkernel (not in an extension), and the - /// microkernel should be the only thing working with the unprotected - /// version of the secret. - /// - /// - /// @tparam PAGE_SIZE defines the size of a page - /// - template class page_pool_t final { - /// @brief stores true if initialized() has been executed - bool m_initialized{}; - /// @brief stores the head of the page pool stack. - void *m_head{}; - /// @brief stores the total number of bytes in the page pool. - bsl::safe_uintmax m_size{bsl::safe_uintmax::zero(true)}; - /// @brief stores the virtual address base of the page pool. - bsl::safe_uintmax m_base_virt{bsl::safe_uintmax::zero(true)}; + /// @brief stores the head of the page pool. + loader::page_pool_node_t *m_head{}; + /// @brief stores the total number of bytes given to the page pool. + bsl::safe_uintmax m_size{}; + /// @brief stores information about how memory is allocated + bsl::array m_rcds{}; + /// @brief safe guards operations on the pool. + mutable spinlock_t m_lock{}; public: - /// - /// @brief Default constructor - /// - constexpr page_pool_t() noexcept = default; - /// /// @brief Creates the page pool given a mutable_buffer_t to /// the page pool as well as the virtual address base of the @@ -119,118 +77,35 @@ namespace mk /// /// /// @param pool the mutable_buffer_t of the page pool - /// @param base_virt the base virtual address base of the page pool - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise - /// - [[nodiscard]] constexpr auto - initialize(bsl::span &pool, bsl::safe_uintmax const &base_virt) &noexcept - -> bsl::errc_type - { - if (bsl::unlikely(m_initialized)) { - bsl::error() << "page_pool_t already initialized\n" << bsl::here(); - return bsl::errc_failure; - } - - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); - }}; - - if (bsl::unlikely(pool.empty())) { - m_head = nullptr; - m_size = bsl::safe_uintmax::zero(true); - m_base_virt = bsl::safe_uintmax::zero(true); - - bsl::error() << "pool is empty\n" << bsl::here(); - return bsl::errc_failure; - } - - if (bsl::unlikely(base_virt.is_zero())) { - m_head = nullptr; - m_size = bsl::safe_uintmax::zero(true); - m_base_virt = bsl::safe_uintmax::zero(true); - - bsl::error() << "base_virt is 0 or invalid\n" << bsl::here(); - return bsl::errc_failure; - } - - m_head = pool.data(); - m_size = pool.size(); - m_base_virt = base_virt; - - release_on_error.ignore(); - m_initialized = true; - - return bsl::errc_success; - } - - /// - /// @brief Release the page_pool_t /// constexpr void - release() &noexcept + initialize(bsl::span &pool) noexcept { - m_base_virt = bsl::safe_uintmax::zero(true); - m_size = bsl::safe_uintmax::zero(true); - m_head = {}; - - m_initialized = {}; + m_head = pool.data(); + m_size = pool.size() * HYPERVISOR_PAGE_SIZE; } - /// - /// @brief Destroyes a previously created page_pool_t - /// - constexpr ~page_pool_t() noexcept = default; - - /// - /// @brief copy constructor - /// - /// - /// @param o the object being copied - /// - constexpr page_pool_t(page_pool_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr page_pool_t(page_pool_t &&o) noexcept = default; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(page_pool_t const &o) &noexcept - -> page_pool_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(page_pool_t &&o) &noexcept - -> page_pool_t & = default; - /// /// @brief Allocates a page from the page pool. /// /// - /// @tparam T the type of pointer to return + /// @tparam T the type of pointer to allocate + /// @param tls the current TLS block + /// @param tag the tag to mark the allocation with /// @return Returns a pointer to the newly allocated page /// template [[nodiscard]] constexpr auto - allocate() &noexcept -> T * + allocate(tls_t &tls, bsl::string_view const &tag) noexcept -> T * { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "page_pool_t not initialized\n" << bsl::here(); + static_assert(sizeof(T) == HYPERVISOR_PAGE_SIZE); + lock_guard_t lock{tls, m_lock}; + + if (tag.empty()) { + bsl::error() << "invalid empty tag" // -- + << bsl::endl // -- + << bsl::here(); // -- + return nullptr; } @@ -239,17 +114,52 @@ namespace mk return nullptr; } - void *const ptr{m_head}; - m_head = *static_cast(m_head); + page_pool_record_t *record{}; + for (auto const elem : m_rcds) { + if (nullptr == elem.data->tag) { + record = elem.data; + record->tag = tag.data(); + break; + } - bsl::builtin_memset(ptr, '\0', PAGE_SIZE); + if (tag == elem.data->tag) { + record = elem.data; + break; + } - if constexpr (!bsl::is_void::value) { - static_assert(bsl::is_standard_layout::value, "T must be a standard layout"); - bsl::construct_at(ptr); + bsl::touch(); } - return static_cast(ptr); + if (nullptr == record) { + bsl::error() << "page pool out of space for tags\n" << bsl::here(); + return nullptr; + } + + auto *const node{m_head}; + m_head = m_head->next; + record->usd += HYPERVISOR_PAGE_SIZE; + + /// NOTE: + /// - We need start the lifetime of the object we are allocating. + /// To do this, we first need to end the lifetime of the node + /// itself, which is done using destroy_at. + /// - Next, we need to construct T. This starts the lifetime of + /// T at the address provided by the node. In other words, we + /// now a pointer of type T that has been properly constructed. + /// - Finally, if the type is trivial, we zero the memory of the + /// type. This ensures that all trivial types are properly + /// constructed and cleared as there is no default constructor + /// to initialize the type. + /// + + bsl::destroy_at(node); + auto *const ptr{bsl::construct_at(node)}; + + if (bsl::is_trivial::value) { + return bsl::builtin_memset(ptr, '\0', HYPERVISOR_PAGE_SIZE); + } + + return ptr; } /// @@ -257,28 +167,103 @@ namespace mk /// function to the page pool. /// /// + /// @tparam T the type of pointer to deallocate + /// @param tls the current TLS block /// @param ptr the pointer to the page to deallocate + /// @param tag the tag the allocation was marked with /// + template constexpr void - deallocate(void *const ptr) &noexcept + deallocate(tls_t &tls, T *const ptr, bsl::string_view const &tag) noexcept { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "page_pool_t not initialized\n" << bsl::here(); - return; - } + static_assert(sizeof(T) == HYPERVISOR_PAGE_SIZE); + lock_guard_t lock{tls, m_lock}; if (bsl::unlikely(nullptr == ptr)) { return; } - /// TODO: - /// - If the address is not in the right range (i.e., not the - /// direct map), this function should return and throw up an - /// error and return + page_pool_record_t *record{}; + for (auto const elem : m_rcds) { + if (elem.data->tag == tag) { + record = elem.data; + break; + } + + bsl::touch(); + } + + if (nullptr == record) { + bsl::error() << "invalid tag " // -- + << tag // -- + << bsl::endl // -- + << bsl::here(); // -- + + return; + } + + /// NOTE: + /// - We are given a T *. This should be the same T * that we + /// returned from the allocator. T * is not a node, unless this + /// is the unit test. Before we can use T * as a node, we need + /// to construct T * as a node, the same way that we constructed + /// the T * in the first place. To do that, we must first end + /// the lifetime of the provided T *. + /// - Next, we construct a node using the memory from T *. This + /// beings the lifetime of our node. + /// - Finally, we add the node to the linked list. + /// - You might be wondering why we simply do not use a static_cast. + /// If the types are POD types, a static_cast using void * would + /// be enough without invoking undefined behavior. The use of + /// void * in a constexpr is not allowed however. To overcome + /// this, we properly handle the lifetime of the objects that + /// we are using. The unit test only ever sees nodes, so to the + /// unit test, the page allocator looks like a linked list that + /// outputs nodes using a stack like process. This is enough to + /// ensure that the page pool never invokes UB, and is handling + /// the allocations properly. The runtime logic is able to change + /// the types from T to node without issue and without using UB. + /// No reinterpret_cast is ever needed to make this work. The + /// rest of the code that uses the page pool during unit testing + /// will use a mocked version of the page pool that uses new and + /// delete to properly create a constexpr friendly version of T. /// - *static_cast(ptr) = m_head; - m_head = ptr; + bsl::destroy_at(ptr); + auto *const node{bsl::construct_at(ptr)}; + + node->next = m_head; + m_head = node; + record->usd -= HYPERVISOR_PAGE_SIZE; + } + + /// + /// @brief Returns the number of bytes allocated for a given tag. + /// + /// + /// @param tls the current TLS block + /// @param tag the tag the allocation was marked with + /// @return Returns the number of bytes allocated for a given tag. + /// + [[nodiscard]] constexpr auto + allocated(tls_t &tls, bsl::string_view const &tag) noexcept -> bsl::safe_uintmax + { + lock_guard_t lock{tls, m_lock}; + + for (auto const elem : m_rcds) { + if (elem.data->tag == tag) { + return elem.data->usd; + } + + bsl::touch(); + } + + bsl::error() << "invalid tag " // -- + << tag // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); } /// @@ -297,27 +282,10 @@ namespace mk /// template [[nodiscard]] constexpr auto - virt_to_phys(T const virt) const &noexcept -> bsl::safe_uintmax + virt_to_phys(T const *const virt) const noexcept -> bsl::safe_uintmax { - static_assert(bsl::is_pointer::value); - static_assert(bsl::is_standard_layout::value); - - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "page_pool_t not initialized\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); - } - - auto const ret{bsl::to_umax(virt) - m_base_virt}; - if (bsl::unlikely(!ret)) { - bsl::error() << "virtual to physical address conversion failed for " // -- - << virt // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::safe_uintmax::zero(true); - } - - return ret; + static_assert(sizeof(T) == HYPERVISOR_PAGE_SIZE); + return bsl::to_umax(virt) - HYPERVISOR_MK_PAGE_POOL_ADDR; } /// @@ -336,27 +304,149 @@ namespace mk /// template [[nodiscard]] constexpr auto - phys_to_virt(bsl::safe_uintmax const &phys) const &noexcept -> T + phys_to_virt(bsl::safe_uintmax const &phys) const noexcept -> T * { - static_assert(bsl::is_pointer::value); - static_assert(bsl::is_standard_layout::value); + static_assert(sizeof(T) == HYPERVISOR_PAGE_SIZE); + return bsl::to_ptr(phys + HYPERVISOR_MK_PAGE_POOL_ADDR); + } - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "page_pool_t not initialized\n" << bsl::here(); - return nullptr; + /// + /// @brief Dumps the page_pool_t + /// + constexpr void + dump() const noexcept + { + constexpr auto kb{1024_umax}; + constexpr auto mb{kb * kb}; + + bsl::print() << bsl::mag << "page pool dump: "; + bsl::print() << bsl::rst << bsl::endl; + + /// Header + /// + + bsl::print() << bsl::ylw << "+----------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::blu << bsl::fmt{"^33s", "overview "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+----------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^23s", "description "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^8s", "value "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+----------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::safe_uintmax usd{}; + for (auto const elem : m_rcds) { + usd += elem.data->usd; } - auto const ret{phys + m_base_virt}; - if (bsl::unlikely(!ret)) { - bsl::error() << "physical to virtual address conversion failed for " // -- - << bsl::hex(phys) // -- - << bsl::endl // -- - << bsl::here(); // -- + /// Total + /// - return nullptr; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<23s", "total "}; + bsl::print() << bsl::ylw << "| "; + if ((m_size / mb).is_zero()) { + bsl::print() << bsl::rst << bsl::fmt{"4d", m_size / kb} << " KB "; + } + else { + bsl::print() << bsl::rst << bsl::fmt{"4d", m_size / mb} << " MB "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Used + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<23s", "used "}; + bsl::print() << bsl::ylw << "| "; + if ((usd / mb).is_zero()) { + bsl::print() << bsl::rst << bsl::fmt{"4d", usd / kb} << " KB "; + } + else { + bsl::print() << bsl::rst << bsl::fmt{"4d", usd / mb} << " MB "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Remaining + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<23s", "remaining "}; + bsl::print() << bsl::ylw << "| "; + if (((m_size - usd) / mb).is_zero()) { + bsl::print() << bsl::rst << bsl::fmt{"4d", (m_size - usd) / kb} << " KB "; + } + else { + bsl::print() << bsl::rst << bsl::fmt{"4d", (m_size - usd) / mb} << " MB "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Tags + /// + + bsl::print() << bsl::ylw << "+----------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::rst << bsl::endl; + bsl::print() << bsl::ylw << "+----------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::blu << bsl::fmt{"^33s", "breakdown "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+----------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^23s", "description "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^8s", "value "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+----------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + for (auto const elem : m_rcds) { + if (nullptr == elem.data->tag) { + continue; + } + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<23s", elem.data->tag}; + bsl::print() << bsl::ylw << "| "; + if ((elem.data->usd / mb).is_zero()) { + bsl::print() << bsl::rst << bsl::fmt{"4d", elem.data->usd / kb} << " KB "; + } + else { + bsl::print() << bsl::rst << bsl::fmt{"4d", elem.data->usd / mb} << " MB "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; } - return bsl::to_ptr(ret); + /// Footer + /// + + bsl::print() << bsl::ylw << "+----------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; } }; } diff --git a/runtime/include/bsl/details/print_thread_id.hpp b/kernel/src/serial_write.hpp similarity index 61% rename from runtime/include/bsl/details/print_thread_id.hpp rename to kernel/src/serial_write.hpp index 2a5f3dbc..7cae44e0 100644 --- a/runtime/include/bsl/details/print_thread_id.hpp +++ b/kernel/src/serial_write.hpp @@ -22,39 +22,34 @@ /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE /// SOFTWARE. -#ifndef RUNTIME_BSL_DETAILS_PRINT_THREAD_ID_HPP -#define RUNTIME_BSL_DETAILS_PRINT_THREAD_ID_HPP +#ifndef SERIAL_WRITE_HPP +#define SERIAL_WRITE_HPP -#include +#include -#include +#include +#include #include #include -namespace bsl::details +namespace mk { /// - /// @brief Outputs the current thread ID info + /// @brief Outputs a string to the serial port. /// /// - /// @tparam T the type of outputter provided - /// @param o the outputter + /// @param str the string to output /// - template constexpr void - print_thread_id(out const o) noexcept + serial_write(bsl::cstr_type const str) noexcept { - if (is_constant_evaluated()) { + if (bsl::is_constant_evaluated()) { return; } - auto const thread_id{syscall::bf_tls_thread_id()}; - - o << " [" // -- - << bsl::cyan << bsl::fmt("#018x", thread_id) << bsl::reset_color // -- - << " - " // -- - << bsl::blue << "US" << bsl::reset_color // -- - << ']'; // -- + for (bsl::safe_uintmax i{}; str[i.get()] != '\0'; ++i) { + serial_write_c(str[i.get()]); + } } } diff --git a/kernel/src/spinlock_t.hpp b/kernel/src/spinlock_t.hpp new file mode 100644 index 00000000..3c874540 --- /dev/null +++ b/kernel/src/spinlock_t.hpp @@ -0,0 +1,273 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef SPINLOCK_T_HPP +#define SPINLOCK_T_HPP + +#include +#include +#include + +#include +#include +#include +#include + +#pragma clang diagnostic ignored "-Watomic-implicit-seq-cst" + +namespace mk +{ + /// @brief defines when an esr has not executed + constexpr auto SPINLOCK_ESR_NOT_EXECUTED{0_umax}; + + /// @class mk::spinlock_t + /// + /// + /// @brief Implements a spinlock_t + /// + /// + /// @note This spinlock_t is designed to detect and prevent deadlock + /// when the same PP attempts to take the lock more than once. This + /// could occur for example if a hardware exception fires before + /// the lock is released. It also handles the case when the lock is + /// taken, and then an ESR fires that is legit and must take the + /// lock as well. + /// + class spinlock_t final + { + /// @brief stores the ppid that currently owns the lock (non-ESR) + bsl::safe_uint16 m_std_ppid; + /// @brief stores the ppid that currently owns the lock (ESR) + bsl::safe_uint16 m_esr_ppid; + /// @brief stores whether or not the lock is acquired + _Atomic bool m_flag; + + public: + /// + /// @brief Default constructor. + /// + // We cannot member initialize atomics so this is not possible + // NOLINTNEXTLINE(bsl-class-member-init) + constexpr spinlock_t() noexcept // -- + : m_std_ppid{bsl::safe_uint16::failure()}, m_esr_ppid{bsl::safe_uint16::failure()} + { + // This is the only way to initialize this + // NOLINTNEXTLINE(bsl-implicit-conversions-forbidden) + m_flag = false; + } + + /// + /// @brief Destructor + /// + constexpr ~spinlock_t() noexcept = default; + + /// + /// @brief copy constructor + /// + /// + /// @param o the object being copied + /// + constexpr spinlock_t(spinlock_t const &o) noexcept = delete; + + /// + /// @brief move constructor + /// + /// + /// @param o the object being moved + /// + constexpr spinlock_t(spinlock_t &&o) noexcept = default; + + /// + /// @brief copy assignment + /// + /// + /// @param o the object being copied + /// @return a reference to *this + /// + [[maybe_unused]] auto operator=(spinlock_t const &o) &noexcept -> spinlock_t & = delete; + + /// + /// @brief move assignment + /// + /// + /// @param o the object being moved + /// @return a reference to *this + /// + [[maybe_unused]] auto operator=(spinlock_t &&o) &noexcept -> spinlock_t & = default; + + /// + /// @brief Locks the spinlock_t. This will not return until the + /// spinlock_t can be successfully acquired. + /// + /// + /// @param tls the current TLS block + /// + constexpr void + lock(tls_t const &tls) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + /// NOTE: + /// - Perform deadlock detection. If deadlock is detected, we + /// return as it means that this PP has already acquired the + /// lock with no means that unlock. + /// + + if (tls.ppid == m_std_ppid) { + if (tls.esr_ip != SPINLOCK_ESR_NOT_EXECUTED) { + if (!m_esr_ppid) { + m_esr_ppid = tls.ppid; + return; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + + bsl::alert() << "pp " // -- + << bsl::hex(tls.ppid) // -- + << " acquired the same lock more than once" // -- + << bsl::endl; // -- + + return; + } + + if (tls.ppid == m_esr_ppid) { + if (tls.esr_ip == SPINLOCK_ESR_NOT_EXECUTED) { + m_std_ppid = tls.ppid; + return; + } + + bsl::alert() << "pp " // -- + << bsl::hex(tls.ppid) // -- + << " acquired the same lock more than once" // -- + << bsl::endl; // -- + + return; + } + + /// NOTE: + /// - The __c11_atomic_exchange here attempts to set the lock to + /// true. If it is already true, __c11_atomic_exchange will + /// return true, which means that the lock was already taken + /// by another PP. If this occurs, we need to wait until the + /// value that __c11_atomic_exchange returns is false, meaning + /// the lock was released. If __c11_atomic_exchange returns + /// false right off the bat, it means that the lock was never + /// taken at all, and there is nothing else to do. + /// - The call to __c11_atomic_load reads the value of the lock, + /// and will continue to loop while the lock is true, meaning + /// it is held by another PP. The reason that __c11_atomic_load + /// is called instead of just looping using __c11_atomic_exchange + /// all the time is __c11_atomic_exchange uses a fence to ensure + /// proper ordering which is expensive. __c11_atomic_load in + /// this case, since we used __ATOMIC_RELAXED does not include + /// the fence, and so it can loop without killing the pipeline. + /// - The only issue with this implementation is that once the + /// call to __c11_atomic_load returns, we still have not acquired + /// the lock as this is what __c11_atomic_exchange does. It is + /// possible that between when __c11_atomic_load returns and + /// __c11_atomic_exchange executes, another PP will have grabbed + /// the lock. Research has shown however that even with this + /// issue, this implemenation is the best for a spinlock_t WRT + /// overall performance. + /// + + while (__c11_atomic_exchange(&m_flag, true, __ATOMIC_ACQUIRE)) { + while (__c11_atomic_load(&m_flag, __ATOMIC_RELAXED)) { + yield(); + } + } + + if (tls.esr_ip == SPINLOCK_ESR_NOT_EXECUTED) { + m_std_ppid = tls.ppid; + } + else { + m_esr_ppid = tls.ppid; + } + } + + /// + /// @brief Unlocks the spinlock_t. + /// + /// + /// @param tls the current TLS block + /// + constexpr void + unlock(tls_t const &tls) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + /// NOTE: + /// - Before we release the lock, we need to make sure that + /// we are not holding the lock in both the normal case, + /// and the ESR case. If both have been released, we are clear + /// to release the lock. + /// + + if (tls.esr_ip == SPINLOCK_ESR_NOT_EXECUTED) { + m_std_ppid = bsl::safe_uint16::failure(); + } + else { + m_esr_ppid = bsl::safe_uint16::failure(); + } + + if (!!m_std_ppid) { + return; + } + + if (!!m_esr_ppid) { + return; + } + + /// NOTE: + /// - Here, we simply need to set the lock flag to false, + /// indicating that we no longer are holding the lock. We + /// use __ATOMIC_RELEASE to ensure proper memory ordering. + /// + + __c11_atomic_store(&m_flag, false, __ATOMIC_RELEASE); + } + + /// + /// @brief Returns true if the spinlock_t is locked + /// + /// + /// @return Returns true if the spinlock_t is locked + /// + [[nodiscard]] constexpr auto + is_locked() const noexcept -> bool + { + return static_cast(m_flag); + } + }; +} + +#endif diff --git a/kernel/src/vm_pool_t.hpp b/kernel/src/vm_pool_t.hpp index 5e241e58..f4472be9 100644 --- a/kernel/src/vm_pool_t.hpp +++ b/kernel/src/vm_pool_t.hpp @@ -25,177 +25,138 @@ #ifndef VM_POOL_T_HPP #define VM_POOL_T_HPP +#include "lock_guard_t.hpp" +#include "spinlock_t.hpp" + +#include +#include +#include +#include +#include + #include #include #include -#include +#include #include +#include namespace mk { /// @class mk::vm_pool_t /// /// - /// @brief TODO + /// @brief Defines the microkernel's VM pool /// - /// - /// @tparam VM_CONCEPT the type of vm_t that this class manages. - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use - /// @tparam MAX_VMS the max number of VMs supported - /// - template class vm_pool_t final { - /// @brief stores true if initialized() has been executed - bool m_initialized; - /// @brief stores a reference to the page pool to use - PAGE_POOL_CONCEPT &m_page_pool; - /// @brief stores the first VM_CONCEPT in the VM_CONCEPT linked list - VM_CONCEPT *m_head; - /// @brief stores the VM_CONCEPTs in the VM_CONCEPT linked list - bsl::array m_pool; + /// @brief stores the pool of vm_ts + bsl::array m_pool{}; + /// @brief safe guards operations on the pool. + mutable spinlock_t m_lock{}; public: - /// @brief an alias for VM_CONCEPT - using vm_type = VM_CONCEPT; - /// @brief an alias for PAGE_POOL_CONCEPT - using page_pool_type = PAGE_POOL_CONCEPT; - - /// - /// @brief Creates a vm_pool_t - /// - /// - /// @param page_pool the page pool to use - /// - explicit constexpr vm_pool_t(PAGE_POOL_CONCEPT &page_pool) noexcept - : m_initialized{}, m_page_pool{page_pool}, m_head{}, m_pool{} - {} - /// /// @brief Initializes this vm_pool_t /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param ext_pool the extension pool to use + /// @param vp_pool the VP pool to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - initialize() &noexcept -> bsl::errc_type + initialize( + tls_t &tls, page_pool_t &page_pool, ext_pool_t &ext_pool, vp_pool_t &vp_pool) noexcept + -> bsl::errc_type { - bsl::errc_type ret{}; + bsl::finally_assert release_on_error{ + [this, &tls, &page_pool, &ext_pool, &vp_pool]() noexcept -> void { + auto const ret{this->release(tls, page_pool, ext_pool, vp_pool)}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return; + } - if (bsl::unlikely(m_initialized)) { - bsl::error() << "vm_pool_t already initialized\n" << bsl::here(); - return bsl::errc_failure; - } + bsl::touch(); + }}; - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); - }}; - - VM_CONCEPT *prev{}; for (auto const vm : m_pool) { - ret = vm.data->initialize(&m_page_pool, bsl::to_u16(vm.index)); - if (bsl::unlikely(!ret)) { + auto const ret{vm.data->initialize(tls, bsl::to_u16(vm.index))}; + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (nullptr != prev) { - prev->set_next(vm.data); - } - else { - m_head = vm.data; - } - - prev = vm.data; + bsl::touch(); } release_on_error.ignore(); - m_initialized = true; + return bsl::errc_success; + } + + /// + /// @brief Release the vm_pool_t. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param ext_pool the extension pool to use + /// @param vp_pool the VP pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + release( + tls_t &tls, page_pool_t &page_pool, ext_pool_t &ext_pool, vp_pool_t &vp_pool) noexcept + -> bsl::errc_type + { + for (auto const vm : m_pool) { + auto const ret{vm.data->release(tls, page_pool, ext_pool, vp_pool)}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } return bsl::errc_success; } /// - /// @brief Release the vm_t - /// - constexpr void - release() &noexcept - { - for (auto const vm : m_pool) { - vm.data->release(); - } - - m_head = {}; - m_initialized = {}; - } - - /// - /// @brief Destroyes a previously created vm_pool_t - /// - constexpr ~vm_pool_t() noexcept = default; - - /// - /// @brief copy constructor - /// - /// - /// @param o the object being copied - /// - constexpr vm_pool_t(vm_pool_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr vm_pool_t(vm_pool_t &&o) noexcept = default; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vm_pool_t const &o) &noexcept - -> vm_pool_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vm_pool_t &&o) &noexcept -> vm_pool_t & = default; - - /// - /// @brief Allocates a vm from the vm pool. We set the allocated - /// vm_t's next() to itself, which indicates that it has been - /// allocated. + /// @brief Allocates a vm from the vm pool. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param ext_pool the extension pool to use /// @return Returns ID of the newly allocated vm /// [[nodiscard]] constexpr auto - allocate() &noexcept -> bsl::safe_uint16 + allocate(tls_t &tls, page_pool_t &page_pool, ext_pool_t &ext_pool) noexcept + -> bsl::safe_uint16 { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "vm_pool_t not initialized\n" << bsl::here(); - return bsl::safe_uint16::zero(true); + lock_guard_t lock{tls, m_lock}; + + vm_t *vm{}; + for (auto const elem : m_pool) { + if (elem.data->is_deallocated()) { + vm = elem.data; + break; + } + + bsl::touch(); } - if (bsl::unlikely(nullptr == m_head)) { + if (bsl::unlikely(nullptr == vm)) { bsl::error() << "vm pool out of vms\n" << bsl::here(); - return bsl::safe_uint16::zero(true); + return bsl::safe_uint16::failure(); } - auto *const vm{m_head}; - m_head = m_head->next(); - - vm->set_next(vm); - return vm->id(); + return vm->allocate(tls, page_pool, ext_pool); } /// @@ -203,43 +164,313 @@ namespace mk /// function to the vm pool. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param vp_pool the VP pool to use + /// @param ext_pool the extension pool to use /// @param vmid the ID of the vm to deallocate /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - deallocate(bsl::safe_uint16 const &vmid) &noexcept -> bsl::errc_type + deallocate( + tls_t &tls, + page_pool_t &page_pool, + vp_pool_t &vp_pool, + ext_pool_t &ext_pool, + bsl::safe_uint16 const &vmid) noexcept -> bsl::errc_type { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "vm_pool_t not initialized\n" << bsl::here(); - return bsl::errc_failure; - } - auto *const vm{m_pool.at_if(bsl::to_umax(vmid))}; if (bsl::unlikely(nullptr == vm)) { - bsl::error() << "invalid vmid: " // -- - << bsl::hex(vmid) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() + << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::errc_failure; + return bsl::errc_index_out_of_bounds; } - if (vm->next() != vm) { - bsl::error() << "vm with id " // -- - << bsl::hex(vmid) // -- - << " was never allocated" // -- - << bsl::endl // -- - << bsl::here(); // -- + return vm->deallocate(tls, page_pool, vp_pool, ext_pool); + } - return bsl::errc_failure; + /// + /// @brief Sets the requested vm_t's status as zombified, meaning + /// it is no longer usable. + /// + /// + /// @param vmid the ID of the vm_t to set as a zombie + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + zombify(bsl::safe_uint16 const &vmid) noexcept -> bsl::errc_type + { + auto *const vm{m_pool.at_if(bsl::to_umax(vmid))}; + if (bsl::unlikely(nullptr == vm)) { + bsl::error() + << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_index_out_of_bounds; } - vm->set_next(m_head); - m_head = vm; - + vm->zombify(); return bsl::errc_success; } + + /// + /// @brief Returns true if the requested vm_t is deallocated, false + /// if the provided VMID is invalid, or if the vm_t is not + /// deallocated. + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID of the vm_t to query + /// @return Returns true if the requested vm_t is deallocated, false + /// if the provided VMID is invalid, or if the vm_t is not + /// deallocated. + /// + [[nodiscard]] constexpr auto + is_deallocated(tls_t &tls, bsl::safe_uint16 const &vmid) const noexcept -> bool + { + bsl::discard(tls); + + auto const *const vm{m_pool.at_if(bsl::to_umax(vmid))}; + if (bsl::unlikely(nullptr == vm)) { + bsl::error() + << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vm->is_deallocated(); + } + + /// + /// @brief Returns true if the requested vm_t is allocated, false + /// if the provided VMID is invalid, or if the vm_t is not + /// allocated. + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID of the vm_t to query + /// @return Returns true if the requested vm_t is allocated, false + /// if the provided VMID is invalid, or if the vm_t is not + /// allocated. + /// + [[nodiscard]] constexpr auto + is_allocated(tls_t &tls, bsl::safe_uint16 const &vmid) const noexcept -> bool + { + bsl::discard(tls); + + auto const *const vm{m_pool.at_if(bsl::to_umax(vmid))}; + if (bsl::unlikely(nullptr == vm)) { + bsl::error() + << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vm->is_allocated(); + } + + /// + /// @brief Returns true if the requested vm_t is a zombie, false + /// if the provided VMID is invalid, or if the vm_t is not + /// a zombie. + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID of the vm_t to query + /// @return Returns true if the requested vm_t is a zombie, false + /// if the provided VMID is invalid, or if the vm_t is not + /// a zombie. + /// + [[nodiscard]] constexpr auto + is_zombie(tls_t &tls, bsl::safe_uint16 const &vmid) const noexcept -> bool + { + bsl::discard(tls); + + auto const *const vm{m_pool.at_if(bsl::to_umax(vmid))}; + if (bsl::unlikely(nullptr == vm)) { + bsl::error() + << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vm->is_zombie(); + } + + /// + /// @brief Sets the requested vm_t as active. + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID of the vm_t to set as active + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_active(tls_t &tls, bsl::safe_uint16 const &vmid) noexcept -> bsl::errc_type + { + auto *const vm{m_pool.at_if(bsl::to_umax(vmid))}; + if (bsl::unlikely(nullptr == vm)) { + bsl::error() + << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_index_out_of_bounds; + } + + return vm->set_active(tls); + } + + /// + /// @brief Sets the requested vm_t as inactive. + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID of the vm_t to set as inactive + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_inactive(tls_t &tls, bsl::safe_uint16 const &vmid) noexcept -> bsl::errc_type + { + auto *const vm{m_pool.at_if(bsl::to_umax(vmid))}; + if (bsl::unlikely(nullptr == vm)) { + bsl::error() + << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_index_out_of_bounds; + } + + return vm->set_inactive(tls); + } + + /// + /// @brief Returns the ID of the first PP identified that the + /// requested vm_t is still active on. If the vm_t is inactive, this + /// function returns bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID of the vm_t to query + /// @return Returns the ID of the first PP identified that the + /// requested vm_t is still active on. If the vm_t is inactive, this + /// function returns bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_active(tls_t &tls, bsl::safe_uint16 const &vmid) const noexcept -> bsl::safe_uint16 + { + auto const *const vm{m_pool.at_if(bsl::to_umax(vmid))}; + if (bsl::unlikely(nullptr == vm)) { + bsl::error() + << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + return vm->is_active(tls); + } + + /// + /// @brief Returns true if the requested vm_t is active on the + /// current PP, false if the provided ID is invalid, or if the + /// vm_t is not active on the current PP. + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID of the vm_t to query + /// @return Returns true if the requested vm_t is active on the + /// current PP, false if the provided ID is invalid, or if the + /// vm_t is not active on the current PP. + /// + [[nodiscard]] constexpr auto + is_active_on_current_pp(tls_t &tls, bsl::safe_uint16 const &vmid) const noexcept -> bool + { + auto const *const vm{m_pool.at_if(bsl::to_umax(vmid))}; + if (bsl::unlikely(nullptr == vm)) { + bsl::error() + << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vm->is_active_on_current_pp(tls); + } + + /// + /// @brief Dumps the requested VM + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID of the VM to dump + /// + constexpr void + dump(tls_t &tls, bsl::safe_uint16 const &vmid) const noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + + auto const *const vm{m_pool.at_if(bsl::to_umax(vmid))}; + if (bsl::unlikely(nullptr == vm)) { + bsl::error() + << "vmid " // -- + << bsl::hex(vmid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VMS " // -- + << bsl::hex(HYPERVISOR_MAX_VMS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return; + } + + vm->dump(tls); + } }; } diff --git a/kernel/src/vm_t.hpp b/kernel/src/vm_t.hpp index e43bf81d..23a1a307 100644 --- a/kernel/src/vm_t.hpp +++ b/kernel/src/vm_t.hpp @@ -25,137 +25,179 @@ #ifndef VM_T_HPP #define VM_T_HPP +#include "lock_guard_t.hpp" +#include "spinlock_t.hpp" + +#include +#include +#include +#include +#include + +#include #include #include #include #include #include +#include namespace mk { - /// @brief defines the value of an invalid VMID - constexpr bsl::safe_uint16 INVALID_VMID{bsl::to_u16(0xFFFFU)}; - /// @class mk::vm_t /// /// - /// @brief TODO + /// @brief Defines the microkernel's notion of a VM. Unlike a VP or + /// VPS, a VM can be run on any PP at any time and in any combination. + /// For example, you could have PPs 0-2 running VM1 and PPs 3-4 + /// running VM2. A VM is not dedicated to any specific PP. A VP and + /// VPS are different. They are assigned to a specific VM and a + /// specific PP (well, a VP is assigned to a VM and a PP, and a VPS + /// is assigned to a VP and PP, and so there for a VPS is indirectly + /// assigned to a VM since it's parent VP is). VM assignment for a + /// VP and VPS cannot change. The only way to change it is to + /// deallocate the VP or VPS and they allocate it later as a new + /// resource. PP reassignment is done through migration. Basically, + /// the VP is migrated to a new PP, and then any time you try to + /// run a VPS, if the PP doesn't match the VP's PP, it is migrated + /// at that time, which is used to not only prevent the microkernel + /// from performing migration on VPSs that don't need it, but it + /// also ensures that the VPS is cleared and loaded on the PP that + /// it is being migrated to, which is a requirement for Intel. In + /// otherwords on Intel, you have to clear the VPS and then load the + /// VPS on the PP you plan to run VMLaunch on, which means that + /// migration has to occur on the PP you plan to use. /// - /// - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use + /// So based on the above, we have to track which PP the VM is active + /// on as it can be active on a lot of PPs, where as with a VP and + /// VPS, we only have to track if it is active or not since it can + /// only be active on one PP at a time. /// - template class vm_t final { - /// @brief stores true if initialized() has been executed - bool m_initialized{}; - /// @brief stores a reference to the page pool to use - PAGE_POOL_CONCEPT *m_page_pool{}; /// @brief stores the ID associated with this vm_t - bsl::safe_uint16 m_id{bsl::safe_uint16::zero(true)}; - /// @brief stores the next vm_t in the vm_pool_t linked list - vm_t *m_next{}; + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + /// @brief stores whether or not this vm_t is allocated. + allocated_status_t m_allocated{allocated_status_t::deallocated}; + /// @brief stores whether or not this vm_t is active. + bsl::array m_active{}; + /// @brief safe guards operations on the pool. + mutable spinlock_t m_lock; public: - /// @brief an alias for PAGE_POOL_CONCEPT - using page_pool_type = PAGE_POOL_CONCEPT; - - /// - /// @brief Default constructor - /// - constexpr vm_t() noexcept = default; - /// /// @brief Initializes this vm_t /// /// - /// @param page_pool the page pool to use + /// @param tls the current TLS block /// @param i the ID for this vm_t /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - initialize(PAGE_POOL_CONCEPT *const page_pool, bsl::safe_uint16 const &i) &noexcept - -> bsl::errc_type + initialize(tls_t &tls, bsl::safe_uint16 const &i) noexcept -> bsl::errc_type { - if (bsl::unlikely(m_initialized)) { + bsl::discard(tls); + + if (bsl::unlikely_assert(m_id)) { bsl::error() << "vm_t already initialized\n" << bsl::here(); - return bsl::errc_failure; + return bsl::errc_precondition; } - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); - }}; + if (bsl::unlikely_assert(!i)) { + bsl::error() << "invalid id\n" << bsl::here(); + return bsl::errc_precondition; + } - m_page_pool = page_pool; - if (bsl::unlikely(nullptr == m_page_pool)) { - bsl::error() << "invalid page_pool\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == i)) { + bsl::error() << "id " // -- + << bsl::hex(i) // -- + << " is invalid and cannot be used for initialization" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; } m_id = i; - if (bsl::unlikely(!i)) { - bsl::error() << "invalid id\n" << bsl::here(); - return bsl::errc_failure; - } - - release_on_error.ignore(); - m_initialized = true; - return bsl::errc_success; } /// - /// @brief Release the vm_t + /// @brief Release the vm_t. /// - constexpr void - release() &noexcept + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param ext_pool the extension pool to use + /// @param vp_pool the VP pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + release( + tls_t &tls, page_pool_t &page_pool, ext_pool_t &ext_pool, vp_pool_t &vp_pool) noexcept + -> bsl::errc_type { - m_next = {}; - m_id = bsl::safe_uint16::zero(true); - m_page_pool = {}; - m_initialized = {}; + bsl::errc_type ret{}; + lock_guard_t lock{tls, m_lock}; + + if (syscall::BF_ROOT_VMID == m_id) { + return bsl::errc_success; + } + + if (this->is_zombie()) { + return bsl::errc_success; + } + + tls.state_reversal_required = true; + bsl::finally zombify_on_error{[this]() noexcept -> void { + this->zombify(); + }}; + + auto const vpid{vp_pool.is_assigned_to_vm(tls, m_id)}; + if (bsl::unlikely(vpid)) { + bsl::error() << "vp " // -- + << bsl::hex(vpid) // -- + << " is assigned to vm " // -- + << bsl::hex(m_id) // -- + << " and therefore vm " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + auto const active_ppid{this->is_active(tls)}; + if (bsl::unlikely(active_ppid)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << " is active on pp " // -- + << bsl::hex(active_ppid) // -- + << " and therefore vm " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + ret = ext_pool.signal_vm_destroyed(tls, page_pool, m_id); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + m_allocated = allocated_status_t::deallocated; + m_id = bsl::safe_uint16::failure(); + + zombify_on_error.ignore(); + return bsl::errc_success; } - /// - /// @brief Destructor - /// - constexpr ~vm_t() noexcept = default; - - /// - /// @brief copy constructor - /// - /// - /// @param o the object being copied - /// - constexpr vm_t(vm_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr vm_t(vm_t &&o) noexcept = default; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vm_t const &o) &noexcept -> vm_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vm_t &&o) &noexcept -> vm_t & = default; - /// /// @brief Returns the ID of this vm_t /// @@ -163,33 +205,508 @@ namespace mk /// @return Returns the ID of this vm_t /// [[nodiscard]] constexpr auto - id() const &noexcept -> bsl::safe_uint16 const & + id() const noexcept -> bsl::safe_uint16 const & { return m_id; } /// - /// @brief Returns the next vm_t in the vm_pool_t linked list + /// @brief Allocates this vm_t /// /// - /// @return Returns the next vm_t in the vm_pool_t linked list + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param ext_pool the extension pool to use + /// @return Returns ID of the newly allocated vm /// [[nodiscard]] constexpr auto - next() const &noexcept -> vm_t * + allocate(tls_t &tls, page_pool_t &page_pool, ext_pool_t &ext_pool) noexcept + -> bsl::safe_uint16 { - return m_next; + bsl::errc_type ret{}; + lock_guard_t lock{tls, m_lock}; + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vm_t not initialized\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::zombie)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << " is a zombie and cannot be allocated" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::allocated)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << " is already allocated and cannot be created" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + tls.state_reversal_required = true; + tls.log_vmid = m_id.get(); + + ret = ext_pool.signal_vm_created(tls, page_pool, m_id); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); + } + + m_allocated = allocated_status_t::allocated; + return m_id; } /// - /// @brief Sets the next vm_t in the vm_pool_t linked list + /// @brief Deallocates this vm_t /// /// - /// @param val the next vm_t in the vm_pool_t linked list to set + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param vp_pool the VP pool to use + /// @param ext_pool the extension pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + deallocate( + tls_t &tls, page_pool_t &page_pool, vp_pool_t &vp_pool, ext_pool_t &ext_pool) noexcept + -> bsl::errc_type + { + bsl::errc_type ret{}; + lock_guard_t lock{tls, m_lock}; + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vm_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_id == syscall::BF_ROOT_VMID)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << " is the root VM which cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated == allocated_status_t::zombie)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << " is a zombie and cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << " is already deallocated and cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + tls.state_reversal_required = true; + bsl::finally zombify_on_error{[this]() noexcept -> void { + this->zombify(); + }}; + + auto const vpid{vp_pool.is_assigned_to_vm(tls, m_id)}; + if (bsl::unlikely(vpid)) { + bsl::error() << "vp " // -- + << bsl::hex(vpid) // -- + << " is assigned to vm " // -- + << bsl::hex(m_id) // -- + << " and therefore vm " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + auto const active_ppid{this->is_active(tls)}; + if (bsl::unlikely(active_ppid)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << " is active on pp " // -- + << bsl::hex(active_ppid) // -- + << " and therefore vm " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + ret = ext_pool.signal_vm_destroyed(tls, page_pool, m_id); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + m_allocated = allocated_status_t::deallocated; + + zombify_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Sets this vm_t's status as zombified, meaning it is no + /// longer usable. /// constexpr void - set_next(vm_t *val) &noexcept + zombify() noexcept { - m_next = val; + if (bsl::unlikely_assert(!m_id)) { + return; + } + + if (m_allocated == allocated_status_t::zombie) { + return; + } + + if (bsl::unlikely(m_id == syscall::BF_ROOT_VMID)) { + bsl::alert() << "attempt to zombify vm " // -- + << bsl::hex(m_id) // -- + << " was ignored as the root VM cannot be a zombie" // -- + << bsl::endl; // -- + } + else { + bsl::alert() << "vm " // -- + << bsl::hex(m_id) // -- + << " has been zombified" // -- + << bsl::endl; // -- + + m_allocated = allocated_status_t::zombie; + } + } + + /// + /// @brief Returns true if this vm_t is deallocated, false otherwise + /// + /// + /// @return Returns true if this vm_t is deallocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_deallocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::deallocated; + } + + /// + /// @brief Returns true if this vm_t is allocated, false otherwise + /// + /// + /// @return Returns true if this vm_t is allocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_allocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::allocated; + } + + /// + /// @brief Returns true if this vm_t is a zombie, false otherwise + /// + /// + /// @return Returns true if this vm_t is a zombie, false otherwise + /// + [[nodiscard]] constexpr auto + is_zombie() const noexcept -> bool + { + return m_allocated == allocated_status_t::zombie; + } + + /// + /// @brief Sets this vm_t as active. + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_active(tls_t &tls) noexcept -> bsl::errc_type + { + lock_guard_t lock{tls, m_lock}; + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vm_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID != tls.active_vmid)) { + bsl::error() << "vm " // -- + << bsl::hex(tls.active_vmid) // -- + << " is still active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + auto *const active{m_active.at_if(bsl::to_umax(tls.ppid))}; + if (bsl::unlikely_assert(nullptr == active)) { + bsl::error() << "tls.ppid " // -- + << bsl::hex(m_id) // -- + << " is greater than the HYPERVISOR_MAX_PPS " // -- + << bsl::hex(HYPERVISOR_MAX_PPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_index_out_of_bounds; + } + + if (bsl::unlikely_assert(*active)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << " is already the active vm on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + tls.active_vmid = m_id.get(); + *active = true; + + return bsl::errc_success; + } + + /// + /// @brief Sets this vm_t as inactive. + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_inactive(tls_t &tls) noexcept -> bsl::errc_type + { + lock_guard_t lock{tls, m_lock}; + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vm_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::deallocated)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == tls.active_vmid)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << " is not active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(tls.active_vmid != m_id)) { + bsl::error() << "vm " // -- + << bsl::hex(tls.active_vmid) // -- + << " is still active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + auto *const active{m_active.at_if(bsl::to_umax(tls.ppid))}; + if (bsl::unlikely_assert(nullptr == active)) { + bsl::error() << "tls.ppid " // -- + << bsl::hex(m_id) // -- + << " is greater than the HYPERVISOR_MAX_PPS " // -- + << bsl::hex(HYPERVISOR_MAX_PPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_index_out_of_bounds; + } + + if (bsl::unlikely_assert(!*active)) { + bsl::error() << "vm " // -- + << bsl::hex(m_id) // -- + << " is not active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + tls.active_vmid = syscall::BF_INVALID_ID.get(); + *active = false; + + return bsl::errc_success; + } + + /// + /// @brief Returns the ID of the first PP identified that this vm_t + /// is still active on. If the vm_t is inactive, this function + /// returns bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @return Returns the ID of the first PP identified that this vm_t + /// is still active on. If the vm_t is inactive, this function + /// returns bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_active(tls_t &tls) const noexcept -> bsl::safe_uint16 + { + auto const online_pps{m_active.size().min(bsl::to_umax(tls.online_pps))}; + + for (bsl::safe_uintmax i{}; i < online_pps; ++i) { + if (*m_active.at_if(i)) { + return bsl::to_u16(i); + } + + bsl::touch(); + } + + return bsl::safe_uint16::failure(); + } + + /// + /// @brief Returns true if this vm_t is active on the current PP, + /// false otherwise + /// + /// + /// @param tls the current TLS block + /// @return Returns true if this vm_t is active on the current PP, + /// false otherwise + /// + [[nodiscard]] constexpr auto + is_active_on_current_pp(tls_t &tls) const noexcept -> bool + { + auto const *const active{m_active.at_if(bsl::to_umax(tls.ppid))}; + if (bsl::unlikely(nullptr == active)) { + bsl::error() << "tls.ppid " // -- + << bsl::hex(m_id) // -- + << " is greater than the HYPERVISOR_MAX_PPS " // -- + << bsl::hex(HYPERVISOR_MAX_PPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return *active; + } + + /// + /// @brief Dumps the vm_t + /// + /// + /// @param tls the current TLS block + /// + constexpr void + dump(tls_t &tls) const noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + + if (bsl::unlikely(!m_id)) { + bsl::print() << "[error]" << bsl::endl; + return; + } + + bsl::print() << bsl::mag << "vm ["; + bsl::print() << bsl::rst << bsl::hex(m_id); + bsl::print() << bsl::mag << "] dump: "; + bsl::print() << bsl::rst << bsl::endl; + + /// Header + /// + + bsl::print() << bsl::ylw << "+---------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^12s", "description "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^6s", "value "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+---------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + /// Allocated + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<12s", "allocated "}; + bsl::print() << bsl::ylw << "| "; + if (this->is_allocated()) { + bsl::print() << bsl::grn << bsl::fmt{"^6s", "yes "}; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^6s", "no "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Active + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<12s", "active "}; + bsl::print() << bsl::ylw << "| "; + if (this->is_active(tls)) { + bsl::print() << bsl::grn << bsl::fmt{"^6s", "yes "}; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^6s", "no "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Footer + /// + + bsl::print() << bsl::ylw << "+---------------------+"; + bsl::print() << bsl::rst << bsl::endl; } }; } diff --git a/kernel/src/vmexit_loop.hpp b/kernel/src/vmexit_loop.hpp index e1398dac..0b0c6f0e 100644 --- a/kernel/src/vmexit_loop.hpp +++ b/kernel/src/vmexit_loop.hpp @@ -25,6 +25,11 @@ #ifndef VMEXIT_LOOP_HPP #define VMEXIT_LOOP_HPP +#include +#include +#include +#include + #include #include #include @@ -36,27 +41,29 @@ namespace mk /// after a successful launch of the hypervisor. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @tparam VPS_POOL_CONCEPT defines the type of VPS pool to use /// @param tls the current TLS block - /// @param ext_vmexit the ext_t to handle the VMExit + /// @param intrinsic the intrinsics to use /// @param vps_pool the VPS pool to use - /// @return Returns bsl::exit_success on success and bsl::exit_failure + /// @param ext the ext_t to handle the VMExit + /// @param log the VMExit log to use + /// @return Returns bsl::exit_success on success, bsl::exit_failure /// otherwise /// - template [[nodiscard]] constexpr auto - vmexit_loop(TLS_CONCEPT &tls, EXT_CONCEPT &ext_vmexit, VPS_POOL_CONCEPT &vps_pool) noexcept - -> bsl::exit_code + vmexit_loop( + tls_t &tls, + intrinsic_t &intrinsic, + vps_pool_t &vps_pool, + ext_t &ext, + vmexit_log_t &log) noexcept -> bsl::exit_code { - auto const exit_reason{vps_pool.run(tls, tls.active_vpsid)}; + auto const exit_reason{vps_pool.run(tls, intrinsic, tls.active_vpsid, log)}; if (bsl::unlikely(!exit_reason)) { bsl::print() << bsl::here(); return bsl::exit_failure; } - auto const ret{ext_vmexit.vmexit(tls, exit_reason)}; + auto const ret{ext.vmexit(tls, intrinsic, exit_reason)}; if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return bsl::exit_failure; diff --git a/kernel/src/vp_pool_t.hpp b/kernel/src/vp_pool_t.hpp index 1024aba2..df5a5d27 100644 --- a/kernel/src/vp_pool_t.hpp +++ b/kernel/src/vp_pool_t.hpp @@ -25,177 +25,132 @@ #ifndef VP_POOL_T_HPP #define VP_POOL_T_HPP +#include "lock_guard_t.hpp" +#include "spinlock_t.hpp" + +#include +#include +#include +#include + #include #include #include -#include +#include #include +#include namespace mk { + class vm_pool_t; + /// @class mk::vp_pool_t /// /// - /// @brief TODO + /// @brief Defines the microkernel's VP pool /// - /// - /// @tparam VP_CONCEPT the type of vp_t that this class manages. - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use - /// @tparam MAX_VPS the max number of VPs supported - /// - template class vp_pool_t final { - /// @brief stores true if initialized() has been executed - bool m_initialized; - /// @brief stores a reference to the page pool to use - PAGE_POOL_CONCEPT &m_page_pool; - /// @brief stores the first VP_CONCEPT in the VP_CONCEPT linked list - VP_CONCEPT *m_head; - /// @brief stores the VP_CONCEPTs in the VP_CONCEPT linked list - bsl::array m_pool; + /// @brief stores the pool of vp_ts + bsl::array m_pool{}; + /// @brief safe guards operations on the pool. + mutable spinlock_t m_lock{}; public: - /// @brief an alias for VP_CONCEPT - using vp_type = VP_CONCEPT; - /// @brief an alias for PAGE_POOL_CONCEPT - using page_pool_type = PAGE_POOL_CONCEPT; - - /// - /// @brief Creates a vp_pool_t - /// - /// - /// @param page_pool the page pool to use - /// - explicit constexpr vp_pool_t(PAGE_POOL_CONCEPT &page_pool) noexcept - : m_initialized{}, m_page_pool{page_pool}, m_head{}, m_pool{} - {} - /// /// @brief Initializes this vp_pool_t /// /// + /// @param tls the current TLS block + /// @param vps_pool the VPS pool to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - initialize() &noexcept -> bsl::errc_type + initialize(tls_t &tls, vps_pool_t &vps_pool) noexcept -> bsl::errc_type { - bsl::errc_type ret{}; - - if (bsl::unlikely(m_initialized)) { - bsl::error() << "vp_pool_t already initialized\n" << bsl::here(); - return bsl::errc_failure; - } - - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); - }}; - - VP_CONCEPT *prev{}; - for (auto const vp : m_pool) { - ret = vp.data->initialize(&m_page_pool, bsl::to_u16(vp.index)); + bsl::finally_assert release_on_error{[this, &tls, &vps_pool]() noexcept -> void { + auto const ret{this->release(tls, vps_pool)}; if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return; } - if (nullptr != prev) { - prev->set_next(vp.data); - } - else { - m_head = vp.data; + bsl::touch(); + }}; + + for (auto const vp : m_pool) { + auto const ret{vp.data->initialize(tls, bsl::to_u16(vp.index))}; + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; } - prev = vp.data; + bsl::touch(); } release_on_error.ignore(); - m_initialized = true; + return bsl::errc_success; + } + + /// + /// @brief Release the vp_pool_t. Note that if this function fails, + /// the microkernel is left in a corrupt state and all use of the + /// vp_pool_t after calling this function will results in UB. + /// + /// + /// @param tls the current TLS block + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + release(tls_t &tls, vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + for (auto const vp : m_pool) { + auto const ret{vp.data->release(tls, vps_pool)}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } return bsl::errc_success; } /// - /// @brief Release the vp_t - /// - constexpr void - release() &noexcept - { - for (auto const vp : m_pool) { - vp.data->release(); - } - - m_head = {}; - m_initialized = {}; - } - - /// - /// @brief Destroyes a previously created vp_pool_t - /// - constexpr ~vp_pool_t() noexcept = default; - - /// - /// @brief copy constructor - /// - /// - /// @param o the object being copied - /// - constexpr vp_pool_t(vp_pool_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr vp_pool_t(vp_pool_t &&o) noexcept = default; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vp_pool_t const &o) &noexcept - -> vp_pool_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vp_pool_t &&o) &noexcept -> vp_pool_t & = default; - - /// - /// @brief Allocates a vp from the vp pool. We set the allocated - /// vp_t's next() to itself, which indicates that it has been - /// allocated. + /// @brief Allocates a vp from the vp pool. /// /// + /// @param tls the current TLS block + /// @param vmid The ID of the VM to assign the newly created VP to + /// @param ppid The ID of the PP to assign the newly created VP to /// @return Returns ID of the newly allocated vp /// [[nodiscard]] constexpr auto - allocate() &noexcept -> bsl::safe_uint16 + allocate(tls_t &tls, bsl::safe_uint16 const &vmid, bsl::safe_uint16 const &ppid) noexcept + -> bsl::safe_uint16 { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "vp_pool_t not initialized\n" << bsl::here(); - return bsl::safe_uint16::zero(true); + lock_guard_t lock{tls, m_lock}; + + vp_t *vp{}; + for (auto const elem : m_pool) { + if (elem.data->is_deallocated()) { + vp = elem.data; + break; + } + + bsl::touch(); } - if (bsl::unlikely(nullptr == m_head)) { + if (bsl::unlikely(nullptr == vp)) { bsl::error() << "vp pool out of vps\n" << bsl::here(); - return bsl::safe_uint16::zero(true); + return bsl::safe_uint16::failure(); } - auto *const vp{m_head}; - m_head = m_head->next(); - - vp->set_next(vp); - return vp->id(); + return vp->allocate(tls, vmid, ppid); } /// @@ -203,43 +158,428 @@ namespace mk /// function to the vp pool. /// /// + /// @param tls the current TLS block + /// @param vps_pool the VPS pool to use /// @param vpid the ID of the vp to deallocate /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - deallocate(bsl::safe_uint16 const &vpid) &noexcept -> bsl::errc_type + deallocate(tls_t &tls, vps_pool_t &vps_pool, bsl::safe_uint16 const &vpid) noexcept + -> bsl::errc_type { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "vp_pool_t not initialized\n" << bsl::here(); - return bsl::errc_failure; - } - auto *const vp{m_pool.at_if(bsl::to_umax(vpid))}; if (bsl::unlikely(nullptr == vp)) { - bsl::error() << "invalid vpid: " // -- - << bsl::hex(vpid) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::errc_failure; + return bsl::errc_index_out_of_bounds; } - if (vp->next() != vp) { - bsl::error() << "vp with id " // -- - << bsl::hex(vpid) // -- - << " was never allocated" // -- - << bsl::endl // -- - << bsl::here(); // -- + return vp->deallocate(tls, vps_pool); + } - return bsl::errc_failure; + /// + /// @brief Sets the requested vp_t's status as zombified, meaning + /// it is no longer usable. + /// + /// + /// @param vpid the ID of the vp_t to set as a zombie + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + zombify(bsl::safe_uint16 const &vpid) noexcept -> bsl::errc_type + { + auto *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_index_out_of_bounds; } - vp->set_next(m_head); - m_head = vp; - + vp->zombify(); return bsl::errc_success; } + + /// + /// @brief Returns true if the requested vp_t is deallocated, false + /// if the provided VPID is invalid, or if the vp_t is not + /// deallocated. + /// + /// + /// @param tls the current TLS block + /// @param vpid the ID of the vp_t to query + /// @return Returns true if the requested vp_t is deallocated, false + /// if the provided VPID is invalid, or if the vp_t is not + /// deallocated. + /// + [[nodiscard]] constexpr auto + is_deallocated(tls_t &tls, bsl::safe_uint16 const &vpid) const noexcept -> bool + { + bsl::discard(tls); + + auto const *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vp->is_deallocated(); + } + + /// + /// @brief Returns true if the requested vp_t is allocated, false + /// if the provided VPID is invalid, or if the vp_t is not + /// allocated. + /// + /// + /// @param tls the current TLS block + /// @param vpid the ID of the vp_t to query + /// @return Returns true if the requested vp_t is allocated, false + /// if the provided VPID is invalid, or if the vp_t is not + /// allocated. + /// + [[nodiscard]] constexpr auto + is_allocated(tls_t &tls, bsl::safe_uint16 const &vpid) const noexcept -> bool + { + bsl::discard(tls); + + auto const *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vp->is_allocated(); + } + + /// + /// @brief Returns true if the requested vp_t is a zombie, false + /// if the provided VPID is invalid, or if the vp_t is not + /// a zombie. + /// + /// + /// @param tls the current TLS block + /// @param vpid the ID of the vp_t to query + /// @return Returns true if the requested vp_t is a zombie, false + /// if the provided VPID is invalid, or if the vp_t is not + /// a zombie. + /// + [[nodiscard]] constexpr auto + is_zombie(tls_t &tls, bsl::safe_uint16 const &vpid) const noexcept -> bool + { + bsl::discard(tls); + + auto const *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vp->is_zombie(); + } + + /// + /// @brief If a vp_t in the pool is assigned to the requested VM, + /// the ID of the first vp_t found is returned. Otherwise, this + /// function will return bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID fo the VM to query + /// @return If a vp_t in the pool is assigned to the requested VM, + /// the ID of the first vp_t found is returned. Otherwise, this + /// function will return bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_assigned_to_vm(tls_t &tls, bsl::safe_uint16 const &vmid) const noexcept + -> bsl::safe_uint16 + { + bsl::discard(tls); + + if (bsl::unlikely_assert(!vmid)) { + bsl::error() << "invalid vmid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == vmid)) { + bsl::error() << "invalid vmid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + for (auto const elem : m_pool) { + if (elem.data->assigned_vm() == vmid) { + return elem.data->id(); + } + + bsl::touch(); + } + + return bsl::safe_uint16::failure(); + } + + /// + /// @brief Sets the requested vp_t as active. + /// + /// + /// @param tls the current TLS block + /// @param vpid the ID of the vp_t to set as active + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_active(tls_t &tls, bsl::safe_uint16 const &vpid) noexcept -> bsl::errc_type + { + auto *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_index_out_of_bounds; + } + + return vp->set_active(tls); + } + + /// + /// @brief Sets the requested vp_t as inactive. + /// + /// + /// @param tls the current TLS block + /// @param vpid the ID of the vp_t to set as inactive + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_inactive(tls_t &tls, bsl::safe_uint16 const &vpid) noexcept -> bsl::errc_type + { + auto *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_index_out_of_bounds; + } + + return vp->set_inactive(tls); + } + + /// + /// @brief Returns true if the requested vp_t is active on the + /// current PP, false if the provided ID is invalid, or if the + /// vp_t is not active on the current PP. + /// + /// + /// @param tls the current TLS block + /// @param vpid the ID of the vp_t to query + /// @return Returns true if the requested vp_t is active on the + /// current PP, false if the provided ID is invalid, or if the + /// vp_t is not active on the current PP. + /// + [[nodiscard]] constexpr auto + is_active(tls_t &tls, bsl::safe_uint16 const &vpid) const noexcept -> bsl::safe_uint16 + { + auto const *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + return vp->is_active(tls); + } + + /// + /// @brief Returns true if this vp_t is active on the current PP, + /// false if the provided ID is invalid, or if the vp_t is not + /// active on the current PP. + /// + /// + /// @param tls the current TLS block + /// @param vpid the ID of the vp_t to query + /// @return Returns true if this vp_t is active on the current PP, + /// false if the provided ID is invalid, or if the vp_t is not + /// active on the current PP. + /// + [[nodiscard]] constexpr auto + is_active_on_current_pp(tls_t &tls, bsl::safe_uint16 const &vpid) const noexcept -> bool + { + auto const *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vp->is_active_on_current_pp(tls); + } + + /// + /// @brief Migrates the requested vp_t from one PP to another. + /// + /// + /// @param tls the current TLS block + /// @param ppid the ID of the PP to migrate to + /// @param vpid the ID of the vp_t to migrate + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + migrate(tls_t &tls, bsl::safe_uint16 const &ppid, bsl::safe_uint16 const &vpid) noexcept + -> bsl::errc_type + { + auto *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_index_out_of_bounds; + } + + return vp->migrate(tls, ppid); + } + + /// + /// @brief Returns the ID of the VM the requested vp_t is assigned to + /// + /// + /// @param vpid the ID of the vp_t to query + /// @return Returns the ID of the VM the requested vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_vm(bsl::safe_uint16 const &vpid) const noexcept -> bsl::safe_uint16 + { + auto const *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + return vp->assigned_vm(); + } + + /// + /// @brief Returns the ID of the PP the requested vp_t is assigned to + /// + /// + /// @param vpid the ID of the vp_t to query + /// @return Returns the ID of the PP the requested vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_pp(bsl::safe_uint16 const &vpid) const noexcept -> bsl::safe_uint16 + { + auto const *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + return vp->assigned_pp(); + } + + /// + /// @brief Dumps the requested VP + /// + /// + /// @param tls the current TLS block + /// @param vpid the ID of the VP to dump + /// + constexpr void + dump(tls_t &tls, bsl::safe_uint16 const &vpid) noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + + auto const *const vp{m_pool.at_if(bsl::to_umax(vpid))}; + if (bsl::unlikely(nullptr == vp)) { + bsl::error() + << "vpid " // -- + << bsl::hex(vpid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPS " // -- + << bsl::hex(HYPERVISOR_MAX_VPS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return; + } + + vp->dump(tls); + } }; } diff --git a/kernel/src/vp_t.hpp b/kernel/src/vp_t.hpp index 6e5b56b5..45c18e4a 100644 --- a/kernel/src/vp_t.hpp +++ b/kernel/src/vp_t.hpp @@ -25,137 +25,138 @@ #ifndef VP_T_HPP #define VP_T_HPP +#include +#include +#include +#include + #include #include #include #include #include +#include namespace mk { - /// @brief defines the value of an invalid VPID - constexpr bsl::safe_uint16 INVALID_VPID{bsl::to_u16(0xFFFFU)}; + class vm_pool_t; /// @class mk::vp_t /// /// - /// @brief TODO + /// @brief Defines the microkernel's notion of a VP /// - /// - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use - /// - template class vp_t final { - /// @brief stores true if initialized() has been executed - bool m_initialized{}; - /// @brief stores a reference to the page pool to use - PAGE_POOL_CONCEPT *m_page_pool{}; /// @brief stores the ID associated with this vp_t - bsl::safe_uint16 m_id{bsl::safe_uint16::zero(true)}; - /// @brief stores the next vp_t in the vp_pool_t linked list - vp_t *m_next{}; + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + /// @brief stores whether or not this vp_t is allocated. + allocated_status_t m_allocated{allocated_status_t::deallocated}; + /// @brief stores the ID of the VM this vp_t is assigned to + bsl::safe_uint16 m_assigned_vmid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vp_t is assigned to + bsl::safe_uint16 m_assigned_ppid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vp_t is active on + bsl::safe_uint16 m_active_ppid{bsl::safe_uint16::failure()}; public: - /// @brief an alias for PAGE_POOL_CONCEPT - using page_pool_type = PAGE_POOL_CONCEPT; - - /// - /// @brief Default constructor - /// - constexpr vp_t() noexcept = default; - /// /// @brief Initializes this vp_t /// /// - /// @param page_pool the page pool to use + /// @param tls the current TLS block /// @param i the ID for this vp_t /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - initialize(PAGE_POOL_CONCEPT *const page_pool, bsl::safe_uint16 const &i) &noexcept - -> bsl::errc_type + initialize(tls_t &tls, bsl::safe_uint16 const &i) noexcept -> bsl::errc_type { - if (bsl::unlikely(m_initialized)) { + bsl::discard(tls); + + if (bsl::unlikely_assert(m_id)) { bsl::error() << "vp_t already initialized\n" << bsl::here(); - return bsl::errc_failure; + return bsl::errc_precondition; } - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); - }}; + if (bsl::unlikely_assert(!i)) { + bsl::error() << "invalid id\n" << bsl::here(); + return bsl::errc_precondition; + } - m_page_pool = page_pool; - if (bsl::unlikely(nullptr == m_page_pool)) { - bsl::error() << "invalid page_pool\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == i)) { + bsl::error() << "id " // -- + << bsl::hex(i) // -- + << " is invalid and cannot be used for initialization" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; } m_id = i; - if (bsl::unlikely(!i)) { - bsl::error() << "invalid id\n" << bsl::here(); - return bsl::errc_failure; - } - - release_on_error.ignore(); - m_initialized = true; - return bsl::errc_success; } /// - /// @brief Release the vp_t + /// @brief Release the vp_t. /// - constexpr void - release() &noexcept + /// + /// @param tls the current TLS block + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + release(tls_t &tls, vps_pool_t &vps_pool) noexcept -> bsl::errc_type { - m_next = {}; - m_id = bsl::safe_uint16::zero(true); - m_page_pool = {}; - m_initialized = {}; + if (this->is_zombie()) { + return bsl::errc_success; + } + + tls.state_reversal_required = true; + bsl::finally zombify_on_error{[this]() noexcept -> void { + this->zombify(); + }}; + + auto const vpsid{vps_pool.is_assigned_to_vp(tls, m_id)}; + if (bsl::unlikely(vpsid)) { + bsl::error() << "vps " // -- + << bsl::hex(vpsid) // -- + << " is assigned to vp " // -- + << bsl::hex(m_id) // -- + << " and therefore vp " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is active on pp " // -- + << bsl::hex(m_active_ppid) // -- + << " and therefore vp " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vmid = syscall::BF_INVALID_ID; + m_allocated = allocated_status_t::deallocated; + m_id = bsl::safe_uint16::failure(); + + zombify_on_error.ignore(); + return bsl::errc_success; } - /// - /// @brief Destructor - /// - constexpr ~vp_t() noexcept = default; - - /// - /// @brief copy constructor - /// - /// - /// @param o the object being copied - /// - constexpr vp_t(vp_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr vp_t(vp_t &&o) noexcept = default; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vp_t const &o) &noexcept -> vp_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vp_t &&o) &noexcept -> vp_t & = default; - /// /// @brief Returns the ID of this vp_t /// @@ -163,33 +164,673 @@ namespace mk /// @return Returns the ID of this vp_t /// [[nodiscard]] constexpr auto - id() const &noexcept -> bsl::safe_uint16 const & + id() const noexcept -> bsl::safe_uint16 const & { return m_id; } /// - /// @brief Returns the next vp_t in the vp_pool_t linked list + /// @brief Allocates this vp_t /// /// - /// @return Returns the next vp_t in the vp_pool_t linked list + /// @param tls the current TLS block + /// @param vmid The ID of the VM to assign the newly created VP to + /// @param ppid The ID of the PP to assign the newly created VP to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise /// [[nodiscard]] constexpr auto - next() const &noexcept -> vp_t * + allocate(tls_t &tls, bsl::safe_uint16 const &vmid, bsl::safe_uint16 const &ppid) noexcept + -> bsl::safe_uint16 { - return m_next; + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vp_t not initialized\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(!vmid)) { + bsl::error() << "invalid vmid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(syscall::BF_INVALID_ID == vmid)) { + bsl::error() << "vm " // -- + << bsl::hex(vmid) // -- + << " is invalid and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + // if (bsl::unlikely(vm_pool.is_zombie(tls, vmid))) { + // bsl::error() << "vm " // -- + // << bsl::hex(vmid) // -- + // << " is a zombie and a vp cannot be assigned to it" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::safe_uint16::failure(); + // } + + // if (bsl::unlikely(vm_pool.is_deallocated(tls, vmid))) { + // bsl::error() << "vm " // -- + // << bsl::hex(vmid) // -- + // << " has not been created and a vp cannot be assigned to it" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::safe_uint16::failure(); + // } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(syscall::BF_INVALID_ID == ppid)) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is invalid and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(!(ppid < tls.online_pps))) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is not less than the total number of online pps " // -- + << bsl::hex(tls.online_pps) // -- + << " and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::zombie)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is a zombie and cannot be allocated" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::allocated)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is already allocated and cannot be created" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + tls.state_reversal_required = true; + tls.log_vpid = m_id.get(); + + m_assigned_vmid = vmid; + m_assigned_ppid = ppid; + m_allocated = allocated_status_t::allocated; + + return m_id; } /// - /// @brief Sets the next vp_t in the vp_pool_t linked list + /// @brief Deallocates this vp_t /// /// - /// @param val the next vp_t in the vp_pool_t linked list to set + /// @param tls the current TLS block + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + deallocate(tls_t &tls, vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vp_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated == allocated_status_t::zombie)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is a zombie and cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is already deallocated and cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + tls.state_reversal_required = true; + bsl::finally zombify_on_error{[this]() noexcept -> void { + this->zombify(); + }}; + + auto const vpsid{vps_pool.is_assigned_to_vp(tls, m_id)}; + if (bsl::unlikely(vpsid)) { + bsl::error() << "vps " // -- + << bsl::hex(vpsid) // -- + << " is assigned to vp " // -- + << bsl::hex(m_id) // -- + << " and therefore vp " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is active on pp " // -- + << bsl::hex(m_active_ppid) // -- + << " and therefore vp " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vmid = syscall::BF_INVALID_ID; + m_allocated = allocated_status_t::deallocated; + + zombify_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Sets this vp_t's status as zombified, meaning it is no + /// longer usable. /// constexpr void - set_next(vp_t *val) &noexcept + zombify() noexcept { - m_next = val; + if (bsl::unlikely_assert(!m_id)) { + return; + } + + if (m_allocated == allocated_status_t::zombie) { + return; + } + + bsl::alert() << "vp " // -- + << bsl::hex(m_id) // -- + << " has been zombified" // -- + << bsl::endl; // -- + + m_allocated = allocated_status_t::zombie; + } + + /// + /// @brief Returns true if this vp_t is deallocated, false otherwise + /// + /// + /// @return Returns true if this vp_t is deallocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_deallocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::deallocated; + } + + /// + /// @brief Returns true if this vp_t is allocated, false otherwise + /// + /// + /// @return Returns true if this vp_t is allocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_allocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::allocated; + } + + /// + /// @brief Returns true if this vp_t is a zombie, false otherwise + /// + /// + /// @return Returns true if this vp_t is a zombie, false otherwise + /// + [[nodiscard]] constexpr auto + is_zombie() const noexcept -> bool + { + return m_allocated == allocated_status_t::zombie; + } + + /// + /// @brief Sets this vp_t as active. + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_active(tls_t &tls) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vp_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.active_vmid != m_assigned_vmid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to vm " // -- + << bsl::hex(m_assigned_vmid) // -- + << " and cannot be activated with vm " // -- + << bsl::hex(tls.active_vmid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be activated on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID != tls.active_vpid)) { + bsl::error() << "vp " // -- + << bsl::hex(tls.active_vpid) // -- + << " is still active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is already the active vp on pp " // -- + << bsl::hex(m_active_ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + tls.active_vpid = m_id.get(); + m_active_ppid = tls.ppid; + + return bsl::errc_success; + } + + /// + /// @brief Sets this vp_t as inactive. + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_inactive(tls_t &tls) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vp_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::deallocated)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == tls.active_vpid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is not active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(tls.active_vpid != m_id)) { + bsl::error() << "vp " // -- + << bsl::hex(tls.active_vpid) // -- + << " is still active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(!m_active_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is not active " // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(tls.ppid != m_active_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is not active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + tls.active_vpid = syscall::BF_INVALID_ID.get(); + m_active_ppid = bsl::safe_uint16::failure(); + + return bsl::errc_success; + } + + /// + /// @brief Returns the ID of the PP that this vp_t is still active + /// on. If the vp_t is inactive, this function returns + /// bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @return Returns the ID of the PP that this vp_t is still active + /// on. If the vp_t is inactive, this function returns + /// bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_active(tls_t &tls) const noexcept -> bsl::safe_uint16 + { + bsl::discard(tls); + return m_active_ppid; + } + + /// + /// @brief Returns true if this vp_t is active on the current PP, + /// false otherwise + /// + /// + /// @param tls the current TLS block + /// @return Returns true if this vp_t is active on the current PP, + /// false otherwise + /// + [[nodiscard]] constexpr auto + is_active_on_current_pp(tls_t &tls) const noexcept -> bool + { + return tls.ppid == m_active_ppid; + } + + /// + /// @brief Migrates this vp_t from one PP to another. If this calls + /// completes successfully, the VPS's assigned PP will not + /// match the VP's assigned PP. Future calls to the run ABI + /// will be able to detect this an migrate mismatched VPSs to + /// the proper PP as needed. Note that since the VP doesn't control + /// any hardware state, all we have to do here is set which PP + /// this VP is allowed to execute on. The VPS is what actually + /// needs to be migrated, and that will not happen until a call + /// to the run ABIs made. Once the run ABI detects a mismatch with + /// the VPS and it's assigned VP, it will be migrated then. + /// + /// + /// @param tls the current TLS block + /// @param ppid the ID of the PP to migrate to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + migrate(tls_t &tls, bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vp_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(syscall::BF_INVALID_ID == ppid)) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is invalid and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(!(ppid < tls.online_pps))) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is not less than the total number of online pps " // -- + << bsl::hex(tls.online_pps) // -- + << " and a vp cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(ppid == m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is already assigned to a pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is still active on pp " // -- + << bsl::hex(m_active_ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + m_assigned_ppid = ppid; + return bsl::errc_success; + } + + /// + /// @brief Returns the ID of the VM this vp_t is assigned to + /// + /// + /// @return Returns the ID of the VM this vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_vm() const noexcept -> bsl::safe_uint16 + { + if (bsl::unlikely(syscall::BF_INVALID_ID == m_assigned_vmid)) { + return bsl::safe_uint16::failure(); + } + + return m_assigned_vmid; + } + + /// + /// @brief Returns the ID of the PP this vp_t is assigned to + /// + /// + /// @return Returns the ID of the PP this vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_pp() const noexcept -> bsl::safe_uint16 + { + if (bsl::unlikely(syscall::BF_INVALID_ID == m_assigned_ppid)) { + return bsl::safe_uint16::failure(); + } + + return m_assigned_ppid; + } + + /// + /// @brief Dumps the vp_t + /// + /// + /// @param tls the current TLS block + /// + constexpr void + dump(tls_t &tls) const noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + + if (bsl::unlikely(!m_id)) { + bsl::print() << "[error]" << bsl::endl; + return; + } + + bsl::print() << bsl::mag << "vp ["; + bsl::print() << bsl::rst << bsl::hex(m_id); + bsl::print() << bsl::mag << "] dump: "; + bsl::print() << bsl::rst << bsl::endl; + + /// Header + /// + + bsl::print() << bsl::ylw << "+--------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^12s", "description "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^11s", "value "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+--------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + /// Allocated + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<12s", "allocated "}; + bsl::print() << bsl::ylw << "| "; + if (this->is_allocated()) { + bsl::print() << bsl::grn << bsl::fmt{"^11s", "yes "}; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^11s", "no "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Active + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<12s", "active "}; + bsl::print() << bsl::ylw << "| "; + if (this->is_active(tls)) { + bsl::print() << bsl::grn << bsl::fmt{"^11s", "yes "}; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^11s", "no "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Assigned VM + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<12s", "assigned vm "}; + bsl::print() << bsl::ylw << "| "; + if (syscall::BF_INVALID_ID != m_assigned_vmid) { + bsl::print() << bsl::grn << " " << bsl::hex(m_assigned_vmid) << " "; + } + else { + bsl::print() << bsl::red << " " << bsl::hex(m_assigned_vmid) << " "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Assigned PP + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<12s", "assigned pp "}; + bsl::print() << bsl::ylw << "| "; + if (syscall::BF_INVALID_ID != m_assigned_ppid) { + bsl::print() << bsl::grn << " " << bsl::hex(m_assigned_ppid) << " "; + } + else { + bsl::print() << bsl::red << " " << bsl::hex(m_assigned_ppid) << " "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Footer + /// + + bsl::print() << bsl::ylw << "+--------------------------+"; + bsl::print() << bsl::rst << bsl::endl; } }; } diff --git a/kernel/src/vps_pool_t.hpp b/kernel/src/vps_pool_t.hpp index f8d6e7cf..ead3cf03 100644 --- a/kernel/src/vps_pool_t.hpp +++ b/kernel/src/vps_pool_t.hpp @@ -25,197 +25,141 @@ #ifndef VPS_POOL_T_HPP #define VPS_POOL_T_HPP +#include "lock_guard_t.hpp" +#include "spinlock_t.hpp" + +#include +#include +#include +#include +#include +#include +#include + #include #include #include -#include +#include #include +#include namespace mk { + class vp_pool_t; + /// @class mk::vps_pool_t /// /// - /// @brief TODO + /// @brief Defines the microkernel's VPS pool /// - /// - /// @tparam VPS_CONCEPT the type of vps_t that this class manages. - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use - /// @tparam MAX_VPSS the max number of VPSs supported - /// - template< - typename VPS_CONCEPT, - typename INTRINSIC_CONCEPT, - typename PAGE_POOL_CONCEPT, - bsl::uintmax MAX_VPSS> class vps_pool_t final { - /// @brief stores true if initialized() has been executed - bool m_initialized; - /// @brief stores a reference to the intrinsics to use - INTRINSIC_CONCEPT &m_intrinsic; - /// @brief stores a reference to the page pool to use - PAGE_POOL_CONCEPT &m_page_pool; - /// @brief stores the first VPS_CONCEPT in the VPS_CONCEPT linked list - VPS_CONCEPT *m_head; - /// @brief stores the VPS_CONCEPTs in the VPS_CONCEPT linked list - bsl::array m_pool; + /// @brief stores the pool of vps_ts + bsl::array m_pool{}; + /// @brief safe guards operations on the pool. + mutable spinlock_t m_lock{}; public: - /// @brief an alias for VPS_CONCEPT - using vps_type = VPS_CONCEPT; - /// @brief an alias for INTRINSIC_CONCEPT - using intrinsic_type = INTRINSIC_CONCEPT; - /// @brief an alias for PAGE_POOL_CONCEPT - using page_pool_type = PAGE_POOL_CONCEPT; - - /// - /// @brief Creates a vps_pool_t - /// - /// - /// @param intrinsic the intrinsics to use - /// @param page_pool the page pool to use - /// - explicit constexpr vps_pool_t( - INTRINSIC_CONCEPT &intrinsic, PAGE_POOL_CONCEPT &page_pool) noexcept - : m_initialized{}, m_intrinsic{intrinsic}, m_page_pool{page_pool}, m_head{}, m_pool{} - {} - /// /// @brief Initializes this vps_pool_t /// /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - initialize() &noexcept -> bsl::errc_type + initialize(tls_t &tls, page_pool_t &page_pool) noexcept -> bsl::errc_type { - bsl::errc_type ret{}; - - if (bsl::unlikely(m_initialized)) { - bsl::error() << "vps_pool_t already initialized\n" << bsl::here(); - return bsl::errc_failure; - } - - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); - }}; - - VPS_CONCEPT *prev{}; - for (auto const vps : m_pool) { - ret = vps.data->initialize(&m_intrinsic, &m_page_pool, bsl::to_u16(vps.index)); + bsl::finally_assert release_on_error{[this, &tls, &page_pool]() noexcept -> void { + auto const ret{this->release(tls, page_pool)}; if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return; } - if (nullptr != prev) { - prev->set_next(vps.data); - } - else { - m_head = vps.data; + bsl::touch(); + }}; + + for (auto const vps : m_pool) { + auto const ret{vps.data->initialize(bsl::to_u16(vps.index))}; + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; } - prev = vps.data; + bsl::touch(); } release_on_error.ignore(); - m_initialized = true; + return bsl::errc_success; + } + + /// + /// @brief Release the vps_pool_t. Note that if this function fails, + /// the microkernel is left in a corrupt state and all use of the + /// vps_pool_t after calling this function will results in UB. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + release(tls_t &tls, page_pool_t &page_pool) noexcept -> bsl::errc_type + { + for (auto const vps : m_pool) { + auto const ret{vps.data->release(tls, page_pool)}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + bsl::touch(); + } return bsl::errc_success; } /// - /// @brief Release the vps_t - /// - constexpr void - release() &noexcept - { - for (auto const vps : m_pool) { - vps.data->release(); - } - - m_head = {}; - m_initialized = {}; - } - - /// - /// @brief Destroyes a previously created vps_pool_t - /// - constexpr ~vps_pool_t() noexcept = default; - - /// - /// @brief copy constructor + /// @brief Allocates a vps from the vps pool. /// /// - /// @param o the object being copied - /// - constexpr vps_pool_t(vps_pool_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr vps_pool_t(vps_pool_t &&o) noexcept = default; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vps_pool_t const &o) &noexcept - -> vps_pool_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vps_pool_t &&o) &noexcept - -> vps_pool_t & = default; - - /// - /// @brief Allocates a vps from the vps pool. We set the allocated - /// vps_t's next() to itself, which indicates that it has been - /// allocated. - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @param intrinsic the intrinsics to use + /// @param vpid The ID of the VP to assign the newly created VP to + /// @param ppid The ID of the PP to assign the newly created VP to /// @return Returns ID of the newly allocated vps /// - template [[nodiscard]] constexpr auto - allocate(TLS_CONCEPT &tls) &noexcept -> bsl::safe_uint16 + allocate( + tls_t &tls, + page_pool_t &page_pool, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::safe_uint16 { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "vps_pool_t not initialized\n" << bsl::here(); - return bsl::safe_uint16::zero(true); + lock_guard_t lock{tls, m_lock}; + + vps_t *vps{}; + for (auto const elem : m_pool) { + if (elem.data->is_deallocated()) { + vps = elem.data; + break; + } + + bsl::touch(); } - if (bsl::unlikely(nullptr == m_head)) { + if (bsl::unlikely(nullptr == vps)) { bsl::error() << "vps pool out of vpss\n" << bsl::here(); - return bsl::safe_uint16::zero(true); + return bsl::safe_uint16::failure(); } - if (bsl::unlikely(!m_head->allocate(tls))) { - bsl::print() << bsl::here(); - return bsl::safe_uint16::zero(true); - } - - auto *const vps{m_head}; - m_head = m_head->next(); - - vps->set_next(vps); - return vps->id(); + return vps->allocate(tls, intrinsic, page_pool, vpid, ppid); } /// @@ -223,107 +167,473 @@ namespace mk /// function to the vps pool. /// /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use /// @param vpsid the ID of the vps to deallocate /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - deallocate(bsl::safe_uint16 const &vpsid) &noexcept -> bsl::errc_type + deallocate(tls_t &tls, page_pool_t &page_pool, bsl::safe_uint16 const &vpsid) noexcept + -> bsl::errc_type { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "vps_pool_t not initialized\n" << bsl::here(); - return bsl::errc_failure; - } - auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; if (bsl::unlikely(nullptr == vps)) { - bsl::error() << "invalid vpsid: " // -- - << bsl::hex(vpsid) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::errc_failure; + return bsl::errc_index_out_of_bounds; } - if (vps->next() != vps) { - bsl::error() << "vps with id " // -- - << bsl::hex(vpsid) // -- - << " was never allocated" // -- - << bsl::endl // -- - << bsl::here(); // -- + return vps->deallocate(tls, page_pool); + } - return bsl::errc_failure; + /// + /// @brief Sets the requested vps_t's status as zombified, meaning + /// it is no longer usable. + /// + /// + /// @param vpsid the ID of the vps_t to set as a zombie + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + zombify(bsl::safe_uint16 const &vpsid) noexcept -> bsl::errc_type + { + auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_index_out_of_bounds; } - vps->deallocate(); - vps->set_next(m_head); - m_head = vps; - + vps->zombify(); return bsl::errc_success; } + /// + /// @brief Returns true if the requested vps_t is deallocated, false + /// if the provided VPID is invalid, or if the vps_t is not + /// deallocated. + /// + /// + /// @param tls the current TLS block + /// @param vpsid the ID of the vps_t to query + /// @return Returns true if the requested vps_t is deallocated, false + /// if the provided VPID is invalid, or if the vps_t is not + /// deallocated. + /// + [[nodiscard]] constexpr auto + is_deallocated(tls_t &tls, bsl::safe_uint16 const &vpsid) const noexcept -> bool + { + bsl::discard(tls); + + auto const *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vps->is_deallocated(); + } + + /// + /// @brief Returns true if the requested vps_t is allocated, false + /// if the provided VPID is invalid, or if the vps_t is not + /// allocated. + /// + /// + /// @param tls the current TLS block + /// @param vpsid the ID of the vps_t to query + /// @return Returns true if the requested vps_t is allocated, false + /// if the provided VPID is invalid, or if the vps_t is not + /// allocated. + /// + [[nodiscard]] constexpr auto + is_allocated(tls_t &tls, bsl::safe_uint16 const &vpsid) const noexcept -> bool + { + bsl::discard(tls); + + auto const *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vps->is_allocated(); + } + + /// + /// @brief Returns true if the requested vps_t is a zombie, false + /// if the provided VPID is invalid, or if the vps_t is not + /// a zombie. + /// + /// + /// @param tls the current TLS block + /// @param vpsid the ID of the vps_t to query + /// @return Returns true if the requested vps_t is a zombie, false + /// if the provided VPID is invalid, or if the vps_t is not + /// a zombie. + /// + [[nodiscard]] constexpr auto + is_zombie(tls_t &tls, bsl::safe_uint16 const &vpsid) const noexcept -> bool + { + bsl::discard(tls); + + auto const *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vps->is_zombie(); + } + + /// + /// @brief If a vps_t in the pool is assigned to the requested VP, + /// the ID of the first vps_t found is returned. Otherwise, this + /// function will return bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @param vpid the ID fo the VP to query + /// @return If a vps_t in the pool is assigned to the requested VP, + /// the ID of the first vps_t found is returned. Otherwise, this + /// function will return bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_assigned_to_vp(tls_t &tls, bsl::safe_uint16 const &vpid) const noexcept + -> bsl::safe_uint16 + { + bsl::discard(tls); + + if (bsl::unlikely(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(syscall::BF_INVALID_ID == vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + for (auto const elem : m_pool) { + if (elem.data->assigned_vp() == vpid) { + return elem.data->id(); + } + + bsl::touch(); + } + + return bsl::safe_uint16::failure(); + } + + /// + /// @brief Sets the requested vps_t as active. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vpsid the ID of the vps_t to set as active + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_active(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uint16 const &vpsid) noexcept + -> bsl::errc_type + { + auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + return vps->set_active(tls, intrinsic); + } + + /// + /// @brief Sets the requested vps_t as inactive. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vpsid the ID of the vps_t to set as inactive + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_inactive(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uint16 const &vpsid) noexcept + -> bsl::errc_type + { + auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + return vps->set_inactive(tls, intrinsic); + } + + /// + /// @brief Returns true if the requested vps_t is active, false + /// if the provided VPID is invalid, or if the vps_t is not + /// active. + /// + /// + /// @param tls the current TLS block + /// @param vpsid the ID of the vps_t to query + /// @return Returns the ID of the PP that the requested vps_t is + /// still active on. If the vps_t is inactive, this function + /// returns bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_active(tls_t &tls, bsl::safe_uint16 const &vpsid) noexcept -> bsl::safe_uint16 + { + auto const *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + return vps->is_active(tls); + } + + /// + /// @brief Returns true if this vps_t is active on the current PP, + /// false if the provided ID is invalid, or if the vps_t is not + /// active on the current PP. + /// + /// + /// @param tls the current TLS block + /// @param vpsid the ID of the vps_t to query + /// @return Returns true if this vps_t is active on the current PP, + /// false if the provided ID is invalid, or if the vps_t is not + /// active on the current PP. + /// + [[nodiscard]] constexpr auto + is_active_on_current_pp(tls_t &tls, bsl::safe_uint16 const &vpsid) noexcept -> bool + { + auto const *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return false; + } + + return vps->is_active_on_current_pp(tls); + } + + /// + /// @brief Migrates the requested vps_t from one PP to another. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vpsid the ID of the vps_t to migrate + /// @param ppid the ID of the PP to migrate to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + migrate( + tls_t &tls, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpsid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + return vps->migrate(tls, intrinsic, ppid); + } + + /// + /// @brief Returns the ID of the VP the requested vps_t is assigned to + /// + /// + /// @param vpsid the ID of the vps_t to query + /// @return Returns the ID of the VP the requested vps_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_vp(bsl::safe_uint16 const &vpsid) const noexcept -> bsl::safe_uint16 + { + auto const *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + return vps->assigned_vp(); + } + + /// + /// @brief Returns the ID of the PP the requested vps_t is assigned to + /// + /// + /// @param vpsid the ID of the vps_t to query + /// @return Returns the ID of the PP the requested vps_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_pp(bsl::safe_uint16 const &vpsid) const noexcept -> bsl::safe_uint16 + { + auto const *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + return vps->assigned_pp(); + } + /// /// @brief Stores the provided state in the requested VPS. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam STATE_SAVE_CONCEPT the type of state save to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param vpsid the ID of the VPS to set the state to /// @param state the state to set the VPS to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto state_save_to_vps( - TLS_CONCEPT &tls, + tls_t &tls, + intrinsic_t &intrinsic, bsl::safe_uint16 const &vpsid, - STATE_SAVE_CONCEPT const *const state) &noexcept -> bsl::errc_type + loader::state_save_t const &state) noexcept -> bsl::errc_type { auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; if (bsl::unlikely(nullptr == vps)) { - bsl::error() << "invalid vpsid: " // -- - << bsl::hex(vpsid) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - return vps->state_save_to_vps(tls, state); + return vps->state_save_to_vps(tls, intrinsic, state); } /// /// @brief Stores the requested VPS state in the provided state save. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam STATE_SAVE_CONCEPT the type of state save to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param vpsid the ID of the VPS to set the state to /// @param state the state save to store the VPS state to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto vps_to_state_save( - TLS_CONCEPT &tls, + tls_t &tls, + intrinsic_t &intrinsic, bsl::safe_uint16 const &vpsid, - STATE_SAVE_CONCEPT *const state) &noexcept -> bsl::errc_type + loader::state_save_t &state) noexcept -> bsl::errc_type { auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; if (bsl::unlikely(nullptr == vps)) { - bsl::error() << "invalid vpsid: " // -- - << bsl::hex(vpsid) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - return vps->vps_to_state_save(tls, state); + return vps->vps_to_state_save(tls, intrinsic, state); } /// @@ -331,31 +641,37 @@ namespace mk /// the field to read. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @tparam FIELD_TYPE the type (i.e., size) of field to read /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param vpsid the ID of the VPS to read from /// @param index the index of the field to read from the VPS /// @return Returns the value of the requested field from the - /// requested VPS or bsl::safe_integral::zero(true) + /// requested VPS or bsl::safe_integral::failure() /// on failure. /// - template + template [[nodiscard]] constexpr auto - read(TLS_CONCEPT &tls, bsl::safe_uint16 const &vpsid, bsl::safe_uintmax const &index) - &noexcept -> bsl::safe_integral + read( + tls_t &tls, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpsid, + bsl::safe_uintmax const &index) noexcept -> bsl::safe_integral { auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; if (bsl::unlikely(nullptr == vps)) { - bsl::error() << "invalid vpsid: " // -- - << bsl::hex(vpsid) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::safe_integral::zero(true); + return bsl::safe_integral::failure(); } - return vps->template read(tls, index); + return vps->template read(tls, intrinsic, index); } /// @@ -363,34 +679,38 @@ namespace mk /// the field and the value to write. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @tparam FIELD_TYPE the type (i.e., size) of field to write /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param vpsid the ID of the VPS to write to /// @param index the index of the field to write to the VPS /// @param value the value to write to the VPS /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template + template [[nodiscard]] constexpr auto write( - TLS_CONCEPT &tls, + tls_t &tls, + intrinsic_t &intrinsic, bsl::safe_uint16 const &vpsid, bsl::safe_uintmax const &index, - bsl::safe_integral const &value) &noexcept -> bsl::errc_type + bsl::safe_integral const &value) noexcept -> bsl::errc_type { auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; if (bsl::unlikely(nullptr == vps)) { - bsl::error() << "invalid vpsid: " // -- - << bsl::hex(vpsid) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - return vps->template write(tls, index, value); + return vps->template write(tls, intrinsic, index, value); } /// @@ -398,30 +718,34 @@ namespace mk /// defining the field to read. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param vpsid the ID of the VPS to read from /// @param reg a bf_reg_t defining the field to read from the VPS /// @return Returns the value of the requested field from the - /// requested VPS or bsl::safe_uintmax::zero(true) on failure. + /// requested VPS or bsl::safe_uintmax::failure() on failure. /// - template [[nodiscard]] constexpr auto read_reg( - TLS_CONCEPT &tls, bsl::safe_uint16 const &vpsid, syscall::bf_reg_t const reg) &noexcept - -> bsl::safe_uintmax + tls_t &tls, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpsid, + syscall::bf_reg_t const reg) noexcept -> bsl::safe_uintmax { auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; if (bsl::unlikely(nullptr == vps)) { - bsl::error() << "invalid vpsid: " // -- - << bsl::hex(vpsid) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::safe_uintmax::zero(true); + return bsl::safe_uintmax::failure(); } - return vps->read_reg(tls, reg); + return vps->read_reg(tls, intrinsic, reg); } /// @@ -429,33 +753,36 @@ namespace mk /// defining the field and a value to write. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param vpsid the ID of the VPS to write to /// @param reg a bf_reg_t defining the field to write to the VPS /// @param value the value to write to the VPS /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto write_reg( - TLS_CONCEPT &tls, + tls_t &tls, + intrinsic_t &intrinsic, bsl::safe_uint16 const &vpsid, syscall::bf_reg_t const reg, - bsl::safe_uintmax const &value) &noexcept -> bsl::errc_type + bsl::safe_uintmax const &value) noexcept -> bsl::errc_type { auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; if (bsl::unlikely(nullptr == vps)) { - bsl::error() << "invalid vpsid: " // -- - << bsl::hex(vpsid) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - return vps->write_reg(tls, reg, value); + return vps->write_reg(tls, intrinsic, reg, value); } /// @@ -464,82 +791,126 @@ namespace mk /// will return the VMExit reason. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param log the VMExit log to use /// @param vpsid the ID of the VPS to run /// @return Returns the VMExit reason on success, or - /// bsl::safe_uintmax::zero(true) on failure. + /// bsl::safe_uintmax::failure() on failure. /// - template [[nodiscard]] constexpr auto - run(TLS_CONCEPT &tls, bsl::safe_uint16 const &vpsid) &noexcept -> bsl::safe_uintmax + run(tls_t &tls, + intrinsic_t &intrinsic, + bsl::safe_uint16 const &vpsid, + vmexit_log_t &log) noexcept -> bsl::safe_uintmax { auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; if (bsl::unlikely(nullptr == vps)) { - bsl::error() << "invalid vpsid: " // -- - << bsl::hex(vpsid) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::safe_uintmax::zero(true); + return bsl::safe_uintmax::failure(); } - return vps->run(tls); + return vps->run(tls, intrinsic, log); } /// /// @brief Advance the IP of the requested VPS /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param vpsid the ID of the VPS to advance the IP for /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - advance_ip(TLS_CONCEPT &tls, bsl::safe_uint16 const &vpsid) &noexcept -> bsl::errc_type + advance_ip(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uint16 const &vpsid) noexcept + -> bsl::errc_type { auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; if (bsl::unlikely(nullptr == vps)) { - bsl::error() << "invalid vpsid: " // -- - << bsl::hex(vpsid) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - return vps->advance_ip(tls); + return vps->advance_ip(tls, intrinsic); + } + + /// + /// @brief Clears the requested VPS's internal cache. Note that this + /// is a hardware specific function and doesn't change the actual + /// values stored in the VPS. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param vpsid the ID of the VPS to clear + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + clear(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uint16 const &vpsid) noexcept + -> bsl::errc_type + { + auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + return vps->clear(tls, intrinsic); } /// /// @brief Dumps the requested VPS /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param vpsid the ID of the VPS to dump - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise /// - template - [[nodiscard]] constexpr auto - dump(TLS_CONCEPT &tls, bsl::safe_uint16 const &vpsid) &noexcept -> bsl::errc_type + constexpr void + dump(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uint16 const &vpsid) noexcept { - auto *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; - if (bsl::unlikely(nullptr == vps)) { - bsl::error() << "invalid vpsid: " // -- - << bsl::hex(vpsid) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; } - vps->dump(tls); - return bsl::errc_success; + auto const *const vps{m_pool.at_if(bsl::to_umax(vpsid))}; + if (bsl::unlikely(nullptr == vps)) { + bsl::error() + << "vpsid " // -- + << bsl::hex(vpsid) // -- + << " is invalid or greater than or equal to the HYPERVISOR_MAX_VPSS " // -- + << bsl::hex(HYPERVISOR_MAX_VPSS) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return; + } + + vps->dump(tls, intrinsic); } }; } diff --git a/kernel/src/x64/amd/dispatch_esr_nmi.hpp b/kernel/src/x64/amd/dispatch_esr_nmi.hpp index 97117c56..04302645 100644 --- a/kernel/src/x64/amd/dispatch_esr_nmi.hpp +++ b/kernel/src/x64/amd/dispatch_esr_nmi.hpp @@ -25,8 +25,11 @@ #ifndef DISPATCH_ESR_NMI_HPP #define DISPATCH_ESR_NMI_HPP +#include +#include + #include -#include +#include namespace mk { @@ -35,21 +38,18 @@ namespace mk /// on AMD do not occur as NMIs are blocked). /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use /// @param tls the current TLS block /// @param intrinsic the intrinsics to use - /// @return Returns bsl::exit_success if the exception was handled, - /// bsl::exit_failure otherwise + /// @return Returns bsl::errc_success if the exception was handled, + /// bsl::errc_failure otherwise /// - template [[nodiscard]] constexpr auto - dispatch_esr_nmi(TLS_CONCEPT &tls, INTRINSIC_CONCEPT &intrinsic) noexcept -> bsl::exit_code + dispatch_esr_nmi(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { bsl::discard(tls); bsl::discard(intrinsic); - return bsl::exit_success; + return bsl::errc_success; } } diff --git a/kernel/src/x64/amd/dispatch_syscall_intrinsic_op.hpp b/kernel/src/x64/amd/dispatch_syscall_intrinsic_op.hpp new file mode 100644 index 00000000..aa0ec3aa --- /dev/null +++ b/kernel/src/x64/amd/dispatch_syscall_intrinsic_op.hpp @@ -0,0 +1,197 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_SYSCALL_INTRINSIC_OP_HPP +#define DISPATCH_SYSCALL_INTRINSIC_OP_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Implements the bf_intrinsic_op_rdmsr syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + syscall_intrinsic_op_rdmsr(tls_t &tls, intrinsic_t &intrinsic) -> bsl::errc_type + { + /// TODO: + /// - Move this logic to the dispatch_syscall_entry.S and implement + /// this right in ASM. This way, we can do the smallest amount of + /// state save logic and execute this instruction as fast as + /// possible. Just make sure that the safe version is used, and + /// it will still need to make sure that the extension is not + /// trying to read/write MSRs that the microkernel is using. + /// + + auto const val{intrinsic.rdmsr(bsl::to_u32_unsafe(tls.ext_reg1))}; + if (bsl::unlikely(!val)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.ext_reg0 = val.get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_intrinsic_op_wrmsr syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + syscall_intrinsic_op_wrmsr(tls_t &tls, intrinsic_t &intrinsic) -> bsl::errc_type + { + /// TODO: + /// - Move this logic to the dispatch_syscall_entry.S and implement + /// this right in ASM. This way, we can do the smallest amount of + /// state save logic and execute this instruction as fast as + /// possible. Just make sure that the safe version is used, and + /// it will still need to make sure that the extension is not + /// trying to read/write MSRs that the microkernel is using. + /// + + auto const ret{intrinsic.wrmsr(bsl::to_u32_unsafe(tls.ext_reg1), tls.ext_reg2)}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_intrinsic_op_invlpga syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + syscall_intrinsic_op_invlpga(tls_t &tls, intrinsic_t &intrinsic) -> bsl::errc_type + { + auto const ret{intrinsic.invlpga(tls.ext_reg1, tls.ext_reg2)}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Dispatches the bf_intrinsic_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param ext the extension that made the syscall + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + dispatch_syscall_intrinsic_op(tls_t &tls, intrinsic_t &intrinsic, ext_t &ext) -> bsl::errc_type + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { + bsl::error() << "invalid handle " // -- + << bsl::hex(tls.ext_reg0) // -- + << bsl::endl // -- + << bsl::here(); // -- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_INVALID_HANDLE.get(); + return bsl::errc_failure; + } + + switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { + case syscall::BF_INTRINSIC_OP_RDMSR_IDX_VAL.get(): { + ret = syscall_intrinsic_op_rdmsr(tls, intrinsic); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_INTRINSIC_OP_WRMSR_IDX_VAL.get(): { + ret = syscall_intrinsic_op_wrmsr(tls, intrinsic); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_INTRINSIC_OP_INVLPGA_IDX_VAL.get(): { + ret = syscall_intrinsic_op_invlpga(tls, intrinsic); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + default: { + break; + } + } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; + } +} + +#endif diff --git a/kernel/src/x64/amd/intrinsic_t.S b/kernel/src/x64/amd/intrinsic_t.S index d5a78c55..f045c208 100644 --- a/kernel/src/x64/amd/intrinsic_t.S +++ b/kernel/src/x64/amd/intrinsic_t.S @@ -104,9 +104,7 @@ intrinsic_set_tp: .type intrinsic_tls_reg, @function intrinsic_tls_reg: - stac mov rax, fs:[rdi] - clac ret int 3 @@ -119,9 +117,7 @@ intrinsic_tls_reg: .type intrinsic_set_tls_reg, @function intrinsic_set_tls_reg: - stac mov fs:[rdi], rsi - clac ret int 3 @@ -245,6 +241,21 @@ intrinsic_wrmsr_unsafe: + .globl intrinsic_invlpga + .type intrinsic_invlpga, @function +intrinsic_invlpga: + + mov rax, rdi + mov rcx, rsi + invlpga rax, ecx + + ret + int 3 + + .size intrinsic_invlpga, .-intrinsic_invlpga + + + .globl intrinsic_vmrun .type intrinsic_vmrun, @function intrinsic_vmrun: @@ -265,18 +276,22 @@ intrinsic_vmrun: /* PAT */ /**************************************************************************/ + mov rax, [r11 + 0x0090] + and rax, 0x00000001 + jnz skip_load_pat + mov edi, 0x00000277 call intrinsic_rdmsr_unsafe mov [r13 + 0x0668], rax mov rsi, [r11 + 0x0668] call intrinsic_wrmsr_unsafe +skip_load_pat: + /**************************************************************************/ /* General Purpose Register State */ /**************************************************************************/ - stac - mov rax, fs:[0x800] mov [r11 + 0x05F8], rax @@ -300,8 +315,6 @@ intrinsic_vmrun: mov r14, fs:[0x868] mov r15, fs:[0x870] - clac - /**************************************************************************/ /* Run */ /**************************************************************************/ @@ -324,8 +337,6 @@ intrinsic_vmrun: /* General Purpose Register State */ /**************************************************************************/ - stac - mov fs:[0x870], r15 mov fs:[0x868], r14 mov fs:[0x860], r13 @@ -349,18 +360,22 @@ intrinsic_vmrun: mov rax, [r11 + 0x05F8] mov fs:[0x800], rax - clac - /**************************************************************************/ /* PAT */ /**************************************************************************/ + mov rax, [r11 + 0x0090] + and rax, 0x00000001 + jnz skip_save_pat + mov edi, 0x00000277 call intrinsic_rdmsr_unsafe mov [r11 + 0x0668], rax mov rsi, [r13 + 0x0668] call intrinsic_wrmsr_unsafe +skip_save_pat: + /**************************************************************************/ /* Done */ /**************************************************************************/ diff --git a/kernel/src/x64/amd/intrinsic_t.hpp b/kernel/src/x64/amd/intrinsic_t.hpp index 9b25d1a1..dec9a7c2 100644 --- a/kernel/src/x64/amd/intrinsic_t.hpp +++ b/kernel/src/x64/amd/intrinsic_t.hpp @@ -28,114 +28,122 @@ #include #include #include +#include #include #include namespace mk { - namespace details - { - /// - /// @brief Implements intrinsic_t::invlpg - /// - /// - /// @param val n/a - /// - extern "C" void intrinsic_invlpg(bsl::uint64 const val) noexcept; + /// + /// @brief Implements intrinsic_t::invlpg + /// + /// + /// @param val n/a + /// + extern "C" void intrinsic_invlpg(bsl::uint64 const val) noexcept; - /// - /// @brief Implements intrinsic_t::cr3 - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_cr3() noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::cr3 + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_cr3() noexcept -> bsl::uint64; - /// - /// @brief Implements intrinsic_t::set_cr3 - /// - /// - /// @param val n/a - /// - extern "C" void intrinsic_set_cr3(bsl::uint64 const val) noexcept; + /// + /// @brief Implements intrinsic_t::set_cr3 + /// + /// + /// @param val n/a + /// + extern "C" void intrinsic_set_cr3(bsl::uint64 const val) noexcept; - /// - /// @brief Implements intrinsic_t::tp - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_tp() noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::tp + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_tp() noexcept -> bsl::uint64; - /// - /// @brief Implements intrinsic_t::set_tp - /// - /// - /// @param val n/a - /// - extern "C" void intrinsic_set_tp(bsl::uint64 const val) noexcept; + /// + /// @brief Implements intrinsic_t::set_tp + /// + /// + /// @param val n/a + /// + extern "C" void intrinsic_set_tp(bsl::uint64 const val) noexcept; - /// - /// @brief Implements intrinsic_t::tls_reg - /// - /// - /// @param reg n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_tls_reg(bsl::uint64 const reg) noexcept - -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::tls_reg + /// + /// + /// @param reg n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_tls_reg(bsl::uint64 const reg) noexcept -> bsl::uint64; - /// - /// @brief Implements intrinsic_t::set_tls_reg - /// - /// - /// @param reg n/a - /// @param val n/a - /// - extern "C" void - intrinsic_set_tls_reg(bsl::uint64 const reg, bsl::uint64 const val) noexcept; + /// + /// @brief Implements intrinsic_t::set_tls_reg + /// + /// + /// @param reg n/a + /// @param val n/a + /// + extern "C" void intrinsic_set_tls_reg(bsl::uint64 const reg, bsl::uint64 const val) noexcept; - /// - /// @brief Implements intrinsic_t::halt - /// - extern "C" void intrinsic_halt() noexcept; + /// + /// @brief Implements intrinsic_t::halt + /// + extern "C" void intrinsic_halt() noexcept; - /// - /// @brief Implements intrinsic_t::rdmsr - /// - /// - /// @param msr n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto - intrinsic_rdmsr(bsl::uint32 msr, bsl::uint64 *const val) noexcept -> bsl::exit_code; + /// + /// @brief Implements intrinsic_t::rdmsr + /// + /// + /// @param msr n/a + /// @param val n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_rdmsr(bsl::uint32 msr, bsl::uint64 *const val) noexcept + -> bsl::exit_code; - /// - /// @brief Implements intrinsic_t::wrmsr - /// - /// - /// @param msr n/a - /// @param val n/a - /// - extern "C" [[nodiscard]] auto - intrinsic_wrmsr(bsl::uint32 msr, bsl::uint64 const val) noexcept -> bsl::exit_code; + /// + /// @brief Implements intrinsic_t::wrmsr + /// + /// + /// @param msr n/a + /// @param val n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_wrmsr(bsl::uint32 msr, bsl::uint64 const val) noexcept + -> bsl::exit_code; - /// - /// @brief Executes the VMRun instruction. When this function returns - /// a "VMExit" has occurred and must be handled. - /// - /// - /// @param guest_vmcb a pointer to the guest VMCB to use - /// @param guest_vmcb_phys the physical address of the guest VMCB to use - /// @param host_vmcb a pointer to the host VMCB to use - /// @param host_vmcb_phys the physical address of the host VMCB to use - /// - extern "C" [[nodiscard]] auto intrinsic_vmrun( - void *const guest_vmcb, - bsl::uintmax const guest_vmcb_phys, - void *const host_vmcb, - bsl::uintmax const host_vmcb_phys) noexcept -> bsl::uintmax; - } + /// + /// @brief Implements intrinsic_t::invlpga + /// + /// + /// @param addr n/a + /// @param asid n/a + /// + extern "C" void intrinsic_invlpga(bsl::uint64 addr, bsl::uint64 const asid) noexcept; + + /// + /// @brief Executes the VMRun instruction. When this function returns + /// a "VMExit" has occurred and must be handled. + /// + /// + /// @param guest_vmcb a pointer to the guest VMCB to use + /// @param guest_vmcb_phys the physical address of the guest VMCB to use + /// @param host_vmcb a pointer to the host VMCB to use + /// @param host_vmcb_phys the physical address of the host VMCB to use + /// @return Returns the exit reason associated with the VMExit + /// + extern "C" [[nodiscard]] auto intrinsic_vmrun( + void *const guest_vmcb, + bsl::uintmax const guest_vmcb_phys, + void *const host_vmcb, + bsl::uintmax const host_vmcb_phys) noexcept -> bsl::uintmax; /// @class mk::intrinsic_t /// @@ -147,52 +155,6 @@ namespace mk class intrinsic_t final { public: - /// - /// @brief Default constructor - /// - constexpr intrinsic_t() noexcept = default; - - /// - /// @brief Destructor - /// - constexpr ~intrinsic_t() noexcept = default; - - /// - /// @brief copy constructor - /// - /// - /// @param o the object being copied - /// - constexpr intrinsic_t(intrinsic_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr intrinsic_t(intrinsic_t &&o) noexcept = delete; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(intrinsic_t const &o) &noexcept - -> intrinsic_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(intrinsic_t &&o) &noexcept - -> intrinsic_t & = delete; - /// /// @brief Invalidates TLB entries given a virtual address /// @@ -207,15 +169,15 @@ namespace mk } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return; } - details::intrinsic_invlpg(val.get()); + intrinsic_invlpg(val.get()); } /// @@ -231,7 +193,7 @@ namespace mk return {}; } - return details::intrinsic_cr3(); + return intrinsic_cr3(); } /// @@ -248,15 +210,15 @@ namespace mk } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return; } - details::intrinsic_set_cr3(val.get()); + intrinsic_set_cr3(val.get()); } /// @@ -272,7 +234,7 @@ namespace mk return {}; } - return details::intrinsic_tp(); + return intrinsic_tp(); } /// @@ -289,15 +251,15 @@ namespace mk } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return; } - details::intrinsic_set_tp(val.get()); + intrinsic_set_tp(val.get()); } /// @@ -315,15 +277,15 @@ namespace mk } if (bsl::unlikely(!reg)) { - bsl::error() << "invalid reg: " // -- - << bsl::hex(reg) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid reg " // -- + << bsl::hex(reg) // -- + << bsl::endl // -- + << bsl::here(); // -- return {}; } - return details::intrinsic_tls_reg(reg.get()); + return intrinsic_tls_reg(reg.get()); } /// @@ -341,24 +303,24 @@ namespace mk } if (bsl::unlikely(!reg)) { - bsl::error() << "invalid reg: " // -- - << bsl::hex(reg) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid reg " // -- + << bsl::hex(reg) // -- + << bsl::endl // -- + << bsl::here(); // -- return; } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return; } - details::intrinsic_set_tls_reg(reg.get(), val.get()); + intrinsic_set_tls_reg(reg.get(), val.get()); } /// @@ -371,7 +333,7 @@ namespace mk return; } - details::intrinsic_halt(); + intrinsic_halt(); } /// @@ -392,22 +354,22 @@ namespace mk } if (bsl::unlikely(!msr)) { - bsl::error() << "invalid msr: " // -- - << bsl::hex(msr) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid msr " // -- + << bsl::hex(msr) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::safe_uint64::zero(true); + return bsl::safe_uint64::failure(); } - ret = details::intrinsic_rdmsr(msr.get(), val.data()); + ret = intrinsic_rdmsr(msr.get(), val.data()); if (bsl::unlikely(ret != bsl::exit_success)) { bsl::error() << "rdmsr failed for msr " // -- << bsl::hex(msr) // -- << bsl::endl // -- << bsl::here(); // -- - return bsl::safe_uint64::zero(true); + return bsl::safe_uint64::failure(); } return val; @@ -420,7 +382,7 @@ namespace mk /// @param msr the MSR to write to /// @param val the value to set the MSR to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] static constexpr auto wrmsr(bsl::safe_uint32 const &msr, bsl::safe_uint64 const &val) noexcept -> bsl::errc_type @@ -432,24 +394,24 @@ namespace mk } if (bsl::unlikely(!msr)) { - bsl::error() << "invalid msr: " // -- - << bsl::hex(msr) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid msr " // -- + << bsl::hex(msr) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - ret = details::intrinsic_wrmsr(msr.get(), val.get()); + ret = intrinsic_wrmsr(msr.get(), val.get()); if (bsl::unlikely(ret != bsl::exit_success)) { bsl::error() << "wrmsr failed for msr " // -- << bsl::hex(msr) // -- @@ -463,6 +425,46 @@ namespace mk return bsl::errc_success; } + + /// + /// @brief Invalidates the TLB mapping for a given virtual page and + /// a given ASID + /// + /// + /// @param addr The address to invalidate + /// @param asid The ASID to invalidate + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + invlpga(bsl::safe_uint64 const &addr, bsl::safe_uint64 const &asid) noexcept + -> bsl::errc_type + { + if (bsl::is_constant_evaluated()) { + return bsl::errc_success; + } + + if (bsl::unlikely(!addr)) { + bsl::error() << "invalid addr " // -- + << bsl::hex(addr) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!asid)) { + bsl::error() << "invalid asid " // -- + << bsl::hex(asid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + intrinsic_invlpga(addr.get(), asid.get()); + return bsl::errc_success; + } }; } diff --git a/kernel/src/x64/amd/promote.S b/kernel/src/x64/amd/promote.S index 45902ed0..da3049f2 100644 --- a/kernel/src/x64/amd/promote.S +++ b/kernel/src/x64/amd/promote.S @@ -24,6 +24,21 @@ * SOFTWARE. */ + /** @brief defines the offset of state_save_t.rax */ + #define SS_OFFSET_RAX 0x000 + /** @brief defines the offset of state_save_t.promote_handler */ + #define SS_OFFSET_PROMOTE_HANDLER 0x2E8 + /** @brief defines the offset of state_save_t.esr_default_handler */ + #define SS_OFFSET_ESR_DEFAULT_HANDLER 0x2F0 + /** @brief defines the offset of state_save_t.esr_df_handler */ + #define SS_OFFSET_ESR_DF_HANDLER 0x2F8 + /** @brief defines the offset of state_save_t.esr_gpf_handler */ + #define SS_OFFSET_ESR_GPF_HANDLER 0x300 + /** @brief defines the offset of state_save_t.esr_nmi_handler */ + #define SS_OFFSET_ESR_NMI_HANDLER 0x308 + /** @brief defines the offset of state_save_t.esr_pf_handler */ + #define SS_OFFSET_ESR_PF_HANDLER 0x310 + .code64 .intel_syntax noprefix @@ -31,87 +46,118 @@ .type promote, @function promote: + /** + * NOTE: + * - Save off the first argument just in case we need to call other + * functions including debugging. The first argument in this case + * is a pointer to the root VP's state save. + */ + mov r15, rdi - mov [r15 + 0x000], rsi + + /** + * NOTE: + * - Store the return value for the demote() function. Once this function + * is done, it will return to the loader's promote() function which + * will return to the C portion of the loader as if demote() had returned + * and this is where we store the return value. Note that promote() + * can be called on error, or when the hypervisor is stopping. + */ + + mov [r15 + SS_OFFSET_RAX], rsi + + /** + * NOTE: + * - Restore the exception vectors. This is needed because we will no + * longer be able to use the exception vectores from the microkernel + * as we unload it, so we will use the exception vectors from the + * loader instead. + */ mov rdi, 0 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 1 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 2 - mov rsi, [r15 + 0x308] + mov rsi, [r15 + SS_OFFSET_ESR_NMI_HANDLER] call set_esr mov rdi, 3 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 4 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 5 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 6 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 7 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 8 - mov rsi, [r15 + 0x2F8] + mov rsi, [r15 + SS_OFFSET_ESR_DF_HANDLER] call set_esr mov rdi, 10 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 11 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 12 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 13 - mov rsi, [r15 + 0x300] + mov rsi, [r15 + SS_OFFSET_ESR_GPF_HANDLER] call set_esr mov rdi, 14 - mov rsi, [r15 + 0x310] + mov rsi, [r15 + SS_OFFSET_ESR_PF_HANDLER] call set_esr mov rdi, 16 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 17 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 18 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 19 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr + /** + * NOTE: + * - Call the loader's promote() handler. This will conclude execution + * from the microkernel. + */ + call set_up_target capture_spec: pause jmp capture_spec set_up_target: - mov rax, [r15 + 0x2E8] + mov rax, [r15 + SS_OFFSET_PROMOTE_HANDLER] mov [rsp], rax ret int 3 diff --git a/kernel/src/x64/amd/vps_t.hpp b/kernel/src/x64/amd/vps_t.hpp index 7b45897d..a0ed568b 100644 --- a/kernel/src/x64/amd/vps_t.hpp +++ b/kernel/src/x64/amd/vps_t.hpp @@ -25,208 +25,235 @@ #ifndef VPS_T_HPP #define VPS_T_HPP -#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include #include #include #include #include #include +#include #include +#include namespace mk { - /// @brief defines the value of an invalid VPSID - constexpr bsl::safe_uint16 INVALID_VPSID{bsl::to_u16(0xFFFFU)}; - - namespace details + /// + /// @brief Converts attributes in the form 0xF0FF to the form + /// 0x0FFF. + /// + /// + /// @param attrib the attrib to compress + /// @return Returns the compressed version of attrib + /// + [[nodiscard]] constexpr auto + compress_attrib(bsl::safe_uint16 const &attrib) noexcept -> bsl::safe_uint16 { - /// - /// @brief Converts attributes in the form 0xF0FF to the form - /// 0x0FFF. - /// - /// - /// @param attrib the attrib to compress - /// @return Returns the compressed version of attrib - /// - [[nodiscard]] constexpr auto - compress_attrib(bsl::safe_uint16 const &attrib) noexcept -> bsl::safe_uint16 - { - constexpr bsl::safe_uint16 mask1{bsl::to_u16(0x00FFU)}; - constexpr bsl::safe_uint16 mask2{bsl::to_u16(0xF000U)}; - constexpr bsl::safe_uint16 shift{bsl::to_u16(4)}; + constexpr auto mask1{0x00FF_u16}; + constexpr auto mask2{0xF000_u16}; + constexpr auto shift{4_u16}; - return (attrib & mask1) | ((attrib & mask2) >> shift); - } + return (attrib & mask1) | ((attrib & mask2) >> shift); + } - /// - /// @brief Converts attributes in the form 0x0FFF to the form - /// 0xF0FF. - /// - /// - /// @param attrib the attrib to decompress - /// @return Returns the decompressed version of attrib - /// - [[nodiscard]] constexpr auto - decompress_attrib(bsl::safe_uint16 const &attrib) noexcept -> bsl::safe_uint16 - { - constexpr bsl::safe_uint16 mask1{bsl::to_u16(0x00FFU)}; - constexpr bsl::safe_uint16 mask2{bsl::to_u16(0x0F00U)}; - constexpr bsl::safe_uint16 shift{bsl::to_u16(4)}; + /// + /// @brief Converts attributes in the form 0x0FFF to the form + /// 0xF0FF. + /// + /// + /// @param attrib the attrib to decompress + /// @return Returns the decompressed version of attrib + /// + [[nodiscard]] constexpr auto + decompress_attrib(bsl::safe_uint16 const &attrib) noexcept -> bsl::safe_uint16 + { + constexpr auto mask1{0x00FF_u16}; + constexpr auto mask2{0x0F00_u16}; + constexpr auto shift{4_u16}; - return (attrib & mask1) | ((attrib & mask2) << shift); - } + return (attrib & mask1) | ((attrib & mask2) << shift); } /// @class mk::vps_t /// /// - /// @brief TODO + /// @brief Defines the microkernel's notion of a VPS. /// - /// - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use - /// - template class vps_t final { - /// @brief stores true if initialized() has been executed - bool m_initialized{}; - /// @brief stores a reference to the intrinsics to use - INTRINSIC_CONCEPT *m_intrinsic{}; - /// @brief stores a reference to the page pool to use - PAGE_POOL_CONCEPT *m_page_pool{}; - /// @brief stores the ID associated with this vps_t - bsl::safe_uint16 m_id{bsl::safe_uint16::zero(true)}; - /// @brief stores the next vps_t in the vp_pool_t linked list - vps_t *m_next{}; + /// @brief stores the ID associated with this vp_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + /// @brief stores whether or not this vp_t is allocated. + allocated_status_t m_allocated{allocated_status_t::deallocated}; + /// @brief stores the ID of the VP this vps_t is assigned to + bsl::safe_uint16 m_assigned_vpid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vp_t is assigned to + bsl::safe_uint16 m_assigned_ppid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vp_t is active on + bsl::safe_uint16 m_active_ppid{bsl::safe_uint16::failure()}; - /// @brief stores true if initialized() has been executed - bool m_allocated{}; /// @brief stores a pointer to the guest VMCB being managed by this VPS vmcb_t *m_guest_vmcb{}; /// @brief stores the physical address of the guest VMCB - bsl::safe_uintmax m_guest_vmcb_phys{bsl::safe_uintmax::zero(true)}; + bsl::safe_uintmax m_guest_vmcb_phys{bsl::safe_uintmax::failure()}; /// @brief stores a pointer to the host VMCB being managed by this VPS vmcb_t *m_host_vmcb{}; /// @brief stores the physical address of the host VMCB - bsl::safe_uintmax m_host_vmcb_phys{bsl::safe_uintmax::zero(true)}; - - public: - /// @brief an alias for INTRINSIC_CONCEPT - using intrinsic_type = INTRINSIC_CONCEPT; - /// @brief an alias for PAGE_POOL_CONCEPT - using page_pool_type = PAGE_POOL_CONCEPT; + bsl::safe_uintmax m_host_vmcb_phys{bsl::safe_uintmax::failure()}; + /// @brief stores the general purpose registers + general_purpose_regs_t m_gprs{}; /// - /// @brief Default constructor + /// @brief Dumps the contents of a field /// - constexpr vps_t() noexcept = default; + /// + /// @tparam T the type of field to dump + /// @param str the name of the field + /// @param val the field to dump + /// + template + constexpr void + dump_field(bsl::string_view const &str, bsl::safe_integral const &val) const noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + auto const *rowcolor{bsl::rst}; + + if (val.is_zero()) { + rowcolor = bsl::blk; + } + else { + bsl::touch(); + } + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<30s", str}; + bsl::print() << bsl::ylw << "| "; + + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << " " << bsl::hex(val) << " "; + } + + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << " " << bsl::hex(val) << " "; + } + + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << " " << bsl::hex(val) << " "; + } + + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << bsl::hex(val) << ' '; + } + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + } + + public: /// /// @brief Initializes this vps_t /// /// - /// @param intrinsic the intrinsics to use - /// @param page_pool the page pool to use /// @param i the ID for this vps_t /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - initialize( - INTRINSIC_CONCEPT *const intrinsic, - PAGE_POOL_CONCEPT *const page_pool, - bsl::safe_uint16 const &i) &noexcept -> bsl::errc_type + initialize(bsl::safe_uint16 const &i) noexcept -> bsl::errc_type { - if (bsl::unlikely(m_initialized)) { - bsl::error() << "vm_t already initialized\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(m_id)) { + bsl::error() << "vps_t already initialized\n" << bsl::here(); + return bsl::errc_precondition; } - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); - }}; - - m_intrinsic = intrinsic; - if (bsl::unlikely(nullptr == m_intrinsic)) { - bsl::error() << "invalid intrinsic\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(!i)) { + bsl::error() << "invalid id\n" << bsl::here(); + return bsl::errc_precondition; } - m_page_pool = page_pool; - if (bsl::unlikely(nullptr == m_page_pool)) { - bsl::error() << "invalid page_pool\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == i)) { + bsl::error() << "id " // -- + << bsl::hex(i) // -- + << " is invalid and cannot be used for initialization" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; } m_id = i; - if (bsl::unlikely(!i)) { - bsl::error() << "invalid id\n" << bsl::here(); - return bsl::errc_failure; - } - - release_on_error.ignore(); - m_initialized = true; - return bsl::errc_success; } /// - /// @brief Release the vps_t + /// @brief Release the vp_t. Note that if this function fails, + /// the microkernel is left in a corrupt state and all use of the + /// vp_t after calling this function will results in UB. /// - constexpr void - release() &noexcept + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + release(tls_t &tls, page_pool_t &page_pool) noexcept -> bsl::errc_type { - this->deallocate(); + if (this->is_zombie()) { + return bsl::errc_success; + } - m_next = {}; - m_id = bsl::safe_uint16::zero(true); - m_page_pool = {}; - m_intrinsic = {}; - m_initialized = {}; + tls.state_reversal_required = true; + bsl::finally zombify_on_error{[this]() noexcept -> void { + this->zombify(); + }}; + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is active on pp " // -- + << bsl::hex(m_active_ppid) // -- + << " and therefore vp " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + m_gprs = {}; + + m_host_vmcb_phys = bsl::safe_uintmax::failure(); + page_pool.deallocate(tls, m_host_vmcb, ALLOCATE_TAG_HOST_VMCB); + m_host_vmcb = {}; + + m_guest_vmcb_phys = bsl::safe_uintmax::failure(); + page_pool.deallocate(tls, m_guest_vmcb, ALLOCATE_TAG_GUEST_VMCB); + m_guest_vmcb = {}; + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vpid = syscall::BF_INVALID_ID; + m_allocated = allocated_status_t::deallocated; + m_id = bsl::safe_uint16::failure(); + + zombify_on_error.ignore(); + return bsl::errc_success; } - /// - /// @brief Destructor - /// - constexpr ~vps_t() noexcept = default; - - /// - /// @brief copy constructor - /// - /// - /// @param o the object being copied - /// - constexpr vps_t(vps_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr vps_t(vps_t &&o) noexcept = default; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vps_t const &o) &noexcept -> vps_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vps_t &&o) &noexcept -> vps_t & = default; - /// /// @brief Returns the ID of this vps_t /// @@ -234,231 +261,791 @@ namespace mk /// @return Returns the ID of this vps_t /// [[nodiscard]] constexpr auto - id() const &noexcept -> bsl::safe_uint16 const & + id() const noexcept -> bsl::safe_uint16 const & { return m_id; } - /// - /// @brief Returns the next vps_t in the vps_pool_t linked list - /// - /// - /// @return Returns the next vps_t in the vps_pool_t linked list - /// - [[nodiscard]] constexpr auto - next() const &noexcept -> vps_t * - { - return m_next; - } - - /// - /// @brief Sets the next vps_t in the vps_pool_t linked list - /// - /// - /// @param val the next vps_t in the vps_pool_t linked list to set - /// - constexpr void - set_next(vps_t *val) &noexcept - { - m_next = val; - } - /// /// @brief Allocates this vps_t /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// @param intrinsic the intrinsics to use + /// @param page_pool the page pool to use + /// @param vpid The ID of the VP to assign the newly created VP to + /// @param ppid The ID of the PP to assign the newly created VP to + /// @return Returns ID of the newly allocated vps /// - template [[nodiscard]] constexpr auto - allocate(TLS_CONCEPT &tls) &noexcept -> bsl::errc_type + allocate( + tls_t &tls, + intrinsic_t &intrinsic, + page_pool_t &page_pool, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::safe_uint16 { - bsl::discard(tls); + bsl::discard(intrinsic); - if (bsl::unlikely(!m_initialized)) { + if (bsl::unlikely_assert(!m_id)) { bsl::error() << "vps_t not initialized\n" << bsl::here(); - return bsl::errc_failure; + return bsl::safe_uint16::failure(); } - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); + if (bsl::unlikely_assert(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(syscall::BF_INVALID_ID == vpid)) { + bsl::error() << "vp " // -- + << bsl::hex(vpid) // -- + << " is invalid and a vps cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + // if (bsl::unlikely(vp_pool.is_zombie(tls, vpid))) { + // bsl::error() << "vp " // -- + // << bsl::hex(vpid) // -- + // << " is a zombie and a vps cannot be assigned to it" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::safe_uint16::failure(); + // } + + // if (bsl::unlikely(vp_pool.is_deallocated(tls, vpid))) { + // bsl::error() << "vp " // -- + // << bsl::hex(vpid) // -- + // << " has not been created and a vps cannot be assigned to it" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::safe_uint16::failure(); + // } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(syscall::BF_INVALID_ID == ppid)) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is invalid and a vps cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(!(ppid < tls.online_pps))) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is not less than the total number of online pps " // -- + << bsl::hex(tls.online_pps) // -- + << " and a vps cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::zombie)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is a zombie and cannot be allocated" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is already allocated and cannot be created" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + tls.state_reversal_required = true; + tls.log_vpsid = m_id.get(); + + bsl::finally cleanup_on_error{[this, &tls, &page_pool]() noexcept -> void { + m_host_vmcb_phys = bsl::safe_uintmax::failure(); + page_pool.deallocate(tls, m_host_vmcb, ALLOCATE_TAG_HOST_VMCB); + m_host_vmcb = {}; + + m_guest_vmcb_phys = bsl::safe_uintmax::failure(); + page_pool.deallocate(tls, m_guest_vmcb, ALLOCATE_TAG_GUEST_VMCB); + m_guest_vmcb = {}; }}; - m_guest_vmcb = m_page_pool->template allocate(); + m_guest_vmcb = page_pool.template allocate(tls, ALLOCATE_TAG_GUEST_VMCB); if (bsl::unlikely(nullptr == m_guest_vmcb)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); } - m_guest_vmcb_phys = m_page_pool->virt_to_phys(m_guest_vmcb); - if (bsl::unlikely(!m_guest_vmcb_phys)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; + m_guest_vmcb_phys = page_pool.virt_to_phys(m_guest_vmcb); + if (bsl::unlikely_assert(!m_guest_vmcb_phys)) { + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); } - m_host_vmcb = m_page_pool->template allocate(); + m_host_vmcb = page_pool.template allocate(tls, ALLOCATE_TAG_HOST_VMCB); if (bsl::unlikely(nullptr == m_host_vmcb)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); } - m_host_vmcb_phys = m_page_pool->virt_to_phys(m_host_vmcb); - if (bsl::unlikely(!m_host_vmcb_phys)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; + m_host_vmcb_phys = page_pool.virt_to_phys(m_host_vmcb); + if (bsl::unlikely_assert(!m_host_vmcb_phys)) { + bsl::print() << bsl::here(); + return bsl::safe_uint16::failure(); } - release_on_error.ignore(); - m_allocated = true; + m_assigned_vpid = vpid; + m_assigned_ppid = ppid; + m_allocated = allocated_status_t::allocated; - return bsl::errc_success; + cleanup_on_error.ignore(); + return m_id; } /// /// @brief Deallocates this vps_t /// - constexpr void - deallocate() &noexcept + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + deallocate(tls_t &tls, page_pool_t &page_pool) noexcept -> bsl::errc_type { - m_host_vmcb_phys = bsl::safe_uintmax::zero(true); - - if (nullptr != m_page_pool) { - m_page_pool->deallocate(m_host_vmcb); - m_host_vmcb = {}; - } - else { - bsl::touch(); + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; } - m_guest_vmcb_phys = bsl::safe_uintmax::zero(true); + if (bsl::unlikely(m_allocated == allocated_status_t::zombie)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is a zombie and cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- - if (nullptr != m_page_pool) { - m_page_pool->deallocate(m_guest_vmcb); - m_guest_vmcb = {}; - } - else { - bsl::touch(); + return bsl::errc_precondition; } - m_allocated = {}; + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is already deallocated and cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + tls.state_reversal_required = true; + bsl::finally zombify_on_error{[this]() noexcept -> void { + this->zombify(); + }}; + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is active on pp " // -- + << bsl::hex(m_active_ppid) // -- + << " and therefore vps " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + m_gprs = {}; + + m_host_vmcb_phys = bsl::safe_uintmax::failure(); + page_pool.deallocate(tls, m_host_vmcb, ALLOCATE_TAG_HOST_VMCB); + m_host_vmcb = {}; + + m_guest_vmcb_phys = bsl::safe_uintmax::failure(); + page_pool.deallocate(tls, m_guest_vmcb, ALLOCATE_TAG_GUEST_VMCB); + m_guest_vmcb = {}; + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vpid = syscall::BF_INVALID_ID; + m_allocated = allocated_status_t::deallocated; + + zombify_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Sets this vps_t's status as zombified, meaning it is no + /// longer usable. + /// + constexpr void + zombify() noexcept + { + if (bsl::unlikely_assert(!m_id)) { + return; + } + + if (m_allocated == allocated_status_t::zombie) { + return; + } + + bsl::alert() << "vps " // -- + << bsl::hex(m_id) // -- + << " has been zombified" // -- + << bsl::endl; // -- + + m_allocated = allocated_status_t::zombie; + } + + /// + /// @brief Returns true if this vps_t is deallocated, false otherwise + /// + /// + /// @return Returns true if this vps_t is deallocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_deallocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::deallocated; + } + + /// + /// @brief Returns true if this vps_t is allocated, false otherwise + /// + /// + /// @return Returns true if this vps_t is allocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_allocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::allocated; + } + + /// + /// @brief Returns true if this vps_t is a zombie, false otherwise + /// + /// + /// @return Returns true if this vps_t is a zombie, false otherwise + /// + [[nodiscard]] constexpr auto + is_zombie() const noexcept -> bool + { + return m_allocated == allocated_status_t::zombie; + } + + /// + /// @brief Sets this vps_t as active. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_active(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.active_vpid != m_assigned_vpid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is assigned to vp " // -- + << bsl::hex(m_assigned_vpid) // -- + << " and cannot be activated with vp " // -- + << bsl::hex(tls.active_vpid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be activated on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID != tls.active_vpsid)) { + bsl::error() << "vps " // -- + << bsl::hex(tls.active_vpsid) // -- + << " is still active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is already the active vps on pp " // -- + << bsl::hex(m_active_ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RAX, m_gprs.rax); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBX, m_gprs.rbx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RCX, m_gprs.rcx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDX, m_gprs.rdx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBP, m_gprs.rbp); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RSI, m_gprs.rsi); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDI, m_gprs.rdi); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R8, m_gprs.r8); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R9, m_gprs.r9); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R10, m_gprs.r10); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R11, m_gprs.r11); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R12, m_gprs.r12); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R13, m_gprs.r13); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R14, m_gprs.r14); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R15, m_gprs.r15); + + tls.active_vpsid = m_id.get(); + m_active_ppid = tls.ppid; + + return bsl::errc_success; + } + + /// + /// @brief Sets this vps_t as inactive. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_inactive(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::deallocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == tls.active_vpsid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is not active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(tls.active_vpsid != m_id)) { + bsl::error() << "vps " // -- + << bsl::hex(tls.active_vpsid) // -- + << " is still active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(!m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is not active " // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(tls.ppid != m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is not active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + m_gprs.rax = intrinsic.tls_reg(syscall::TLS_OFFSET_RAX).get(); + m_gprs.rbx = intrinsic.tls_reg(syscall::TLS_OFFSET_RBX).get(); + m_gprs.rcx = intrinsic.tls_reg(syscall::TLS_OFFSET_RCX).get(); + m_gprs.rdx = intrinsic.tls_reg(syscall::TLS_OFFSET_RDX).get(); + m_gprs.rbp = intrinsic.tls_reg(syscall::TLS_OFFSET_RBP).get(); + m_gprs.rsi = intrinsic.tls_reg(syscall::TLS_OFFSET_RSI).get(); + m_gprs.rdi = intrinsic.tls_reg(syscall::TLS_OFFSET_RDI).get(); + m_gprs.r8 = intrinsic.tls_reg(syscall::TLS_OFFSET_R8).get(); + m_gprs.r9 = intrinsic.tls_reg(syscall::TLS_OFFSET_R9).get(); + m_gprs.r10 = intrinsic.tls_reg(syscall::TLS_OFFSET_R10).get(); + m_gprs.r11 = intrinsic.tls_reg(syscall::TLS_OFFSET_R11).get(); + m_gprs.r12 = intrinsic.tls_reg(syscall::TLS_OFFSET_R12).get(); + m_gprs.r13 = intrinsic.tls_reg(syscall::TLS_OFFSET_R13).get(); + m_gprs.r14 = intrinsic.tls_reg(syscall::TLS_OFFSET_R14).get(); + m_gprs.r15 = intrinsic.tls_reg(syscall::TLS_OFFSET_R15).get(); + + tls.active_vpsid = syscall::BF_INVALID_ID.get(); + m_active_ppid = bsl::safe_uint16::failure(); + + return bsl::errc_success; + } + + /// + /// @brief Returns the ID of the PP that this vps_t is still active + /// on. If the vps_t is inactive, this function returns + /// bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @return Returns the ID of the PP that this vps_t is still active + /// on. If the vps_t is inactive, this function returns + /// bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_active(tls_t &tls) const noexcept -> bsl::safe_uint16 + { + bsl::discard(tls); + return m_active_ppid; + } + + /// + /// @brief Returns true if this vps_t is active on the current PP, + /// false otherwise + /// + /// + /// @param tls the current TLS block + /// @return Returns true if this vps_t is active on the current PP, + /// false otherwise + /// + [[nodiscard]] constexpr auto + is_active_on_current_pp(tls_t &tls) const noexcept -> bool + { + return tls.ppid == m_active_ppid; + } + + /// + /// @brief Migrates this vps_t from one PP to another. This should + /// only be called by the run ABI when the VP and VPS's assigned + /// ppids do not match. The VPS should always match the assigned + /// VP's ID. If it doesn't we need to migrate the VPS. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param ppid the ID of the PP to migrate to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + migrate(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uint16 const &ppid) noexcept + -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(ppid); + + // if (bsl::unlikely_assert(!m_id)) { + // bsl::error() << "vps_t not initialized\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(!m_allocated)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " was never allocated" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(!ppid)) { + // bsl::error() << "invalid ppid\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(syscall::BF_INVALID_ID == ppid)) { + // bsl::error() << "invalid ppid\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(!(ppid < tls.online_pps))) { + // bsl::error() << "invalid ppid\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(tls.ppid != ppid)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " is being migrated to pp " // -- + // << bsl::hex(ppid) // -- + // << " by pp " // -- + // << bsl::hex(tls.ppid) // -- + // << " which is not allowed " // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(ppid == m_assigned_ppid)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " is already assigned to a pp " // -- + // << bsl::hex(m_assigned_ppid) // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(syscall::BF_INVALID_ID != m_active_ppid)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " is still active on pp " // -- + // << bsl::hex(m_active_ppid) // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // m_guest_vmcb->vmcb_clean_bits = bsl::ZERO_U32.get(); + // m_assigned_ppid = ppid; + + return bsl::errc_success; + } + + /// + /// @brief Returns the ID of the VP this vp_t is assigned to + /// + /// + /// @return Returns the ID of the VP this vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_vp() const noexcept -> bsl::safe_uint16 + { + if (bsl::unlikely(syscall::BF_INVALID_ID == m_assigned_vpid)) { + return bsl::safe_uint16::failure(); + } + + return m_assigned_vpid; + } + + /// + /// @brief Returns the ID of the PP this vp_t is assigned to + /// + /// + /// @return Returns the ID of the PP this vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_pp() const noexcept -> bsl::safe_uint16 + { + if (bsl::unlikely(syscall::BF_INVALID_ID == m_assigned_ppid)) { + return bsl::safe_uint16::failure(); + } + + return m_assigned_ppid; } /// /// @brief Stores the provided state in the VPS. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam STATE_SAVE_CONCEPT the type of state save to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param state the state to set the VPS to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - state_save_to_vps(TLS_CONCEPT &tls, STATE_SAVE_CONCEPT const *const state) &noexcept + state_save_to_vps( + tls_t &tls, intrinsic_t &intrinsic, loader::state_save_t const &state) noexcept -> bsl::errc_type { - bsl::discard(tls); - - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; } - if (bsl::unlikely(nullptr == state)) { - bsl::error() << "invalid state\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; } - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RAX, state->rax); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RBX, state->rbx); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RCX, state->rcx); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RDX, state->rdx); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RBP, state->rbp); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RSI, state->rsi); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RDI, state->rdi); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R8, state->r8); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R9, state->r9); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R10, state->r10); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R11, state->r11); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R12, state->r12); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R13, state->r13); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R14, state->r14); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R15, state->r15); + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- - m_guest_vmcb->rsp = state->rsp; - m_guest_vmcb->rip = state->rip; + return bsl::errc_precondition; + } - m_guest_vmcb->rflags = state->rflags; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RAX, state.rax); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBX, state.rbx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RCX, state.rcx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDX, state.rdx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBP, state.rbp); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RSI, state.rsi); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDI, state.rdi); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R8, state.r8); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R9, state.r9); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R10, state.r10); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R11, state.r11); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R12, state.r12); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R13, state.r13); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R14, state.r14); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R15, state.r15); + } + else { + m_gprs.rax = state.rax; + m_gprs.rbx = state.rbx; + m_gprs.rcx = state.rcx; + m_gprs.rdx = state.rdx; + m_gprs.rbp = state.rbp; + m_gprs.rsi = state.rsi; + m_gprs.rdi = state.rdi; + m_gprs.r8 = state.r8; + m_gprs.r9 = state.r9; + m_gprs.r10 = state.r10; + m_gprs.r11 = state.r11; + m_gprs.r12 = state.r12; + m_gprs.r13 = state.r13; + m_gprs.r14 = state.r14; + m_gprs.r15 = state.r15; + } - m_guest_vmcb->gdtr_limit = state->gdtr.limit; - m_guest_vmcb->gdtr_base = bsl::to_umax(state->gdtr.base).get(); - m_guest_vmcb->idtr_limit = state->idtr.limit; - m_guest_vmcb->idtr_base = bsl::to_umax(state->idtr.base).get(); + m_guest_vmcb->rsp = state.rsp; + m_guest_vmcb->rip = state.rip; - m_guest_vmcb->es_selector = state->es_selector; - m_guest_vmcb->es_attrib = details::compress_attrib(state->es_attrib).get(); - m_guest_vmcb->es_limit = state->es_limit; - m_guest_vmcb->es_base = state->es_base; + m_guest_vmcb->rflags = state.rflags; - m_guest_vmcb->cs_selector = state->cs_selector; - m_guest_vmcb->cs_attrib = details::compress_attrib(state->cs_attrib).get(); - m_guest_vmcb->cs_limit = state->cs_limit; - m_guest_vmcb->cs_base = state->cs_base; + m_guest_vmcb->gdtr_limit = bsl::to_u32(state.gdtr.limit).get(); + m_guest_vmcb->gdtr_base = bsl::to_umax(state.gdtr.base).get(); + m_guest_vmcb->idtr_limit = bsl::to_u32(state.idtr.limit).get(); + m_guest_vmcb->idtr_base = bsl::to_umax(state.idtr.base).get(); - m_guest_vmcb->ss_selector = state->ss_selector; - m_guest_vmcb->ss_attrib = details::compress_attrib(state->ss_attrib).get(); - m_guest_vmcb->ss_limit = state->ss_limit; - m_guest_vmcb->ss_base = state->ss_base; + m_guest_vmcb->es_selector = state.es_selector; + m_guest_vmcb->es_attrib = compress_attrib(state.es_attrib).get(); + m_guest_vmcb->es_limit = state.es_limit; + m_guest_vmcb->es_base = state.es_base; - m_guest_vmcb->ds_selector = state->ds_selector; - m_guest_vmcb->ds_attrib = details::compress_attrib(state->ds_attrib).get(); - m_guest_vmcb->ds_limit = state->ds_limit; - m_guest_vmcb->ds_base = state->ds_base; + m_guest_vmcb->cs_selector = state.cs_selector; + m_guest_vmcb->cs_attrib = compress_attrib(state.cs_attrib).get(); + m_guest_vmcb->cs_limit = state.cs_limit; + m_guest_vmcb->cs_base = state.cs_base; - m_guest_vmcb->fs_selector = state->fs_selector; - m_guest_vmcb->fs_attrib = details::compress_attrib(state->fs_attrib).get(); - m_guest_vmcb->fs_limit = state->fs_limit; + m_guest_vmcb->ss_selector = state.ss_selector; + m_guest_vmcb->ss_attrib = compress_attrib(state.ss_attrib).get(); + m_guest_vmcb->ss_limit = state.ss_limit; + m_guest_vmcb->ss_base = state.ss_base; - m_guest_vmcb->gs_selector = state->gs_selector; - m_guest_vmcb->gs_attrib = details::compress_attrib(state->gs_attrib).get(); - m_guest_vmcb->gs_limit = state->gs_limit; + m_guest_vmcb->ds_selector = state.ds_selector; + m_guest_vmcb->ds_attrib = compress_attrib(state.ds_attrib).get(); + m_guest_vmcb->ds_limit = state.ds_limit; + m_guest_vmcb->ds_base = state.ds_base; - m_guest_vmcb->ldtr_selector = state->ldtr_selector; - m_guest_vmcb->ldtr_attrib = details::compress_attrib(state->ldtr_attrib).get(); - m_guest_vmcb->ldtr_limit = state->ldtr_limit; - m_guest_vmcb->ldtr_base = state->ldtr_base; + m_guest_vmcb->fs_selector = state.fs_selector; + m_guest_vmcb->fs_attrib = compress_attrib(state.fs_attrib).get(); + m_guest_vmcb->fs_limit = state.fs_limit; - m_guest_vmcb->tr_selector = state->tr_selector; - m_guest_vmcb->tr_attrib = details::compress_attrib(state->tr_attrib).get(); - m_guest_vmcb->tr_limit = state->tr_limit; - m_guest_vmcb->tr_base = state->tr_base; + m_guest_vmcb->gs_selector = state.gs_selector; + m_guest_vmcb->gs_attrib = compress_attrib(state.gs_attrib).get(); + m_guest_vmcb->gs_limit = state.gs_limit; - m_guest_vmcb->cr0 = state->cr0; - m_guest_vmcb->cr2 = state->cr2; - m_guest_vmcb->cr3 = state->cr3; - m_guest_vmcb->cr4 = state->cr4; + m_guest_vmcb->ldtr_selector = state.ldtr_selector; + m_guest_vmcb->ldtr_attrib = compress_attrib(state.ldtr_attrib).get(); + m_guest_vmcb->ldtr_limit = state.ldtr_limit; + m_guest_vmcb->ldtr_base = state.ldtr_base; - m_guest_vmcb->dr6 = state->dr6; - m_guest_vmcb->dr7 = state->dr7; + m_guest_vmcb->tr_selector = state.tr_selector; + m_guest_vmcb->tr_attrib = compress_attrib(state.tr_attrib).get(); + m_guest_vmcb->tr_limit = state.tr_limit; + m_guest_vmcb->tr_base = state.tr_base; - m_guest_vmcb->efer = state->ia32_efer; - m_guest_vmcb->star = state->ia32_star; - m_guest_vmcb->lstar = state->ia32_lstar; - m_guest_vmcb->cstar = state->ia32_cstar; - m_guest_vmcb->sfmask = state->ia32_fmask; - m_guest_vmcb->fs_base = state->ia32_fs_base; - m_guest_vmcb->gs_base = state->ia32_gs_base; - m_guest_vmcb->kernel_gs_base = state->ia32_kernel_gs_base; - m_guest_vmcb->sysenter_cs = state->ia32_sysenter_cs; - m_guest_vmcb->sysenter_esp = state->ia32_sysenter_esp; - m_guest_vmcb->sysenter_eip = state->ia32_sysenter_eip; - m_guest_vmcb->g_pat = state->ia32_pat; - m_guest_vmcb->dbgctl = state->ia32_debugctl; + m_guest_vmcb->cr0 = state.cr0; + m_guest_vmcb->cr2 = state.cr2; + m_guest_vmcb->cr3 = state.cr3; + m_guest_vmcb->cr4 = state.cr4; + + m_guest_vmcb->dr6 = state.dr6; + m_guest_vmcb->dr7 = state.dr7; + + m_guest_vmcb->efer = state.ia32_efer; + m_guest_vmcb->star = state.ia32_star; + m_guest_vmcb->lstar = state.ia32_lstar; + m_guest_vmcb->cstar = state.ia32_cstar; + m_guest_vmcb->sfmask = state.ia32_fmask; + m_guest_vmcb->fs_base = state.ia32_fs_base; + m_guest_vmcb->gs_base = state.ia32_gs_base; + m_guest_vmcb->kernel_gs_base = state.ia32_kernel_gs_base; + m_guest_vmcb->sysenter_cs = state.ia32_sysenter_cs; + m_guest_vmcb->sysenter_esp = state.ia32_sysenter_esp; + m_guest_vmcb->sysenter_eip = state.ia32_sysenter_eip; + m_guest_vmcb->g_pat = state.ia32_pat; + m_guest_vmcb->dbgctl = state.ia32_debugctl; return bsl::errc_success; } @@ -467,115 +1054,148 @@ namespace mk /// @brief Stores the VPS state in the provided state save. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam STATE_SAVE_CONCEPT the type of state save to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param state the state save to store the VPS state to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - vps_to_state_save(TLS_CONCEPT &tls, STATE_SAVE_CONCEPT *const state) &noexcept + vps_to_state_save(tls_t &tls, intrinsic_t &intrinsic, loader::state_save_t &state) noexcept -> bsl::errc_type { - bsl::discard(tls); - - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; } - if (bsl::unlikely(nullptr == state)) { - bsl::error() << "invalid state\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; } - state->rax = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RAX).get(); - state->rbx = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RBX).get(); - state->rcx = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RCX).get(); - state->rdx = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RDX).get(); - state->rbp = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RBP).get(); - state->rsi = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RSI).get(); - state->rdi = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RDI).get(); - state->r8 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R8).get(); - state->r9 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R9).get(); - state->r10 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R10).get(); - state->r11 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R11).get(); - state->r12 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R12).get(); - state->r13 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R13).get(); - state->r14 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R14).get(); - state->r15 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R15).get(); + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- - state->rsp = m_guest_vmcb->rsp; - state->rip = m_guest_vmcb->rip; + return bsl::errc_precondition; + } - state->rflags = m_guest_vmcb->rflags; + if (tls.active_vpsid == m_id) { + state.rax = intrinsic.tls_reg(syscall::TLS_OFFSET_RAX).get(); + state.rbx = intrinsic.tls_reg(syscall::TLS_OFFSET_RBX).get(); + state.rcx = intrinsic.tls_reg(syscall::TLS_OFFSET_RCX).get(); + state.rdx = intrinsic.tls_reg(syscall::TLS_OFFSET_RDX).get(); + state.rbp = intrinsic.tls_reg(syscall::TLS_OFFSET_RBP).get(); + state.rsi = intrinsic.tls_reg(syscall::TLS_OFFSET_RSI).get(); + state.rdi = intrinsic.tls_reg(syscall::TLS_OFFSET_RDI).get(); + state.r8 = intrinsic.tls_reg(syscall::TLS_OFFSET_R8).get(); + state.r9 = intrinsic.tls_reg(syscall::TLS_OFFSET_R9).get(); + state.r10 = intrinsic.tls_reg(syscall::TLS_OFFSET_R10).get(); + state.r11 = intrinsic.tls_reg(syscall::TLS_OFFSET_R11).get(); + state.r12 = intrinsic.tls_reg(syscall::TLS_OFFSET_R12).get(); + state.r13 = intrinsic.tls_reg(syscall::TLS_OFFSET_R13).get(); + state.r14 = intrinsic.tls_reg(syscall::TLS_OFFSET_R14).get(); + state.r15 = intrinsic.tls_reg(syscall::TLS_OFFSET_R15).get(); + } + else { + state.rax = m_gprs.rax; + state.rbx = m_gprs.rbx; + state.rcx = m_gprs.rcx; + state.rdx = m_gprs.rdx; + state.rbp = m_gprs.rbp; + state.rsi = m_gprs.rsi; + state.rdi = m_gprs.rdi; + state.r8 = m_gprs.r8; + state.r9 = m_gprs.r9; + state.r10 = m_gprs.r10; + state.r11 = m_gprs.r11; + state.r12 = m_gprs.r12; + state.r13 = m_gprs.r13; + state.r14 = m_gprs.r14; + state.r15 = m_gprs.r15; + } - state->gdtr.limit = bsl::to_u16(m_guest_vmcb->gdtr_limit).get(); - state->gdtr.base = bsl::to_ptr(m_guest_vmcb->gdtr_base); - state->idtr.limit = bsl::to_u16(m_guest_vmcb->idtr_limit).get(); - state->idtr.base = bsl::to_ptr(m_guest_vmcb->idtr_base); + state.rsp = m_guest_vmcb->rsp; + state.rip = m_guest_vmcb->rip; - state->es_selector = m_guest_vmcb->es_selector; - state->es_attrib = details::decompress_attrib(m_guest_vmcb->es_attrib).get(); - state->es_limit = m_guest_vmcb->es_limit; - state->es_base = m_guest_vmcb->es_base; + state.rflags = m_guest_vmcb->rflags; - state->cs_selector = m_guest_vmcb->cs_selector; - state->cs_attrib = details::decompress_attrib(m_guest_vmcb->cs_attrib).get(); - state->cs_limit = m_guest_vmcb->cs_limit; - state->cs_base = m_guest_vmcb->cs_base; + state.gdtr.limit = bsl::to_u16(m_guest_vmcb->gdtr_limit).get(); + state.gdtr.base = bsl::to_ptr(m_guest_vmcb->gdtr_base); + state.idtr.limit = bsl::to_u16(m_guest_vmcb->idtr_limit).get(); + state.idtr.base = bsl::to_ptr(m_guest_vmcb->idtr_base); - state->ss_selector = m_guest_vmcb->ss_selector; - state->ss_attrib = details::decompress_attrib(m_guest_vmcb->ss_attrib).get(); - state->ss_limit = m_guest_vmcb->ss_limit; - state->ss_base = m_guest_vmcb->ss_base; + state.es_selector = m_guest_vmcb->es_selector; + state.es_attrib = decompress_attrib(m_guest_vmcb->es_attrib).get(); + state.es_limit = m_guest_vmcb->es_limit; + state.es_base = m_guest_vmcb->es_base; - state->ds_selector = m_guest_vmcb->ds_selector; - state->ds_attrib = details::decompress_attrib(m_guest_vmcb->ds_attrib).get(); - state->ds_limit = m_guest_vmcb->ds_limit; - state->ds_base = m_guest_vmcb->ds_base; + state.cs_selector = m_guest_vmcb->cs_selector; + state.cs_attrib = decompress_attrib(m_guest_vmcb->cs_attrib).get(); + state.cs_limit = m_guest_vmcb->cs_limit; + state.cs_base = m_guest_vmcb->cs_base; - state->fs_selector = m_guest_vmcb->fs_selector; - state->fs_attrib = details::decompress_attrib(m_guest_vmcb->fs_attrib).get(); - state->fs_limit = m_guest_vmcb->fs_limit; + state.ss_selector = m_guest_vmcb->ss_selector; + state.ss_attrib = decompress_attrib(m_guest_vmcb->ss_attrib).get(); + state.ss_limit = m_guest_vmcb->ss_limit; + state.ss_base = m_guest_vmcb->ss_base; - state->gs_selector = m_guest_vmcb->gs_selector; - state->gs_attrib = details::decompress_attrib(m_guest_vmcb->gs_attrib).get(); - state->gs_limit = m_guest_vmcb->gs_limit; + state.ds_selector = m_guest_vmcb->ds_selector; + state.ds_attrib = decompress_attrib(m_guest_vmcb->ds_attrib).get(); + state.ds_limit = m_guest_vmcb->ds_limit; + state.ds_base = m_guest_vmcb->ds_base; - state->ldtr_selector = m_guest_vmcb->ldtr_selector; - state->ldtr_attrib = details::decompress_attrib(m_guest_vmcb->ldtr_attrib).get(); - state->ldtr_limit = m_guest_vmcb->ldtr_limit; - state->ldtr_base = m_guest_vmcb->ldtr_base; + state.fs_selector = m_guest_vmcb->fs_selector; + state.fs_attrib = decompress_attrib(m_guest_vmcb->fs_attrib).get(); + state.fs_limit = m_guest_vmcb->fs_limit; - state->tr_selector = m_guest_vmcb->tr_selector; - state->tr_attrib = details::decompress_attrib(m_guest_vmcb->tr_attrib).get(); - state->tr_limit = m_guest_vmcb->tr_limit; - state->tr_base = m_guest_vmcb->tr_base; + state.gs_selector = m_guest_vmcb->gs_selector; + state.gs_attrib = decompress_attrib(m_guest_vmcb->gs_attrib).get(); + state.gs_limit = m_guest_vmcb->gs_limit; - state->cr0 = m_guest_vmcb->cr0; - state->cr2 = m_guest_vmcb->cr2; - state->cr3 = m_guest_vmcb->cr3; - state->cr4 = m_guest_vmcb->cr4; + state.ldtr_selector = m_guest_vmcb->ldtr_selector; + state.ldtr_attrib = decompress_attrib(m_guest_vmcb->ldtr_attrib).get(); + state.ldtr_limit = m_guest_vmcb->ldtr_limit; + state.ldtr_base = m_guest_vmcb->ldtr_base; - state->dr6 = m_guest_vmcb->dr6; - state->dr7 = m_guest_vmcb->dr7; + state.tr_selector = m_guest_vmcb->tr_selector; + state.tr_attrib = decompress_attrib(m_guest_vmcb->tr_attrib).get(); + state.tr_limit = m_guest_vmcb->tr_limit; + state.tr_base = m_guest_vmcb->tr_base; - state->ia32_efer = m_guest_vmcb->efer; - state->ia32_star = m_guest_vmcb->star; - state->ia32_lstar = m_guest_vmcb->lstar; - state->ia32_cstar = m_guest_vmcb->cstar; - state->ia32_fmask = m_guest_vmcb->sfmask; - state->ia32_fs_base = m_guest_vmcb->fs_base; - state->ia32_gs_base = m_guest_vmcb->gs_base; - state->ia32_kernel_gs_base = m_guest_vmcb->kernel_gs_base; - state->ia32_sysenter_cs = m_guest_vmcb->sysenter_cs; - state->ia32_sysenter_esp = m_guest_vmcb->sysenter_esp; - state->ia32_sysenter_eip = m_guest_vmcb->sysenter_eip; - state->ia32_pat = m_guest_vmcb->g_pat; - state->ia32_debugctl = m_guest_vmcb->dbgctl; + state.cr0 = m_guest_vmcb->cr0; + state.cr2 = m_guest_vmcb->cr2; + state.cr3 = m_guest_vmcb->cr3; + state.cr4 = m_guest_vmcb->cr4; + + state.dr6 = m_guest_vmcb->dr6; + state.dr7 = m_guest_vmcb->dr7; + + state.ia32_efer = m_guest_vmcb->efer; + state.ia32_star = m_guest_vmcb->star; + state.ia32_lstar = m_guest_vmcb->lstar; + state.ia32_cstar = m_guest_vmcb->cstar; + state.ia32_fmask = m_guest_vmcb->sfmask; + state.ia32_fs_base = m_guest_vmcb->fs_base; + state.ia32_gs_base = m_guest_vmcb->gs_base; + state.ia32_kernel_gs_base = m_guest_vmcb->kernel_gs_base; + state.ia32_sysenter_cs = m_guest_vmcb->sysenter_cs; + state.ia32_sysenter_esp = m_guest_vmcb->sysenter_esp; + state.ia32_sysenter_eip = m_guest_vmcb->sysenter_eip; + state.ia32_pat = m_guest_vmcb->g_pat; + state.ia32_debugctl = m_guest_vmcb->dbgctl; return bsl::errc_success; } @@ -585,24 +1205,47 @@ namespace mk /// the field to read. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @tparam FIELD_TYPE the type (i.e., size) of field to read /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param index the index of the field to read from the VPS /// @return Returns the value of the requested field from the - /// VPS or bsl::safe_integral::zero(true) + /// VPS or bsl::safe_integral::failure() /// on failure. /// - template + template [[nodiscard]] constexpr auto - read(TLS_CONCEPT &tls, bsl::safe_uintmax const &index) &noexcept + read(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uintmax const &index) noexcept -> bsl::safe_integral { - bsl::discard(tls); + bsl::discard(intrinsic); - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::safe_integral::zero(true); + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::safe_integral::failure(); + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_integral::failure(); + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_integral::failure(); } auto const view{bsl::as_t(m_guest_vmcb, sizeof(vmcb_t))}; @@ -610,12 +1253,13 @@ namespace mk auto *const ptr{view.at_if(view_index)}; if (bsl::unlikely(nullptr == ptr)) { - bsl::error() << "invalid index: " // -- - << bsl::hex(index) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "index " // -- + << bsl::hex(index) // -- + << " is invalid" // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::safe_integral::zero(true); + return bsl::safe_integral::failure(); } return *ptr; @@ -626,35 +1270,55 @@ namespace mk /// the field and the value to write. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @tparam FIELD_TYPE the type (i.e., size) of field to write /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param index the index of the field to write to the VPS - /// @param value the value to write to the VPS + /// @param val the value to write to the VPS /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template + template [[nodiscard]] constexpr auto write( - TLS_CONCEPT &tls, + tls_t &tls, + intrinsic_t &intrinsic, bsl::safe_uintmax const &index, - bsl::safe_integral const &value) &noexcept -> bsl::errc_type + bsl::safe_integral const &val) noexcept -> bsl::errc_type { - bsl::discard(tls); + bsl::discard(intrinsic); - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(!val)) { + bsl::error() << "invalid value\n" << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(!value)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(value) // -- - << bsl::endl // -- - << bsl::here(); // -- + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::errc_failure; + return bsl::errc_precondition; } auto view{bsl::as_writable_t(m_guest_vmcb, sizeof(vmcb_t))}; @@ -662,15 +1326,16 @@ namespace mk auto *const ptr{view.at_if(view_index)}; if (bsl::unlikely(nullptr == ptr)) { - bsl::error() << "invalid index: " // -- - << bsl::hex(index) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "index " // -- + << bsl::hex(index) // -- + << " is invalid" // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - *ptr = value.get(); + *ptr = val.get(); return bsl::errc_success; } @@ -679,82 +1344,163 @@ namespace mk /// defining the field to read. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param reg a bf_reg_t defining the field to read from the VPS /// @return Returns the value of the requested field from the - /// VPS or bsl::safe_uintmax::zero(true) on failure. + /// VPS or bsl::safe_uintmax::failure() on failure. /// - template [[nodiscard]] constexpr auto - read_reg(TLS_CONCEPT &tls, syscall::bf_reg_t const reg) &noexcept -> bsl::safe_uintmax + read_reg(tls_t &tls, intrinsic_t &intrinsic, syscall::bf_reg_t const reg) noexcept + -> bsl::safe_uintmax { - bsl::discard(tls); + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::safe_uintmax::failure(); + } - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); } switch (reg) { case syscall::bf_reg_t::bf_reg_t_rax: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RAX); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RAX); + } + + return m_gprs.rax; } case syscall::bf_reg_t::bf_reg_t_rbx: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RBX); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RBX); + } + + return m_gprs.rbx; } case syscall::bf_reg_t::bf_reg_t_rcx: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RCX); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RCX); + } + + return m_gprs.rcx; } case syscall::bf_reg_t::bf_reg_t_rdx: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RDX); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RDX); + } + + return m_gprs.rdx; } case syscall::bf_reg_t::bf_reg_t_rbp: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RBP); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RBP); + } + + return m_gprs.rbp; } case syscall::bf_reg_t::bf_reg_t_rsi: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RSI); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RSI); + } + + return m_gprs.rsi; } case syscall::bf_reg_t::bf_reg_t_rdi: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RDI); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RDI); + } + + return m_gprs.rdi; } case syscall::bf_reg_t::bf_reg_t_r8: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R8); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R8); + } + + return m_gprs.r8; } case syscall::bf_reg_t::bf_reg_t_r9: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R9); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R9); + } + + return m_gprs.r9; } case syscall::bf_reg_t::bf_reg_t_r10: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R10); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R10); + } + + return m_gprs.r10; } case syscall::bf_reg_t::bf_reg_t_r11: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R11); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R11); + } + + return m_gprs.r11; } case syscall::bf_reg_t::bf_reg_t_r12: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R12); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R12); + } + + return m_gprs.r12; } case syscall::bf_reg_t::bf_reg_t_r13: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R13); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R13); + } + + return m_gprs.r13; } case syscall::bf_reg_t::bf_reg_t_r14: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R14); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R14); + } + + return m_gprs.r14; } case syscall::bf_reg_t::bf_reg_t_r15: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R15); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R15); + } + + return m_gprs.r15; } case syscall::bf_reg_t::bf_reg_t_rsp: { @@ -991,9 +1737,11 @@ namespace mk default: { bsl::error() << "unknown by bf_reg_t\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); + break; } } + + return bsl::safe_uintmax::failure(); } /// @@ -1001,408 +1749,501 @@ namespace mk /// defining the field and a value to write. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param reg a bf_reg_t defining the field to write to the VPS /// @param val the value to write to the VPS /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto write_reg( - TLS_CONCEPT &tls, syscall::bf_reg_t const reg, bsl::safe_uintmax const &val) &noexcept - -> bsl::errc_type + tls_t &tls, + intrinsic_t &intrinsic, + syscall::bf_reg_t const reg, + bsl::safe_uintmax const &val) noexcept -> bsl::errc_type { - bsl::discard(tls); + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(!val)) { + bsl::error() << "invalid value\n" << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::errc_failure; + return bsl::errc_precondition; } switch (reg) { case syscall::bf_reg_t::bf_reg_t_rax: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RAX, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RAX, val); + } + else { + m_gprs.rax = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rbx: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RBX, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBX, val); + } + else { + m_gprs.rbx = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rcx: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RCX, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RCX, val); + } + else { + m_gprs.rcx = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rdx: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RDX, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDX, val); + } + else { + m_gprs.rdx = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rbp: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RBP, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBP, val); + } + else { + m_gprs.rbp = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rsi: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RSI, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RSI, val); + } + else { + m_gprs.rsi = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rdi: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RDI, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDI, val); + } + else { + m_gprs.rdi = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r8: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R8, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R8, val); + } + else { + m_gprs.r8 = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r9: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R9, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R9, val); + } + else { + m_gprs.r9 = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r10: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R10, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R10, val); + } + else { + m_gprs.r10 = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r11: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R11, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R11, val); + } + else { + m_gprs.r11 = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r12: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R12, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R12, val); + } + else { + m_gprs.r12 = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r13: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R13, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R13, val); + } + else { + m_gprs.r13 = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r14: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R14, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R14, val); + } + else { + m_gprs.r14 = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r15: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R15, val); - break; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R15, val); + } + else { + m_gprs.r15 = val.get(); + } + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rsp: { m_guest_vmcb->rsp = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rip: { m_guest_vmcb->rip = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rflags: { m_guest_vmcb->rflags = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_gdtr_base_addr: { m_guest_vmcb->gdtr_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_gdtr_limit: { m_guest_vmcb->gdtr_limit = bsl::to_u32(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_idtr_base_addr: { m_guest_vmcb->idtr_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_idtr_limit: { m_guest_vmcb->idtr_limit = bsl::to_u32(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_es: { m_guest_vmcb->es_selector = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_es_base_addr: { m_guest_vmcb->es_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_es_limit: { m_guest_vmcb->es_limit = bsl::to_u32(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_es_attributes: { m_guest_vmcb->es_attrib = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_cs: { m_guest_vmcb->cs_selector = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_cs_base_addr: { m_guest_vmcb->cs_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_cs_limit: { m_guest_vmcb->cs_limit = bsl::to_u32(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_cs_attributes: { m_guest_vmcb->cs_attrib = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ss: { m_guest_vmcb->ss_selector = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ss_base_addr: { m_guest_vmcb->ss_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ss_limit: { m_guest_vmcb->ss_limit = bsl::to_u32(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ss_attributes: { m_guest_vmcb->ss_attrib = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ds: { m_guest_vmcb->ds_selector = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ds_base_addr: { m_guest_vmcb->ds_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ds_limit: { m_guest_vmcb->ds_limit = bsl::to_u32(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ds_attributes: { m_guest_vmcb->ds_attrib = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_fs: { m_guest_vmcb->fs_selector = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_fs_base_addr: { m_guest_vmcb->fs_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_fs_limit: { m_guest_vmcb->fs_limit = bsl::to_u32(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_fs_attributes: { m_guest_vmcb->fs_attrib = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_gs: { m_guest_vmcb->gs_selector = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_gs_base_addr: { m_guest_vmcb->gs_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_gs_limit: { m_guest_vmcb->gs_limit = bsl::to_u32(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_gs_attributes: { m_guest_vmcb->gs_attrib = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ldtr: { m_guest_vmcb->ldtr_selector = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ldtr_base_addr: { m_guest_vmcb->ldtr_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ldtr_limit: { m_guest_vmcb->ldtr_limit = bsl::to_u32(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ldtr_attributes: { m_guest_vmcb->ldtr_attrib = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_tr: { m_guest_vmcb->tr_selector = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_tr_base_addr: { m_guest_vmcb->tr_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_tr_limit: { m_guest_vmcb->tr_limit = bsl::to_u32(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_tr_attributes: { m_guest_vmcb->tr_attrib = bsl::to_u16(val).get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_cr0: { m_guest_vmcb->cr0 = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_cr2: { m_guest_vmcb->cr2 = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_cr3: { m_guest_vmcb->cr3 = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_cr4: { m_guest_vmcb->cr4 = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_dr6: { m_guest_vmcb->dr6 = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_dr7: { m_guest_vmcb->dr7 = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_efer: { m_guest_vmcb->efer = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_star: { m_guest_vmcb->star = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_lstar: { m_guest_vmcb->lstar = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_cstar: { m_guest_vmcb->cstar = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_fmask: { m_guest_vmcb->sfmask = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_fs_base: { m_guest_vmcb->fs_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_gs_base: { m_guest_vmcb->gs_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_kernel_gs_base: { m_guest_vmcb->kernel_gs_base = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_sysenter_cs: { m_guest_vmcb->sysenter_cs = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_sysenter_esp: { m_guest_vmcb->sysenter_esp = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_sysenter_eip: { m_guest_vmcb->sysenter_eip = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_pat: { m_guest_vmcb->g_pat = val.get(); - break; + return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_ia32_debugctl: { m_guest_vmcb->dbgctl = val.get(); - break; + return bsl::errc_success; } default: { bsl::error() << "unknown by bf_reg_t\n" << bsl::here(); - return bsl::errc_failure; + break; } } - return bsl::errc_success; + return bsl::errc_failure; } /// @@ -1411,30 +2252,73 @@ namespace mk /// will return the VMExit reason. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param log the VMExit log to use /// @return Returns the VMExit reason on success, or - /// bsl::safe_uintmax::zero(true) on failure. + /// bsl::safe_uintmax::failure() on failure. /// - template [[nodiscard]] constexpr auto - run(TLS_CONCEPT &tls) &noexcept -> bsl::safe_uintmax + run(tls_t &tls, intrinsic_t &intrinsic, vmexit_log_t &log) noexcept -> bsl::safe_uintmax { - constexpr bsl::safe_uintmax invalid_exit_reason{bsl::to_umax(0xFFFFFFFFFFFFFFFFU)}; - - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::safe_uintmax::failure(); } - auto const exit_reason{details::intrinsic_vmrun( + if (bsl::unlikely_assert(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + if (bsl::unlikely_assert(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot run by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + bsl::safe_uintmax const exit_reason{intrinsic_vmrun( m_guest_vmcb, m_guest_vmcb_phys.get(), m_host_vmcb, m_host_vmcb_phys.get())}; - if (invalid_exit_reason == exit_reason) { - this->dump(tls); - - bsl::error() << "vmrun failed\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); + if constexpr (!(BSL_DEBUG_LEVEL < bsl::VV)) { + log.add( + tls.ppid, + {tls.active_vmid, + tls.active_vpid, + tls.active_vpsid, + exit_reason, + m_guest_vmcb->exitinfo1, + m_guest_vmcb->exitinfo2, + m_guest_vmcb->exitininfo, + intrinsic.tls_reg(syscall::TLS_OFFSET_RAX), + intrinsic.tls_reg(syscall::TLS_OFFSET_RBX), + intrinsic.tls_reg(syscall::TLS_OFFSET_RCX), + intrinsic.tls_reg(syscall::TLS_OFFSET_RDX), + intrinsic.tls_reg(syscall::TLS_OFFSET_RBP), + intrinsic.tls_reg(syscall::TLS_OFFSET_RSI), + intrinsic.tls_reg(syscall::TLS_OFFSET_RDI), + intrinsic.tls_reg(syscall::TLS_OFFSET_R8), + intrinsic.tls_reg(syscall::TLS_OFFSET_R9), + intrinsic.tls_reg(syscall::TLS_OFFSET_R10), + intrinsic.tls_reg(syscall::TLS_OFFSET_R11), + intrinsic.tls_reg(syscall::TLS_OFFSET_R12), + intrinsic.tls_reg(syscall::TLS_OFFSET_R13), + intrinsic.tls_reg(syscall::TLS_OFFSET_R14), + intrinsic.tls_reg(syscall::TLS_OFFSET_R15), + m_guest_vmcb->rsp, + m_guest_vmcb->rip}); } /// TODO: @@ -1449,20 +2333,42 @@ namespace mk /// @brief Advance the IP of the VPS /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - advance_ip(TLS_CONCEPT &tls) &noexcept -> bsl::errc_type + advance_ip(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { - bsl::discard(tls); + bsl::discard(intrinsic); - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; } m_guest_vmcb->rip = m_guest_vmcb->nrip; @@ -1470,17 +2376,342 @@ namespace mk } /// - /// @brief Dumps the contents of the VPS to the console + /// @brief Clears the VPS's internal cache. Note that this is a + /// hardware specific function and doesn't change the actual + /// values stored in the VPS. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise /// - template - constexpr void - dump(TLS_CONCEPT &tls) &noexcept + [[nodiscard]] constexpr auto + clear(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { - bsl::discard(tls); + bsl::discard(intrinsic); + + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + constexpr auto reset{0_u32}; + m_guest_vmcb->vmcb_clean_bits = reset.get(); + return bsl::errc_success; + } + + /// + /// @brief Dumps the vm_t + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// + constexpr void + dump(tls_t &tls, intrinsic_t &intrinsic) const noexcept + { + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return; + } + + // clang-format off + + constexpr auto guest_instruction_bytes_0{0x0_umax}; + constexpr auto guest_instruction_bytes_1{0x1_umax}; + constexpr auto guest_instruction_bytes_2{0x2_umax}; + constexpr auto guest_instruction_bytes_3{0x3_umax}; + constexpr auto guest_instruction_bytes_4{0x4_umax}; + constexpr auto guest_instruction_bytes_5{0x5_umax}; + constexpr auto guest_instruction_bytes_6{0x6_umax}; + constexpr auto guest_instruction_bytes_7{0x7_umax}; + constexpr auto guest_instruction_bytes_8{0x8_umax}; + constexpr auto guest_instruction_bytes_9{0x9_umax}; + constexpr auto guest_instruction_bytes_a{0xA_umax}; + /// NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) + constexpr auto guest_instruction_bytes_b{0xB_umax}; + constexpr auto guest_instruction_bytes_c{0xC_umax}; + constexpr auto guest_instruction_bytes_d{0xD_umax}; + constexpr auto guest_instruction_bytes_e{0xE_umax}; + + if (bsl::unlikely_assert(!m_id)) { + bsl::print() << "[error]" << bsl::endl; + return; + } + + bsl::print() << bsl::mag << "vps ["; + bsl::print() << bsl::rst << bsl::hex(m_id); + bsl::print() << bsl::mag << "] dump: "; + bsl::print() << bsl::rst << bsl::endl; + + /// Header + /// + + bsl::print() << bsl::ylw << "+----------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^30s", "description "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^19s", "value "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+----------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + /// Allocated + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<30s", "allocated "}; + bsl::print() << bsl::ylw << "| "; + if (this->is_allocated()) { + bsl::print() << bsl::grn << bsl::fmt{"^19s", "yes "}; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^19s", "no "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Assigned VP + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<30s", "assigned vp "}; + bsl::print() << bsl::ylw << "| "; + if (m_assigned_vpid != syscall::BF_INVALID_ID) { + bsl::print() << bsl::grn << " " << bsl::hex(m_assigned_vpid) << " "; + } + else { + bsl::print() << bsl::red << " " << bsl::hex(m_assigned_vpid) << " "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Assigned PP + /// + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<30s", "assigned pp "}; + bsl::print() << bsl::ylw << "| "; + if (m_assigned_ppid != syscall::BF_INVALID_ID) { + bsl::print() << bsl::grn << " " << bsl::hex(m_assigned_ppid) << " "; + } + else { + bsl::print() << bsl::red << " " << bsl::hex(m_assigned_ppid) << " "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + + /// Guest Missing Fields + /// + + bsl::print() << bsl::ylw << "+----------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + if (!this->is_allocated()) { + return; + } + + if (tls.active_vpsid == m_id) { + this->dump_field("rax ", intrinsic.tls_reg(syscall::TLS_OFFSET_RAX)); + this->dump_field("rbx ", intrinsic.tls_reg(syscall::TLS_OFFSET_RBX)); + this->dump_field("rcx ", intrinsic.tls_reg(syscall::TLS_OFFSET_RCX)); + this->dump_field("rdx ", intrinsic.tls_reg(syscall::TLS_OFFSET_RDX)); + this->dump_field("rbp ", intrinsic.tls_reg(syscall::TLS_OFFSET_RBP)); + this->dump_field("rsi ", intrinsic.tls_reg(syscall::TLS_OFFSET_RSI)); + this->dump_field("rdi ", intrinsic.tls_reg(syscall::TLS_OFFSET_RDI)); + this->dump_field("r8 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R8)); + this->dump_field("r9 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R9)); + this->dump_field("r10 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R10)); + this->dump_field("r11 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R11)); + this->dump_field("r12 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R12)); + this->dump_field("r13 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R13)); + this->dump_field("r14 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R14)); + this->dump_field("r15 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R15)); + } + else { + this->dump_field("rax ", bsl::make_safe(m_gprs.rax)); + this->dump_field("rbx ", bsl::make_safe(m_gprs.rbx)); + this->dump_field("rcx ", bsl::make_safe(m_gprs.rcx)); + this->dump_field("rdx ", bsl::make_safe(m_gprs.rdx)); + this->dump_field("rbp ", bsl::make_safe(m_gprs.rbp)); + this->dump_field("rsi ", bsl::make_safe(m_gprs.rsi)); + this->dump_field("rdi ", bsl::make_safe(m_gprs.rdi)); + this->dump_field("r8 ", bsl::make_safe(m_gprs.r8)); + this->dump_field("r9 ", bsl::make_safe(m_gprs.r9)); + this->dump_field("r10 ", bsl::make_safe(m_gprs.r10)); + this->dump_field("r11 ", bsl::make_safe(m_gprs.r11)); + this->dump_field("r12 ", bsl::make_safe(m_gprs.r12)); + this->dump_field("r13 ", bsl::make_safe(m_gprs.r13)); + this->dump_field("r14 ", bsl::make_safe(m_gprs.r14)); + this->dump_field("r15 ", bsl::make_safe(m_gprs.r15)); + } + + /// Guest Control Area Fields + /// + + bsl::print() << bsl::ylw << "+----------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + this->dump_field("intercept_cr_read ", bsl::make_safe(m_guest_vmcb->intercept_cr_read)); + this->dump_field("intercept_cr_write ", bsl::make_safe(m_guest_vmcb->intercept_cr_write)); + this->dump_field("intercept_dr_read ", bsl::make_safe(m_guest_vmcb->intercept_dr_read)); + this->dump_field("intercept_dr_write ", bsl::make_safe(m_guest_vmcb->intercept_dr_write)); + this->dump_field("intercept_exception ", bsl::make_safe(m_guest_vmcb->intercept_exception)); + this->dump_field("intercept_instruction1 ", bsl::make_safe(m_guest_vmcb->intercept_instruction1)); + this->dump_field("intercept_instruction2 ", bsl::make_safe(m_guest_vmcb->intercept_instruction2)); + this->dump_field("intercept_instruction3 ", bsl::make_safe(m_guest_vmcb->intercept_instruction3)); + this->dump_field("pause_filter_threshold ", bsl::make_safe(m_guest_vmcb->pause_filter_threshold)); + this->dump_field("pause_filter_count ", bsl::make_safe(m_guest_vmcb->pause_filter_count)); + this->dump_field("iopm_base_pa ", bsl::make_safe(m_guest_vmcb->iopm_base_pa)); + this->dump_field("msrpm_base_pa ", bsl::make_safe(m_guest_vmcb->msrpm_base_pa)); + this->dump_field("tsc_offset ", bsl::make_safe(m_guest_vmcb->tsc_offset)); + this->dump_field("guest_asid ", bsl::make_safe(m_guest_vmcb->guest_asid)); + this->dump_field("tlb_control ", bsl::make_safe(m_guest_vmcb->tlb_control)); + this->dump_field("virtual_interrupt_a ", bsl::make_safe(m_guest_vmcb->virtual_interrupt_a)); + this->dump_field("virtual_interrupt_b ", bsl::make_safe(m_guest_vmcb->virtual_interrupt_b)); + this->dump_field("exitcode ", bsl::make_safe(m_guest_vmcb->exitcode)); + this->dump_field("exitinfo1 ", bsl::make_safe(m_guest_vmcb->exitinfo1)); + this->dump_field("exitinfo2 ", bsl::make_safe(m_guest_vmcb->exitinfo2)); + this->dump_field("exitininfo ", bsl::make_safe(m_guest_vmcb->exitininfo)); + this->dump_field("ctls1 ", bsl::make_safe(m_guest_vmcb->ctls1)); + this->dump_field("avic_apic_bar ", bsl::make_safe(m_guest_vmcb->avic_apic_bar)); + this->dump_field("guest_pa_of_ghcb ", bsl::make_safe(m_guest_vmcb->guest_pa_of_ghcb)); + this->dump_field("eventinj ", bsl::make_safe(m_guest_vmcb->eventinj)); + this->dump_field("n_cr3 ", bsl::make_safe(m_guest_vmcb->n_cr3)); + this->dump_field("ctls2 ", bsl::make_safe(m_guest_vmcb->ctls2)); + this->dump_field("vmcb_clean_bits ", bsl::make_safe(m_guest_vmcb->vmcb_clean_bits)); + this->dump_field("nrip ", bsl::make_safe(m_guest_vmcb->nrip)); + this->dump_field("number_of_bytes_fetched ", bsl::make_safe(m_guest_vmcb->number_of_bytes_fetched)); + + auto const &gib{m_guest_vmcb->guest_instruction_bytes}; + this->dump_field("guest_instruction_bytes[0]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_0))); + this->dump_field("guest_instruction_bytes[1]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_1))); + this->dump_field("guest_instruction_bytes[2]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_2))); + this->dump_field("guest_instruction_bytes[3]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_3))); + this->dump_field("guest_instruction_bytes[4]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_4))); + this->dump_field("guest_instruction_bytes[5]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_5))); + this->dump_field("guest_instruction_bytes[6]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_6))); + this->dump_field("guest_instruction_bytes[7]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_7))); + this->dump_field("guest_instruction_bytes[8]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_8))); + this->dump_field("guest_instruction_bytes[9]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_9))); + this->dump_field("guest_instruction_bytes[a]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_a))); + this->dump_field("guest_instruction_bytes[b]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_b))); + this->dump_field("guest_instruction_bytes[c]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_c))); + this->dump_field("guest_instruction_bytes[d]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_d))); + this->dump_field("guest_instruction_bytes[e]", bsl::make_safe(*gib.at_if(guest_instruction_bytes_e))); + + this->dump_field("avic_apic_backing_page_ptr ", bsl::make_safe(m_guest_vmcb->avic_apic_backing_page_ptr)); + this->dump_field("avic_logical_table_ptr ", bsl::make_safe(m_guest_vmcb->avic_logical_table_ptr)); + this->dump_field("avic_physical_table_ptr ", bsl::make_safe(m_guest_vmcb->avic_physical_table_ptr)); + this->dump_field("vmsa_ptr ", bsl::make_safe(m_guest_vmcb->vmsa_ptr)); + + /// Guest State Save Area Fields + /// + + bsl::print() << bsl::ylw << "+----------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + this->dump_field("es_selector ", bsl::make_safe(m_guest_vmcb->es_selector)); + this->dump_field("es_attrib ", bsl::make_safe(m_guest_vmcb->es_attrib)); + this->dump_field("es_limit ", bsl::make_safe(m_guest_vmcb->es_limit)); + this->dump_field("es_base ", bsl::make_safe(m_guest_vmcb->es_base)); + this->dump_field("cs_selector ", bsl::make_safe(m_guest_vmcb->cs_selector)); + this->dump_field("cs_attrib ", bsl::make_safe(m_guest_vmcb->cs_attrib)); + this->dump_field("cs_limit ", bsl::make_safe(m_guest_vmcb->cs_limit)); + this->dump_field("cs_base ", bsl::make_safe(m_guest_vmcb->cs_base)); + this->dump_field("ss_selector ", bsl::make_safe(m_guest_vmcb->ss_selector)); + this->dump_field("ss_attrib ", bsl::make_safe(m_guest_vmcb->ss_attrib)); + this->dump_field("ss_limit ", bsl::make_safe(m_guest_vmcb->ss_limit)); + this->dump_field("ss_base ", bsl::make_safe(m_guest_vmcb->ss_base)); + this->dump_field("ds_selector ", bsl::make_safe(m_guest_vmcb->ds_selector)); + this->dump_field("ds_attrib ", bsl::make_safe(m_guest_vmcb->ds_attrib)); + this->dump_field("ds_limit ", bsl::make_safe(m_guest_vmcb->ds_limit)); + this->dump_field("ds_base ", bsl::make_safe(m_guest_vmcb->ds_base)); + this->dump_field("fs_selector ", bsl::make_safe(m_guest_vmcb->fs_selector)); + this->dump_field("fs_attrib ", bsl::make_safe(m_guest_vmcb->fs_attrib)); + this->dump_field("fs_limit ", bsl::make_safe(m_guest_vmcb->fs_limit)); + this->dump_field("fs_base ", bsl::make_safe(m_guest_vmcb->fs_base)); + this->dump_field("gs_selector ", bsl::make_safe(m_guest_vmcb->gs_selector)); + this->dump_field("gs_attrib ", bsl::make_safe(m_guest_vmcb->gs_attrib)); + this->dump_field("gs_limit ", bsl::make_safe(m_guest_vmcb->gs_limit)); + this->dump_field("gs_base ", bsl::make_safe(m_guest_vmcb->gs_base)); + this->dump_field("gdtr_selector ", bsl::make_safe(m_guest_vmcb->gdtr_selector)); + this->dump_field("gdtr_attrib ", bsl::make_safe(m_guest_vmcb->gdtr_attrib)); + this->dump_field("gdtr_limit ", bsl::make_safe(m_guest_vmcb->gdtr_limit)); + this->dump_field("gdtr_base ", bsl::make_safe(m_guest_vmcb->gdtr_base)); + this->dump_field("ldtr_selector ", bsl::make_safe(m_guest_vmcb->ldtr_selector)); + this->dump_field("ldtr_attrib ", bsl::make_safe(m_guest_vmcb->ldtr_attrib)); + this->dump_field("ldtr_limit ", bsl::make_safe(m_guest_vmcb->ldtr_limit)); + this->dump_field("ldtr_base ", bsl::make_safe(m_guest_vmcb->ldtr_base)); + this->dump_field("idtr_selector ", bsl::make_safe(m_guest_vmcb->idtr_selector)); + this->dump_field("idtr_attrib ", bsl::make_safe(m_guest_vmcb->idtr_attrib)); + this->dump_field("idtr_limit ", bsl::make_safe(m_guest_vmcb->idtr_limit)); + this->dump_field("idtr_base ", bsl::make_safe(m_guest_vmcb->idtr_base)); + this->dump_field("tr_selector ", bsl::make_safe(m_guest_vmcb->tr_selector)); + this->dump_field("tr_attrib ", bsl::make_safe(m_guest_vmcb->tr_attrib)); + this->dump_field("tr_limit ", bsl::make_safe(m_guest_vmcb->tr_limit)); + this->dump_field("tr_base ", bsl::make_safe(m_guest_vmcb->tr_base)); + this->dump_field("cpl ", bsl::make_safe(m_guest_vmcb->cpl)); + this->dump_field("efer ", bsl::make_safe(m_guest_vmcb->efer)); + this->dump_field("cr4 ", bsl::make_safe(m_guest_vmcb->cr4)); + this->dump_field("cr3 ", bsl::make_safe(m_guest_vmcb->cr3)); + this->dump_field("cr0 ", bsl::make_safe(m_guest_vmcb->cr0)); + this->dump_field("dr7 ", bsl::make_safe(m_guest_vmcb->dr7)); + this->dump_field("dr6 ", bsl::make_safe(m_guest_vmcb->dr6)); + this->dump_field("rflags ", bsl::make_safe(m_guest_vmcb->rflags)); + this->dump_field("rip ", bsl::make_safe(m_guest_vmcb->rip)); + this->dump_field("rsp ", bsl::make_safe(m_guest_vmcb->rsp)); + this->dump_field("rax ", bsl::make_safe(m_guest_vmcb->rax)); + this->dump_field("star ", bsl::make_safe(m_guest_vmcb->star)); + this->dump_field("lstar ", bsl::make_safe(m_guest_vmcb->lstar)); + this->dump_field("cstar ", bsl::make_safe(m_guest_vmcb->cstar)); + this->dump_field("sfmask ", bsl::make_safe(m_guest_vmcb->sfmask)); + this->dump_field("kernel_gs_base ", bsl::make_safe(m_guest_vmcb->kernel_gs_base)); + this->dump_field("sysenter_cs ", bsl::make_safe(m_guest_vmcb->sysenter_cs)); + this->dump_field("sysenter_esp ", bsl::make_safe(m_guest_vmcb->sysenter_esp)); + this->dump_field("sysenter_eip ", bsl::make_safe(m_guest_vmcb->sysenter_eip)); + this->dump_field("cr2 ", bsl::make_safe(m_guest_vmcb->cr2)); + this->dump_field("g_pat ", bsl::make_safe(m_guest_vmcb->g_pat)); + this->dump_field("dbgctl ", bsl::make_safe(m_guest_vmcb->dbgctl)); + this->dump_field("br_from ", bsl::make_safe(m_guest_vmcb->br_from)); + this->dump_field("br_to ", bsl::make_safe(m_guest_vmcb->br_to)); + this->dump_field("lastexcpfrom ", bsl::make_safe(m_guest_vmcb->lastexcpfrom)); + this->dump_field("lastexcpto ", bsl::make_safe(m_guest_vmcb->lastexcpto)); + + /// Footer + /// + + bsl::print() << bsl::ylw << "+----------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + // clang-format on } }; } diff --git a/kernel/src/x64/call_ext.S b/kernel/src/x64/call_ext.S index c5422c3a..a4de9ce6 100644 --- a/kernel/src/x64/call_ext.S +++ b/kernel/src/x64/call_ext.S @@ -40,10 +40,10 @@ call_ext: mov gs:[0x020], r14 mov gs:[0x028], r15 + mov rax, gs:[0x238] + mov fs:[0xFF0], rax mov rax, gs:[0x208] - stac - mov fs:[0xFF8], rax - clac + mov fs:[0xFF8], eax mov gs:[0x1A8], rsp mov rax, gs:[0x1A0] diff --git a/kernel/src/x64/dispatch_esr.hpp b/kernel/src/x64/dispatch_esr.hpp index c26ddc31..64c12a16 100644 --- a/kernel/src/x64/dispatch_esr.hpp +++ b/kernel/src/x64/dispatch_esr.hpp @@ -26,50 +26,56 @@ #define DISPATCH_ESR_HPP #include +#include +#include +#include +#include #include #include +#include +#include #include #include namespace mk { /// @brief defines a constant for the exception vector #0 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_0{bsl::to_umax(0)}; + constexpr auto EXCEPTION_VECTOR_0{0_umax}; /// @brief defines a constant for the exception vector #1 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_1{bsl::to_umax(1)}; + constexpr auto EXCEPTION_VECTOR_1{1_umax}; /// @brief defines a constant for the exception vector #2 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_2{bsl::to_umax(2)}; + constexpr auto EXCEPTION_VECTOR_2{2_umax}; /// @brief defines a constant for the exception vector #3 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_3{bsl::to_umax(3)}; + constexpr auto EXCEPTION_VECTOR_3{3_umax}; /// @brief defines a constant for the exception vector #4 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_4{bsl::to_umax(4)}; + constexpr auto EXCEPTION_VECTOR_4{4_umax}; /// @brief defines a constant for the exception vector #5 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_5{bsl::to_umax(5)}; + constexpr auto EXCEPTION_VECTOR_5{5_umax}; /// @brief defines a constant for the exception vector #6 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_6{bsl::to_umax(6)}; + constexpr auto EXCEPTION_VECTOR_6{6_umax}; /// @brief defines a constant for the exception vector #7 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_7{bsl::to_umax(7)}; + constexpr auto EXCEPTION_VECTOR_7{7_umax}; /// @brief defines a constant for the exception vector #8 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_8{bsl::to_umax(8)}; + constexpr auto EXCEPTION_VECTOR_8{8_umax}; /// @brief defines a constant for the exception vector #10 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_10{bsl::to_umax(10)}; + constexpr auto EXCEPTION_VECTOR_10{10_umax}; /// @brief defines a constant for the exception vector #11 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_11{bsl::to_umax(11)}; + constexpr auto EXCEPTION_VECTOR_11{11_umax}; /// @brief defines a constant for the exception vector #12 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_12{bsl::to_umax(12)}; + constexpr auto EXCEPTION_VECTOR_12{12_umax}; /// @brief defines a constant for the exception vector #13 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_13{bsl::to_umax(13)}; + constexpr auto EXCEPTION_VECTOR_13{13_umax}; /// @brief defines a constant for the exception vector #14 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_14{bsl::to_umax(14)}; + constexpr auto EXCEPTION_VECTOR_14{14_umax}; /// @brief defines a constant for the exception vector #16 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_16{bsl::to_umax(16)}; + constexpr auto EXCEPTION_VECTOR_16{16_umax}; /// @brief defines a constant for the exception vector #17 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_17{bsl::to_umax(17)}; + constexpr auto EXCEPTION_VECTOR_17{17_umax}; /// @brief defines a constant for the exception vector #18 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_18{bsl::to_umax(18)}; + constexpr auto EXCEPTION_VECTOR_18{18_umax}; /// @brief defines a constant for the exception vector #19 - constexpr bsl::safe_uintmax EXCEPTION_VECTOR_19{bsl::to_umax(19)}; + constexpr auto EXCEPTION_VECTOR_19{19_umax}; /// /// @brief Returns the name of an ESR given it's vector @@ -79,7 +85,7 @@ namespace mk /// @return Returns the name of an ESR given it's vector /// [[nodiscard]] constexpr auto - dispatch_esr_vector_to_name(bsl::safe_uintmax const &vector) noexcept -> bsl::string_view + vector_to_name(bsl::safe_uintmax const &vector) noexcept -> bsl::string_view { switch (vector.get()) { case EXCEPTION_VECTOR_0.get(): { @@ -151,33 +157,11 @@ namespace mk } default: { - return "unknown"; + break; } } - } - /// - /// @brief Print a line - /// - constexpr void - dispatch_esr_print_line() noexcept - { - bsl::print() << bsl::yellow; - bsl::print() << "+--------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; - } - - /// - /// @brief Print a header - /// - constexpr void - dispatch_esr_print_header() noexcept - { - bsl::print() << bsl::yellow << "| " << bsl::cyan; - bsl::print() << "Register "; - bsl::print() << bsl::yellow << "| " << bsl::cyan; - bsl::print() << "Value "; - bsl::print() << bsl::yellow << "|" << bsl::reset_color << bsl::endl; + return "unknown"; } /// @@ -188,28 +172,37 @@ namespace mk /// @param val the value of the register /// constexpr void - dispatch_esr_print_reg(bsl::string_view const name, bsl::safe_uintmax const &val) noexcept + dispatch_esr_dump(bsl::string_view const &name, bsl::safe_uintmax const &val) noexcept { - constexpr bsl::safe_uintmax name_col_size{bsl::to_umax(9)}; - - bsl::print() << bsl::yellow << "| " << bsl::reset_color; - bsl::print() << name; - - for (bsl::safe_uintmax i{}; i < name_col_size - name.size(); ++i) { - bsl::print() << ' '; - } - - bsl::print() << bsl::yellow << "| " << bsl::reset_color; - + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<16s", name}; + bsl::print() << bsl::ylw << "| "; if (val.is_zero()) { - bsl::print() << bsl::black << bsl::hex(val) << bsl::reset_color; + bsl::print() << bsl::blk << " " << bsl::hex(val) << " "; } else { - bsl::print() << bsl::hex(val); + bsl::print() << bsl::rst << " " << bsl::hex(val) << " "; } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + } - bsl::print() << bsl::yellow << " |" << bsl::reset_color; - bsl::print() << bsl::endl; + /// + /// @brief Print the contents of a register + /// + /// + /// @param name the name of the register + /// @param val the value of the register + /// + constexpr void + dispatch_esr_dump(bsl::string_view const &name, bsl::safe_uint16 const &val) noexcept + { + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<16s", name}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << " " << bsl::hex(val) << " "; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; } /// @@ -218,22 +211,21 @@ namespace mk /// /// @param name the name of the register /// @param val the value of the register - /// @param seg_val the value of the register's segment + /// @param seg the value of the register's segment /// constexpr void - dispatch_esr_print_reg_with_segment( + dispatch_esr_dump_with_segment( bsl::string_view const name, bsl::safe_uintmax const &val, - bsl::safe_uintmax const &seg_val) noexcept + bsl::safe_uintmax const &seg) noexcept { - bsl::print() << bsl::yellow << "| " << bsl::reset_color; - bsl::print() << name << " "; - bsl::print() << bsl::yellow << "| " << bsl::reset_color; - bsl::print() << bsl::hex(bsl::to_u16(seg_val)); - bsl::print() << ":"; - bsl::print() << bsl::hex(val); - bsl::print() << bsl::yellow << " |" << bsl::reset_color; - bsl::print() << bsl::endl; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<16s", name}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::hex(bsl::to_u16(seg)) << ':'; + bsl::print() << bsl::rst << bsl::hex(val) << ' '; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; } /// @@ -241,70 +233,147 @@ namespace mk /// function will dispatch exceptions as needed. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param ext the extension that made the syscall /// @param intrinsic the intrinsics to use /// @return Returns bsl::exit_success if the exception was handled, /// bsl::exit_failure otherwise /// - template [[nodiscard]] constexpr auto - dispatch_esr(TLS_CONCEPT &tls, INTRINSIC_CONCEPT &intrinsic) noexcept -> bsl::exit_code + dispatch_esr( + tls_t &tls, page_pool_t &page_pool, intrinsic_t &intrinsic, ext_t *const ext) noexcept + -> bsl::exit_code { - if (tls.esr_vector == EXCEPTION_VECTOR_2) { - return dispatch_esr_nmi(tls, intrinsic); + bsl::finally reset_on_exit{[&tls]() noexcept -> void { + /// NOTE: + /// - This tells our spinlock_ts that we are no longer in an ESR, + /// which is needed to ensure deadlock detection is handled + /// properly. + /// + + tls.esr_ip = {}; + }}; + + switch (tls.esr_vector) { + case EXCEPTION_VECTOR_2.get(): { + if (bsl::likely(dispatch_esr_nmi(tls, intrinsic))) { + return bsl::exit_success; + } + + break; + } + + case EXCEPTION_VECTOR_14.get(): { + if (bsl::likely(dispatch_esr_page_fault(tls, page_pool, ext))) { + return bsl::exit_success; + } + + break; + } + + default: { + break; + } } - bsl::print() << bsl::bold_red // -- - << "...\n\n" // -- - << bsl::bold_magenta // -- - << dispatch_esr_vector_to_name(tls.esr_vector) << ' ' // -- - << bsl::reset_color // -- - << "[" << bsl::red // -- - << bsl::hex(bsl::to_u8_unsafe(tls.esr_error_code)) << bsl::reset_color // -- - << "]: " // -- - << bsl::endl; // -- + bsl::print() << bsl::red << "...\n\n"; + bsl::print() << bsl::mag << vector_to_name(tls.esr_vector) << " ["; + bsl::print() << bsl::cyn << "ec: "; + bsl::print() << bsl::rst << bsl::hex(bsl::to_u8_unsafe(tls.esr_error_code)); + bsl::print() << bsl::mag << "] dump: "; + bsl::print() << bsl::rst << bsl::endl; - dispatch_esr_print_line(); - dispatch_esr_print_header(); - dispatch_esr_print_line(); + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { + return bsl::exit_failure; + } - dispatch_esr_print_reg_with_segment("rip", tls.esr_rip, tls.esr_cs); - dispatch_esr_print_reg_with_segment("rsp", tls.esr_rsp, tls.esr_ss); - dispatch_esr_print_line(); + /// Header + /// - dispatch_esr_print_reg("rflags", tls.esr_rflags); - dispatch_esr_print_line(); + bsl::print() << bsl::ylw << "+---------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - dispatch_esr_print_reg("rax", tls.esr_rax); - dispatch_esr_print_reg("rbx", tls.esr_rbx); - dispatch_esr_print_reg("rcx", tls.esr_rcx); - dispatch_esr_print_reg("rdx", tls.esr_rdx); - dispatch_esr_print_reg("rbp", tls.esr_rbp); - dispatch_esr_print_reg("rsi", tls.esr_rsi); - dispatch_esr_print_reg("rdi", tls.esr_rdi); - dispatch_esr_print_reg("r8", tls.esr_r8); - dispatch_esr_print_reg("r9", tls.esr_r9); - dispatch_esr_print_reg("r10", tls.esr_r10); - dispatch_esr_print_reg("r11", tls.esr_r11); - dispatch_esr_print_reg("r12", tls.esr_r12); - dispatch_esr_print_reg("r13", tls.esr_r13); - dispatch_esr_print_reg("r14", tls.esr_r14); - dispatch_esr_print_reg("r15", tls.esr_r15); - dispatch_esr_print_line(); + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^16s", "description "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^26s", "value "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; - dispatch_esr_print_reg("cr0", tls.esr_cr0); - dispatch_esr_print_reg("cr2", tls.esr_cr2); - dispatch_esr_print_reg("cr3", tls.esr_cr3); - dispatch_esr_print_reg("cr4", tls.esr_cr4); - dispatch_esr_print_line(); + bsl::print() << bsl::ylw << "+---------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - bsl::print() << bsl::endl // -- - << bsl::bold_magenta // -- - << "backtrace:" // -- - << bsl::reset_color // -- - << bsl::endl; // -- + /// IP/SP + /// + + dispatch_esr_dump_with_segment("rip", tls.esr_ip, tls.esr_cs); + dispatch_esr_dump_with_segment("rsp", tls.esr_sp, tls.esr_ss); + + /// Flags + /// + + bsl::print() << bsl::ylw << "+---------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + dispatch_esr_dump("rflags", tls.esr_rflags); + + /// General Purpose Registers + /// + + bsl::print() << bsl::ylw << "+---------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + dispatch_esr_dump("rax", tls.esr_rax); + dispatch_esr_dump("rbx", tls.esr_rbx); + dispatch_esr_dump("rcx", tls.esr_rcx); + dispatch_esr_dump("rdx", tls.esr_rdx); + dispatch_esr_dump("rbp", tls.esr_rbp); + dispatch_esr_dump("rsi", tls.esr_rsi); + dispatch_esr_dump("rdi", tls.esr_rdi); + dispatch_esr_dump("r8", tls.esr_r8); + dispatch_esr_dump("r9", tls.esr_r9); + dispatch_esr_dump("r10", tls.esr_r10); + dispatch_esr_dump("r11", tls.esr_r11); + dispatch_esr_dump("r12", tls.esr_r12); + dispatch_esr_dump("r13", tls.esr_r13); + dispatch_esr_dump("r14", tls.esr_r14); + dispatch_esr_dump("r15", tls.esr_r15); + + /// Control Registers + /// + + bsl::print() << bsl::ylw << "+---------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + dispatch_esr_dump("cr0", tls.esr_cr0); + dispatch_esr_dump("cr2", tls.esr_pf_addr); + dispatch_esr_dump("cr3", tls.esr_cr3); + dispatch_esr_dump("cr4", tls.esr_cr4); + + /// TLS State + /// + + bsl::print() << bsl::ylw << "+---------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + dispatch_esr_dump("ppid", tls.ppid); + dispatch_esr_dump("online_pps", tls.online_pps); + dispatch_esr_dump("active_extid", tls.active_extid); + dispatch_esr_dump("active_vmid", tls.active_vmid); + dispatch_esr_dump("active_vpid", tls.active_vpid); + dispatch_esr_dump("active_vpsid", tls.active_vpsid); + dispatch_esr_dump("sp", tls.sp); + dispatch_esr_dump("tp", tls.tp); + + /// Footer + /// + + bsl::print() << bsl::ylw << "+---------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::mag << "\nbacktrace:"; + bsl::print() << bsl::rst << bsl::endl; return bsl::exit_failure; } diff --git a/kernel/src/x64/dispatch_esr_entry.S b/kernel/src/x64/dispatch_esr_entry.S index e7fd3bc5..147686dc 100644 --- a/kernel/src/x64/dispatch_esr_entry.S +++ b/kernel/src/x64/dispatch_esr_entry.S @@ -24,13 +24,16 @@ * SOFTWARE. */ - .code64 + .code64 .intel_syntax noprefix .globl dispatch_esr_entry .type dispatch_esr_entry, @function dispatch_esr_entry: + push 0x40002 + popf + mov rdi, gs:[0x200] call dispatch_esr_trampoline diff --git a/kernel/src/x64/dispatch_syscall_entry.S b/kernel/src/x64/dispatch_syscall_entry.S index 91a88ee1..ed65b70b 100644 --- a/kernel/src/x64/dispatch_syscall_entry.S +++ b/kernel/src/x64/dispatch_syscall_entry.S @@ -58,9 +58,20 @@ dispatch_syscall_entry: mov rax, gs:[0x1B8] mov gs:[0x188], rax + push 0x40002 + popf + + xor rax, rax + mov gs:[0x280], rax + mov rax, 0xDEAD000000010001 + mov gs:[0x288], rax + mov rdi, gs:[0x200] call dispatch_syscall_trampoline + cmp rax, 0x0 + jne dispatch_syscall_fast_fail_entry + mov rdx, gs:[0x1A0] mov gs:[0x180], rdx mov rdx, gs:[0x1A8] @@ -74,6 +85,7 @@ dispatch_syscall_entry: mov rdx, gs:[0x048] mov rsi, gs:[0x058] mov rdi, gs:[0x060] + mov rax, gs:[0x288] mov r15, gs:[0x0A0] mov r14, gs:[0x098] @@ -103,6 +115,9 @@ dispatch_syscall_fast_fail_entry: mov rax, gs:[0x1A8] mov gs:[0x188], rax + mov rdi, gs:[0x200] + call dispatch_syscall_trampoline_failure + mov rsp, gs:[0x0A8] mov r9, gs:[0x070] @@ -111,6 +126,7 @@ dispatch_syscall_fast_fail_entry: mov rdx, gs:[0x048] mov rsi, gs:[0x058] mov rdi, gs:[0x060] + mov rax, gs:[0x288] mov r15, gs:[0x0A0] mov r14, gs:[0x098] @@ -122,7 +138,6 @@ dispatch_syscall_fast_fail_entry: mov r11, gs:[0x080] mov rcx, gs:[0x040] - mov rax, 0xDEAD000000010001 sysretq int 3 diff --git a/kernel/src/x64/dispatch_syscall_intrinsic_op.hpp b/kernel/src/x64/dispatch_syscall_intrinsic_op.hpp deleted file mode 100644 index 5075240d..00000000 --- a/kernel/src/x64/dispatch_syscall_intrinsic_op.hpp +++ /dev/null @@ -1,154 +0,0 @@ -/// @copyright -/// Copyright (C) 2020 Assured Information Security, Inc. -/// -/// @copyright -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// @copyright -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// @copyright -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -/// SOFTWARE. - -#ifndef DISPATCH_SYSCALL_INTRINSIC_OP_HPP -#define DISPATCH_SYSCALL_INTRINSIC_OP_HPP - -#include - -#include -#include -#include -#include - -namespace mk -{ - namespace details - { - /// - /// @brief Implements the bf_intrinsic_op_read_msr syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @param tls the current TLS block - /// @param intrinsic the intrinsics to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_intrinsic_op_read_msr(TLS_CONCEPT &tls, INTRINSIC_CONCEPT &intrinsic) - -> syscall::bf_status_t - { - auto const ret{intrinsic.rdmsr(bsl::to_u32_unsafe(tls.ext_reg1))}; - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - tls.ext_reg0 = ret.get(); - return syscall::BF_STATUS_SUCCESS; - } - - /// - /// @brief Implements the bf_intrinsic_op_destroy_vm syscall - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @param tls the current TLS block - /// @param intrinsic the intrinsics to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - syscall_intrinsic_op_write_msr(TLS_CONCEPT &tls, INTRINSIC_CONCEPT &intrinsic) - -> syscall::bf_status_t - { - auto const ret{intrinsic.wrmsr(bsl::to_u32_unsafe(tls.ext_reg1), tls.ext_reg2)}; - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - - return syscall::BF_STATUS_SUCCESS; - } - } - - /// - /// @brief Dispatches the bf_intrinsic_op syscalls - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam EXT_CONCEPT defines the type of ext_t to use - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @param tls the current TLS block - /// @param ext the extension that made the syscall - /// @param intrinsic the intrinsics to use - /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error - /// code on failure. - /// - template - [[nodiscard]] constexpr auto - dispatch_syscall_intrinsic_op( - TLS_CONCEPT &tls, EXT_CONCEPT const &ext, INTRINSIC_CONCEPT &intrinsic) - -> syscall::bf_status_t - { - syscall::bf_status_t ret{}; - - if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { - bsl::error() << "invalid handle: " // -- - << bsl::hex(tls.ext_reg0) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return syscall::BF_STATUS_FAILURE_INVALID_HANDLE; - } - - switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { - case syscall::BF_INTRINSIC_OP_READ_MSR_IDX_VAL.get(): { - ret = details::syscall_intrinsic_op_read_msr(tls, intrinsic); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { - bsl::print() << bsl::here(); - return ret; - } - - return ret; - } - - case syscall::BF_INTRINSIC_OP_WRITE_MSR_IDX_VAL.get(): { - ret = details::syscall_intrinsic_op_write_msr(tls, intrinsic); - if (bsl::unlikely(ret != syscall::BF_STATUS_SUCCESS)) { - bsl::print() << bsl::here(); - return ret; - } - - return ret; - } - - default: { - bsl::error() << "unknown syscall index: " //-- - << bsl::hex(tls.ext_syscall) //-- - << bsl::endl //-- - << bsl::here(); //-- - - return syscall::BF_STATUS_FAILURE_UNKNOWN; - } - } - } -} - -#endif diff --git a/kernel/src/x64/get_current_tls.S b/kernel/src/x64/get_current_tls.S index c6b02d23..1240a00b 100644 --- a/kernel/src/x64/get_current_tls.S +++ b/kernel/src/x64/get_current_tls.S @@ -24,6 +24,9 @@ * SOFTWARE. */ + /** @brief defines the offset of tls_t.self */ + #define TLS_OFFSET_SELF 0x200 + .code64 .intel_syntax noprefix @@ -31,7 +34,7 @@ .type get_current_tls, @function get_current_tls: - mov rax, gs:[0x200] + mov rax, gs:[TLS_OFFSET_SELF] ret int 3 diff --git a/kernel/src/x64/intel/dispatch_esr_nmi.hpp b/kernel/src/x64/intel/dispatch_esr_nmi.hpp index 9e405908..335039d8 100644 --- a/kernel/src/x64/intel/dispatch_esr_nmi.hpp +++ b/kernel/src/x64/intel/dispatch_esr_nmi.hpp @@ -25,9 +25,11 @@ #ifndef DISPATCH_ESR_NMI_HPP #define DISPATCH_ESR_NMI_HPP +#include +#include + #include #include -#include #include #include #include @@ -38,32 +40,32 @@ namespace mk /// @brief Provides the main entry point for NMI exceptions. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use /// @param tls the current TLS block /// @param intrinsic the intrinsics to use - /// @return Returns bsl::exit_success if the exception was handled, - /// bsl::exit_failure otherwise + /// @return Returns bsl::errc_success if the exception was handled, + /// bsl::errc_failure otherwise /// - template [[nodiscard]] constexpr auto - dispatch_esr_nmi(TLS_CONCEPT &tls, INTRINSIC_CONCEPT &intrinsic) noexcept -> bsl::exit_code + dispatch_esr_nmi(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { bsl::errc_type ret{}; bsl::safe_uint32 val{}; - constexpr bsl::safe_uintmax vmcs_procbased_ctls_idx{bsl::to_umax(0x4002U)}; - constexpr bsl::safe_uint32 vmcs_set_nmi_window_exiting{bsl::to_u32(0x400000U)}; + constexpr auto vmcs_procbased_ctls_idx{0x4002_umax}; + constexpr auto vmcs_set_nmi_window_exiting{0x400000_u32}; - if (bsl::ZERO_UMAX != tls.nmi_lock) { - tls.nmi_pending = bsl::ONE_UMAX.get(); - return bsl::exit_success; + constexpr auto unlocked{0_umax}; + constexpr auto pending{1_umax}; + + if (unlocked != tls.nmi_lock) { + tls.nmi_pending = pending.get(); + return bsl::errc_success; } ret = intrinsic.vmread32(vmcs_procbased_ctls_idx, val.data()); if (bsl::unlikely(!ret)) { bsl::error() << bsl::here(); - return bsl::exit_failure; + return ret; } val |= vmcs_set_nmi_window_exiting; @@ -71,11 +73,12 @@ namespace mk ret = intrinsic.vmwrite32(vmcs_procbased_ctls_idx, val); if (bsl::unlikely(!ret)) { bsl::error() << bsl::here(); - return bsl::exit_failure; + return ret; } - tls.nmi_pending = bsl::ZERO_UMAX.get(); - return bsl::exit_success; + constexpr auto not_pending{0_umax}; + tls.nmi_pending = not_pending.get(); + return bsl::errc_success; } } diff --git a/kernel/src/x64/intel/dispatch_syscall_intrinsic_op.hpp b/kernel/src/x64/intel/dispatch_syscall_intrinsic_op.hpp new file mode 100644 index 00000000..52884d50 --- /dev/null +++ b/kernel/src/x64/intel/dispatch_syscall_intrinsic_op.hpp @@ -0,0 +1,230 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DISPATCH_SYSCALL_INTRINSIC_OP_HPP +#define DISPATCH_SYSCALL_INTRINSIC_OP_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Implements the bf_intrinsic_op_rdmsr syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + syscall_intrinsic_op_rdmsr(tls_t &tls, intrinsic_t &intrinsic) -> bsl::errc_type + { + /// TODO: + /// - Move this logic to the dispatch_syscall_entry.S and implement + /// this right in ASM. This way, we can do the smallest amount of + /// state save logic and execute this instruction as fast as + /// possible. Just make sure that the safe version is used, and + /// it will still need to make sure that the extension is not + /// trying to read/write MSRs that the microkernel is using. + /// + + auto const ret{intrinsic.rdmsr(bsl::to_u32_unsafe(tls.ext_reg1))}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.ext_reg0 = ret.get(); + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_intrinsic_op_wrmsr syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + syscall_intrinsic_op_wrmsr(tls_t &tls, intrinsic_t &intrinsic) -> bsl::errc_type + { + /// TODO: + /// - Move this logic to the dispatch_syscall_entry.S and implement + /// this right in ASM. This way, we can do the smallest amount of + /// state save logic and execute this instruction as fast as + /// possible. Just make sure that the safe version is used, and + /// it will still need to make sure that the extension is not + /// trying to read/write MSRs that the microkernel is using. + /// + + auto const ret{intrinsic.wrmsr(bsl::to_u32_unsafe(tls.ext_reg1), tls.ext_reg2)}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_intrinsic_op_invept syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + syscall_intrinsic_op_invept(tls_t &tls, intrinsic_t &intrinsic) -> bsl::errc_type + { + auto const ret{intrinsic.invept(tls.ext_reg1, tls.ext_reg2)}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Implements the bf_intrinsic_op_invvpid syscall + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + syscall_intrinsic_op_invvpid(tls_t &tls, intrinsic_t &intrinsic) -> bsl::errc_type + { + auto const ret{ + intrinsic.invvpid(tls.ext_reg1, bsl::to_u16_unsafe(tls.ext_reg2), tls.ext_reg3)}; + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + tls.syscall_ret_status = syscall::BF_STATUS_SUCCESS.get(); + return bsl::errc_success; + } + + /// + /// @brief Dispatches the bf_intrinsic_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param ext the extension that made the syscall + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + dispatch_syscall_intrinsic_op(tls_t &tls, intrinsic_t &intrinsic, ext_t &ext) -> bsl::errc_type + { + bsl::errc_type ret{}; + + if (bsl::unlikely(!ext.is_handle_valid(tls.ext_reg0))) { + bsl::error() << "invalid handle " // -- + << bsl::hex(tls.ext_reg0) // -- + << bsl::endl // -- + << bsl::here(); // -- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_INVALID_HANDLE.get(); + return bsl::errc_failure; + } + + switch (syscall::bf_syscall_index(tls.ext_syscall).get()) { + case syscall::BF_INTRINSIC_OP_RDMSR_IDX_VAL.get(): { + ret = syscall_intrinsic_op_rdmsr(tls, intrinsic); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_INTRINSIC_OP_WRMSR_IDX_VAL.get(): { + ret = syscall_intrinsic_op_wrmsr(tls, intrinsic); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_INTRINSIC_OP_INVEPT_IDX_VAL.get(): { + ret = syscall_intrinsic_op_invept(tls, intrinsic); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + case syscall::BF_INTRINSIC_OP_INVVPID_IDX_VAL.get(): { + ret = syscall_intrinsic_op_invvpid(tls, intrinsic); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + return ret; + } + + default: { + break; + } + } + + bsl::error() << "unknown syscall index " //-- + << bsl::hex(tls.ext_syscall) //-- + << bsl::endl //-- + << bsl::here(); //-- + + tls.syscall_ret_status = syscall::BF_STATUS_FAILURE_UNSUPPORTED.get(); + return bsl::errc_failure; + } +} + +#endif diff --git a/kernel/src/x64/intel/intrinsic_t.S b/kernel/src/x64/intel/intrinsic_t.S index 3462b1f6..35533ed7 100644 --- a/kernel/src/x64/intel/intrinsic_t.S +++ b/kernel/src/x64/intel/intrinsic_t.S @@ -228,9 +228,7 @@ intrinsic_set_tp: .type intrinsic_tls_reg, @function intrinsic_tls_reg: - stac mov rax, fs:[rdi] - clac ret int 3 @@ -243,9 +241,7 @@ intrinsic_tls_reg: .type intrinsic_set_tls_reg, @function intrinsic_set_tls_reg: - stac mov fs:[rdi], rsi - clac ret int 3 @@ -369,6 +365,32 @@ intrinsic_wrmsr_unsafe: + .globl intrinsic_invept + .type intrinsic_invept, @function +intrinsic_invept: + + invept rsi, [rdi] + + ret + int 3 + + .size intrinsic_invept, .-intrinsic_invept + + + + .globl intrinsic_invvpid + .type intrinsic_invvpid, @function +intrinsic_invvpid: + + invept rsi, [rdi] + + ret + int 3 + + .size intrinsic_invvpid, .-intrinsic_invvpid + + + .globl intrinsic_vmload .type intrinsic_vmload, @function intrinsic_vmload: @@ -381,7 +403,10 @@ intrinsic_vmload: int 3 intrinsic_vmload_failure: - mov rax, 0x1 + + mov rax, 0x4400 + vmread rax, rax + ret int 3 @@ -390,6 +415,29 @@ intrinsic_vmload_failure: + .globl intrinsic_vmclear + .type intrinsic_vmclear, @function +intrinsic_vmclear: + + vmclear [rdi] + jbe intrinsic_vmclear_failure + + xor rax, rax + ret + int 3 + +intrinsic_vmclear_failure: + + mov rax, 0x4400 + vmread rax, rax + + ret + int 3 + + .size intrinsic_vmclear, .-intrinsic_vmclear + + + .globl intrinsic_vmread16 .type intrinsic_vmread16, @function intrinsic_vmread16: @@ -403,7 +451,10 @@ intrinsic_vmread16: int 3 intrinsic_vmread16_failure: - mov rax, 0x1 + + mov rax, 0x4400 + vmread rax, rax + ret int 3 @@ -424,7 +475,10 @@ intrinsic_vmread32: int 3 intrinsic_vmread32_failure: - mov rax, 0x1 + + mov rax, 0x4400 + vmread rax, rax + ret int 3 @@ -445,7 +499,10 @@ intrinsic_vmread64: int 3 intrinsic_vmread64_failure: - mov rax, 0x1 + + mov rax, 0x4400 + vmread rax, rax + ret int 3 @@ -465,7 +522,10 @@ intrinsic_vmwrite16: int 3 intrinsic_vmwrite16_failure: - mov rax, 0x1 + + mov rax, 0x4400 + vmread rax, rax + ret int 3 @@ -485,7 +545,10 @@ intrinsic_vmwrite32: int 3 intrinsic_vmwrite32_failure: - mov rax, 0x1 + + mov rax, 0x4400 + vmread rax, rax + ret int 3 @@ -505,7 +568,10 @@ intrinsic_vmwrite64: int 3 intrinsic_vmwrite64_failure: - mov rax, 0x1 + + mov rax, 0x4400 + vmread rax, rax + ret int 3 @@ -530,10 +596,10 @@ intrinsic_vmrun: /* CR2/DR6 */ /**************************************************************************/ - mov rax, [r15 + 0x078] + mov rax, [r15 + 0x000] mov cr2, rax - mov rax, [r15 + 0x080] + mov rax, [r15 + 0x008] mov dr6, rax /**************************************************************************/ @@ -541,23 +607,23 @@ intrinsic_vmrun: /**************************************************************************/ mov edi, 0xC0000081 - mov rsi, [r15 + 0x088] + mov rsi, [r15 + 0x010] call intrinsic_wrmsr_unsafe mov edi, 0xC0000082 - mov rsi, [r15 + 0x090] + mov rsi, [r15 + 0x018] call intrinsic_wrmsr_unsafe mov edi, 0xC0000083 - mov rsi, [r15 + 0x098] + mov rsi, [r15 + 0x020] call intrinsic_wrmsr_unsafe mov edi, 0xC0000084 - mov rsi, [r15 + 0x0A0] + mov rsi, [r15 + 0x028] call intrinsic_wrmsr_unsafe mov edi, 0xC0000102 - mov rsi, [r15 + 0x0A8] + mov rsi, [r15 + 0x030] call intrinsic_wrmsr_unsafe /**************************************************************************/ @@ -584,11 +650,9 @@ nmis_complete: mov rax, 0x6C14 vmwrite rax, rsp - mov rax, [r15 + 0x0D8] + mov rax, [r15 + 0x060] cmp rax, 0x1 - stac - mov rax, fs:[0x800] mov rbx, fs:[0x808] mov rcx, fs:[0x810] @@ -605,8 +669,6 @@ nmis_complete: mov r14, fs:[0x868] mov r15, fs:[0x870] - clac - /**************************************************************************/ /* Run */ /**************************************************************************/ @@ -637,32 +699,32 @@ intrinsic_vmrun_failure: mov edi, 0xC0000102 call intrinsic_rdmsr_unsafe - mov [r15 + 0x0A8], rax - mov rsi, [r15 + 0x0D0] + mov [r15 + 0x030], rax + mov rsi, [r15 + 0x058] call intrinsic_wrmsr_unsafe mov edi, 0xC0000084 call intrinsic_rdmsr_unsafe - mov [r15 + 0x0A0], rax - mov rsi, [r15 + 0x0C8] + mov [r15 + 0x028], rax + mov rsi, [r15 + 0x050] call intrinsic_wrmsr_unsafe mov edi, 0xC0000083 call intrinsic_rdmsr_unsafe - mov [r15 + 0x098], rax - mov rsi, [r15 + 0x0C0] + mov [r15 + 0x020], rax + mov rsi, [r15 + 0x048] call intrinsic_wrmsr_unsafe mov edi, 0xC0000082 call intrinsic_rdmsr_unsafe - mov [r15 + 0x090], rax - mov rsi, [r15 + 0x0B8] + mov [r15 + 0x018], rax + mov rsi, [r15 + 0x040] call intrinsic_wrmsr_unsafe mov edi, 0xC0000081 call intrinsic_rdmsr_unsafe - mov [r15 + 0x088], rax - mov rsi, [r15 + 0x0B0] + mov [r15 + 0x010], rax + mov rsi, [r15 + 0x038] call intrinsic_wrmsr_unsafe /**************************************************************************/ @@ -670,10 +732,10 @@ intrinsic_vmrun_failure: /**************************************************************************/ mov rax, dr6 - mov [r15 + 0x080], rax + mov [r15 + 0x008], rax mov rax, cr2 - mov [r15 + 0x078], rax + mov [r15 + 0x000], rax /**************************************************************************/ /* Done */ @@ -686,7 +748,11 @@ intrinsic_vmrun_failure: pop rbp pop rbx - mov rax, 0xFFFFFFFFFFFFFFFF + mov rax, 0x4400 + vmread rax, rax + mov rdx, 0xFFFFFFFF00000000 + or rax, rdx + ret int 3 @@ -698,12 +764,13 @@ intrinsic_vmrun_failure: .type intrinsic_vmexit, @function intrinsic_vmexit: + push 0x40002 + popf + /**************************************************************************/ /* General Purpose Register State */ /**************************************************************************/ - stac - mov fs:[0x870], r15 mov fs:[0x868], r14 mov fs:[0x860], r13 @@ -720,8 +787,6 @@ intrinsic_vmexit: mov fs:[0x808], rbx mov fs:[0x800], rax - clac - pop r15 /**************************************************************************/ @@ -729,7 +794,7 @@ intrinsic_vmexit: /**************************************************************************/ mov rax, 0x1 - mov [r15 + 0x0D8], rax + mov [r15 + 0x060], rax /**************************************************************************/ /* NMIs */ @@ -744,32 +809,32 @@ intrinsic_vmexit: mov edi, 0xC0000102 call intrinsic_rdmsr_unsafe - mov [r15 + 0x0A8], rax - mov rsi, [r15 + 0x0D0] + mov [r15 + 0x030], rax + mov rsi, [r15 + 0x058] call intrinsic_wrmsr_unsafe mov edi, 0xC0000084 call intrinsic_rdmsr_unsafe - mov [r15 + 0x0A0], rax - mov rsi, [r15 + 0x0C8] + mov [r15 + 0x028], rax + mov rsi, [r15 + 0x050] call intrinsic_wrmsr_unsafe mov edi, 0xC0000083 call intrinsic_rdmsr_unsafe - mov [r15 + 0x098], rax - mov rsi, [r15 + 0x0C0] + mov [r15 + 0x020], rax + mov rsi, [r15 + 0x048] call intrinsic_wrmsr_unsafe mov edi, 0xC0000082 call intrinsic_rdmsr_unsafe - mov [r15 + 0x090], rax - mov rsi, [r15 + 0x0B8] + mov [r15 + 0x018], rax + mov rsi, [r15 + 0x040] call intrinsic_wrmsr_unsafe mov edi, 0xC0000081 call intrinsic_rdmsr_unsafe - mov [r15 + 0x088], rax - mov rsi, [r15 + 0x0B0] + mov [r15 + 0x010], rax + mov rsi, [r15 + 0x038] call intrinsic_wrmsr_unsafe /**************************************************************************/ @@ -777,10 +842,10 @@ intrinsic_vmexit: /**************************************************************************/ mov rax, dr6 - mov [r15 + 0x080], rax + mov [r15 + 0x008], rax mov rax, cr2 - mov [r15 + 0x078], rax + mov [r15 + 0x000], rax /**************************************************************************/ /* Done */ diff --git a/kernel/src/x64/intel/intrinsic_t.hpp b/kernel/src/x64/intel/intrinsic_t.hpp index 3181397c..5f78eb38 100644 --- a/kernel/src/x64/intel/intrinsic_t.hpp +++ b/kernel/src/x64/intel/intrinsic_t.hpp @@ -25,8 +25,13 @@ #ifndef INTRINSIC_HPP #define INTRINSIC_HPP +#include +#include + +#include #include #include +#include #include #include #include @@ -35,252 +40,276 @@ namespace mk { - namespace details - { - /// - /// @brief Implements intrinsic_t::invlpg - /// - /// - /// @param val n/a - /// - extern "C" void intrinsic_invlpg(bsl::uint64 const val) noexcept; + /// + /// @brief Implements intrinsic_t::invlpg + /// + /// + /// @param val n/a + /// + extern "C" void intrinsic_invlpg(bsl::uint64 const val) noexcept; - /// - /// @brief Implements intrinsic_t::es_selector - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_es_selector() noexcept -> bsl::uint16; + /// + /// @brief Implements intrinsic_t::es_selector + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_es_selector() noexcept -> bsl::uint16; - /// - /// @brief Implements intrinsic_t::es_selector - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_cs_selector() noexcept -> bsl::uint16; + /// + /// @brief Implements intrinsic_t::es_selector + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_cs_selector() noexcept -> bsl::uint16; - /// - /// @brief Implements intrinsic_t::es_selector - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_ss_selector() noexcept -> bsl::uint16; + /// + /// @brief Implements intrinsic_t::es_selector + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_ss_selector() noexcept -> bsl::uint16; - /// - /// @brief Implements intrinsic_t::es_selector - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_ds_selector() noexcept -> bsl::uint16; + /// + /// @brief Implements intrinsic_t::es_selector + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_ds_selector() noexcept -> bsl::uint16; - /// - /// @brief Implements intrinsic_t::es_selector - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_fs_selector() noexcept -> bsl::uint16; + /// + /// @brief Implements intrinsic_t::es_selector + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_fs_selector() noexcept -> bsl::uint16; - /// - /// @brief Implements intrinsic_t::es_selector - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_gs_selector() noexcept -> bsl::uint16; + /// + /// @brief Implements intrinsic_t::es_selector + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_gs_selector() noexcept -> bsl::uint16; - /// - /// @brief Implements intrinsic_t::tr_selector - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_tr_selector() noexcept -> bsl::uint16; + /// + /// @brief Implements intrinsic_t::tr_selector + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_tr_selector() noexcept -> bsl::uint16; - /// - /// @brief Implements intrinsic_t::cr0 - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_cr0() noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::cr0 + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_cr0() noexcept -> bsl::uint64; - /// - /// @brief Implements intrinsic_t::cr3 - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_cr3() noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::cr3 + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_cr3() noexcept -> bsl::uint64; - /// - /// @brief Implements intrinsic_t::set_cr3 - /// - /// - /// @param val n/a - /// - extern "C" void intrinsic_set_cr3(bsl::uint64 const val) noexcept; + /// + /// @brief Implements intrinsic_t::set_cr3 + /// + /// + /// @param val n/a + /// + extern "C" void intrinsic_set_cr3(bsl::uint64 const val) noexcept; - /// - /// @brief Implements intrinsic_t::cr4 - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_cr4() noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::cr4 + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_cr4() noexcept -> bsl::uint64; - /// - /// @brief Implements intrinsic_t::tp - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_tp() noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::tp + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_tp() noexcept -> bsl::uint64; - /// - /// @brief Implements intrinsic_t::set_tp - /// - /// - /// @param val n/a - /// - extern "C" void intrinsic_set_tp(bsl::uint64 const val) noexcept; + /// + /// @brief Implements intrinsic_t::set_tp + /// + /// + /// @param val n/a + /// + extern "C" void intrinsic_set_tp(bsl::uint64 const val) noexcept; - /// - /// @brief Implements intrinsic_t::tls_reg - /// - /// - /// @param reg n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_tls_reg(bsl::uint64 const reg) noexcept - -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::tls_reg + /// + /// + /// @param reg n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_tls_reg(bsl::uint64 const reg) noexcept -> bsl::uint64; - /// - /// @brief Implements intrinsic_t::set_tls_reg - /// - /// - /// @param reg n/a - /// @param val n/a - /// - extern "C" void - intrinsic_set_tls_reg(bsl::uint64 const reg, bsl::uint64 const val) noexcept; + /// + /// @brief Implements intrinsic_t::set_tls_reg + /// + /// + /// @param reg n/a + /// @param val n/a + /// + extern "C" void intrinsic_set_tls_reg(bsl::uint64 const reg, bsl::uint64 const val) noexcept; - /// - /// @brief Implements intrinsic_t::halt - /// - extern "C" void intrinsic_halt() noexcept; + /// + /// @brief Implements intrinsic_t::halt + /// + extern "C" void intrinsic_halt() noexcept; - /// - /// @brief Implements intrinsic_t::rdmsr - /// - /// - /// @param msr n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto - intrinsic_rdmsr(bsl::uint32 msr, bsl::uint64 *const val) noexcept -> bsl::exit_code; + /// + /// @brief Implements intrinsic_t::rdmsr + /// + /// + /// @param msr n/a + /// @param val n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_rdmsr(bsl::uint32 msr, bsl::uint64 *const val) noexcept + -> bsl::exit_code; - /// - /// @brief Implements intrinsic_t::wrmsr - /// - /// - /// @param msr n/a - /// @param val n/a - /// - extern "C" [[nodiscard]] auto - intrinsic_wrmsr(bsl::uint32 msr, bsl::uint64 const val) noexcept -> bsl::exit_code; + /// + /// @brief Implements intrinsic_t::wrmsr + /// + /// + /// @param msr n/a + /// @param val n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_wrmsr(bsl::uint32 msr, bsl::uint64 const val) noexcept + -> bsl::exit_code; - /// - /// @brief Implements intrinsic_t::vmload - /// - /// - /// @param phys n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto intrinsic_vmload(void *const phys) noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::invept + /// + /// + /// @param desc n/a + /// @param type n/a + /// + extern "C" void intrinsic_invept(void *const desc, bsl::uint64 const type) noexcept; - /// - /// @brief Implements intrinsic_t::vmread16 - /// - /// - /// @param field n/a - /// @param val n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto - intrinsic_vmread16(bsl::uint64 field, bsl::uint16 *const val) noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::invvpid + /// + /// + /// @param desc n/a + /// @param type n/a + /// + extern "C" void intrinsic_invvpid(void *const desc, bsl::uint64 const type) noexcept; - /// - /// @brief Implements intrinsic_t::vmread32 - /// - /// - /// @param field n/a - /// @param val n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto - intrinsic_vmread32(bsl::uint64 field, bsl::uint32 *const val) noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::vmload + /// + /// + /// @param phys n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_vmload(void *const phys) noexcept -> bsl::exit_code; - /// - /// @brief Implements intrinsic_t::vmread64 - /// - /// - /// @param field n/a - /// @param val n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto - intrinsic_vmread64(bsl::uint64 field, bsl::uint64 *const val) noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::vmclear + /// + /// + /// @param phys n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto intrinsic_vmclear(void *const phys) noexcept -> bsl::exit_code; - /// - /// @brief Implements intrinsic_t::vmwrite16 - /// - /// - /// @param field n/a - /// @param val n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto - intrinsic_vmwrite16(bsl::uint64 field, bsl::uint16 const val) noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::vmread16 + /// + /// + /// @param field n/a + /// @param val n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto + intrinsic_vmread16(bsl::uint64 field, bsl::uint16 *const val) noexcept -> bsl::exit_code; - /// - /// @brief Implements intrinsic_t::vmwrite32 - /// - /// - /// @param field n/a - /// @param val n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto - intrinsic_vmwrite32(bsl::uint64 field, bsl::uint32 const val) noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::vmread32 + /// + /// + /// @param field n/a + /// @param val n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto + intrinsic_vmread32(bsl::uint64 field, bsl::uint32 *const val) noexcept -> bsl::exit_code; - /// - /// @brief Implements intrinsic_t::vmwrite64 - /// - /// - /// @param field n/a - /// @param val n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto - intrinsic_vmwrite64(bsl::uint64 field, bsl::uint64 const val) noexcept -> bsl::uint64; + /// + /// @brief Implements intrinsic_t::vmread64 + /// + /// + /// @param field n/a + /// @param val n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto + intrinsic_vmread64(bsl::uint64 field, bsl::uint64 *const val) noexcept -> bsl::exit_code; - /// - /// @brief Executes the VMLaunch/VMResume instructions. When this - /// function returns, a "VMExit" has occurred and must be handled. - /// - /// - /// @param vmcs_missing_registers a pointer to struct for where to - /// store the registers not saved in the VMCS - /// @return Returns the error code associated with the VMExit - /// - extern "C" [[nodiscard]] auto intrinsic_vmrun(void *const vmcs_missing_registers) noexcept - -> bsl::uintmax; - } + /// + /// @brief Implements intrinsic_t::vmwrite16 + /// + /// + /// @param field n/a + /// @param val n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto + intrinsic_vmwrite16(bsl::uint64 field, bsl::uint16 const val) noexcept -> bsl::exit_code; + + /// + /// @brief Implements intrinsic_t::vmwrite32 + /// + /// + /// @param field n/a + /// @param val n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto + intrinsic_vmwrite32(bsl::uint64 field, bsl::uint32 const val) noexcept -> bsl::exit_code; + + /// + /// @brief Implements intrinsic_t::vmwrite64 + /// + /// + /// @param field n/a + /// @param val n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto + intrinsic_vmwrite64(bsl::uint64 field, bsl::uint64 const val) noexcept -> bsl::exit_code; + + /// + /// @brief Executes the VMLaunch/VMResume instructions. When this + /// function returns, a "VMExit" has occurred and must be handled. + /// + /// + /// @param vmcs_missing_registers a pointer to struct for where to + /// store the registers not saved in the VMCS + /// @return Returns the exit reason associated with the VMExit + /// + extern "C" [[nodiscard]] auto intrinsic_vmrun(void *const vmcs_missing_registers) noexcept + -> bsl::uintmax; /// @class mk::intrinsic_t /// @@ -292,52 +321,6 @@ namespace mk class intrinsic_t final { public: - /// - /// @brief Default constructor - /// - constexpr intrinsic_t() noexcept = default; - - /// - /// @brief Destructor - /// - constexpr ~intrinsic_t() noexcept = default; - - /// - /// @brief copy constructor - /// - /// - /// @param o the object being copied - /// - constexpr intrinsic_t(intrinsic_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr intrinsic_t(intrinsic_t &&o) noexcept = delete; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(intrinsic_t const &o) &noexcept - -> intrinsic_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(intrinsic_t &&o) &noexcept - -> intrinsic_t & = delete; - /// /// @brief Invalidates TLB entries given a virtual address /// @@ -352,15 +335,15 @@ namespace mk } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return; } - details::intrinsic_invlpg(val.get()); + intrinsic_invlpg(val.get()); } /// @@ -376,7 +359,7 @@ namespace mk return {}; } - return details::intrinsic_es_selector(); + return intrinsic_es_selector(); } /// @@ -392,7 +375,7 @@ namespace mk return {}; } - return details::intrinsic_cs_selector(); + return intrinsic_cs_selector(); } /// @@ -408,7 +391,7 @@ namespace mk return {}; } - return details::intrinsic_ss_selector(); + return intrinsic_ss_selector(); } /// @@ -424,7 +407,7 @@ namespace mk return {}; } - return details::intrinsic_ds_selector(); + return intrinsic_ds_selector(); } /// @@ -440,7 +423,7 @@ namespace mk return {}; } - return details::intrinsic_fs_selector(); + return intrinsic_fs_selector(); } /// @@ -456,7 +439,7 @@ namespace mk return {}; } - return details::intrinsic_gs_selector(); + return intrinsic_gs_selector(); } /// @@ -472,7 +455,7 @@ namespace mk return {}; } - return details::intrinsic_tr_selector(); + return intrinsic_tr_selector(); } /// @@ -488,7 +471,7 @@ namespace mk return {}; } - return details::intrinsic_cr0(); + return intrinsic_cr0(); } /// @@ -504,7 +487,7 @@ namespace mk return {}; } - return details::intrinsic_cr3(); + return intrinsic_cr3(); } /// @@ -521,15 +504,15 @@ namespace mk } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return; } - details::intrinsic_set_cr3(val.get()); + intrinsic_set_cr3(val.get()); } /// @@ -545,7 +528,7 @@ namespace mk return {}; } - return details::intrinsic_cr4(); + return intrinsic_cr4(); } /// @@ -561,7 +544,7 @@ namespace mk return {}; } - return details::intrinsic_tp(); + return intrinsic_tp(); } /// @@ -578,15 +561,15 @@ namespace mk } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return; } - details::intrinsic_set_tp(val.get()); + intrinsic_set_tp(val.get()); } /// @@ -604,15 +587,15 @@ namespace mk } if (bsl::unlikely(!reg)) { - bsl::error() << "invalid reg: " // -- - << bsl::hex(reg) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid reg " // -- + << bsl::hex(reg) // -- + << bsl::endl // -- + << bsl::here(); // -- return {}; } - return details::intrinsic_tls_reg(reg.get()); + return intrinsic_tls_reg(reg.get()); } /// @@ -630,24 +613,24 @@ namespace mk } if (bsl::unlikely(!reg)) { - bsl::error() << "invalid reg: " // -- - << bsl::hex(reg) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid reg " // -- + << bsl::hex(reg) // -- + << bsl::endl // -- + << bsl::here(); // -- return; } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return; } - details::intrinsic_set_tls_reg(reg.get(), val.get()); + intrinsic_set_tls_reg(reg.get(), val.get()); } /// @@ -660,7 +643,7 @@ namespace mk return; } - details::intrinsic_halt(); + intrinsic_halt(); } /// @@ -681,22 +664,22 @@ namespace mk } if (bsl::unlikely(!msr)) { - bsl::error() << "invalid msr: " // -- - << bsl::hex(msr) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid msr " // -- + << bsl::hex(msr) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::safe_uint64::zero(true); + return bsl::safe_uint64::failure(); } - ret = details::intrinsic_rdmsr(msr.get(), val.data()); + ret = intrinsic_rdmsr(msr.get(), val.data()); if (bsl::unlikely(ret != bsl::exit_success)) { bsl::error() << "rdmsr failed for msr " // -- << bsl::hex(msr) // -- << bsl::endl // -- << bsl::here(); // -- - return bsl::safe_uint64::zero(true); + return bsl::safe_uint64::failure(); } return val; @@ -709,7 +692,7 @@ namespace mk /// @param msr the MSR to write to /// @param val the value to set the MSR to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] static constexpr auto wrmsr(bsl::safe_uint32 const &msr, bsl::safe_uint64 const &val) noexcept -> bsl::errc_type @@ -721,24 +704,24 @@ namespace mk } if (bsl::unlikely(!msr)) { - bsl::error() << "invalid msr: " // -- - << bsl::hex(msr) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid msr " // -- + << bsl::hex(msr) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - ret = details::intrinsic_wrmsr(msr.get(), val.get()); + ret = intrinsic_wrmsr(msr.get(), val.get()); if (bsl::unlikely(ret != bsl::exit_success)) { bsl::error() << "wrmsr failed for msr " // -- << bsl::hex(msr) // -- @@ -753,6 +736,102 @@ namespace mk return bsl::errc_success; } + /// + /// @brief Invalidates mappings in the translation lookaside buffers + /// (TLBs) and paging-structure caches that were derived from + /// extended page tables (EPT). + /// + /// + /// @param eptp The EPTP to invalidate + /// @param type The INVEPT type (see the Intel SDM for details) + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + invept(bsl::safe_uint64 const &eptp, bsl::safe_uint64 const &type) noexcept + -> bsl::errc_type + { + if (bsl::is_constant_evaluated()) { + return bsl::errc_success; + } + + if (bsl::unlikely(!eptp)) { + bsl::error() << "invalid eptp " // -- + << bsl::hex(eptp) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!type)) { + bsl::error() << "invalid type " // -- + << bsl::hex(type) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + invept_descriptor_t desc{eptp.get(), {}}; + intrinsic_invept(&desc, type.get()); + return bsl::errc_success; + } + + /// + /// @brief Invalidates mappings in the translation lookaside buffers + /// (TLBs) and paging-structure caches that were derived from + /// extended page tables (EPT). + /// + /// + /// @param addr The address to invalidate + /// @param vpid The VPID to invalidate + /// @param type The INVVPID type (see the Intel SDM for details) + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + invvpid( + bsl::safe_uint64 const &addr, + bsl::safe_uint16 const &vpid, + bsl::safe_uint64 const &type) noexcept -> bsl::errc_type + { + if (bsl::is_constant_evaluated()) { + return bsl::errc_success; + } + + if (bsl::unlikely(!addr)) { + bsl::error() << "invalid addr " // -- + << bsl::hex(addr) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!vpid)) { + bsl::error() << "invalid vpid " // -- + << bsl::hex(vpid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely(!type)) { + bsl::error() << "invalid type " // -- + << bsl::hex(type) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + invvpid_descriptor_t desc{vpid.get(), {}, {}, {}, addr.get()}; + intrinsic_invvpid(&desc, type.get()); + return bsl::errc_success; + } + /// /// @brief Loads a VMCS given a pointer to the physical address /// of the VMCS. @@ -761,7 +840,7 @@ namespace mk /// @param phys a pointer to the physical address of the VMCS to /// load. /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] static constexpr auto vmload(void *const phys) noexcept -> bsl::errc_type @@ -771,18 +850,20 @@ namespace mk } if (bsl::unlikely(nullptr == phys)) { - bsl::error() << "invalid phys: " // -- - << phys // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid phys " // -- + << phys // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - auto const ret{details::intrinsic_vmload(phys)}; - if (bsl::unlikely(ret != bsl::ZERO_UMAX)) { + bsl::exit_code const ret{intrinsic_vmload(phys)}; + if (bsl::unlikely(ret != bsl::exit_success)) { bsl::error() << "vmload failed for " // -- << phys // -- + << " with error code " // -- + << ret // -- << bsl::endl // -- << bsl::here(); // -- @@ -792,6 +873,47 @@ namespace mk return bsl::errc_success; } + /// + /// @brief Clears a VMCS given a pointer to the physical address + /// of the VMCS. + /// + /// + /// @param phys a pointer to the physical address of the VMCS to + /// load. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + vmclear(void *const phys) noexcept -> bsl::errc_type + { + if (bsl::is_constant_evaluated()) { + return bsl::errc_success; + } + + if (bsl::unlikely(nullptr == phys)) { + bsl::error() << "invalid phys " // -- + << phys // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + bsl::exit_code const ret{intrinsic_vmclear(phys)}; + if (bsl::unlikely(ret != bsl::exit_success)) { + bsl::error() << "vmclear failed for " // -- + << phys // -- + << " with error code " // -- + << ret // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + /// /// @brief Returns the value of requested 16 bit VMCS field /// @@ -799,7 +921,7 @@ namespace mk /// @param field the 16 bit VMCS field to read /// @param val the value to store the 32 bit VMCS field to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] static constexpr auto vmread16(bsl::safe_uint64 const &field, bsl::uint16 *const val) noexcept -> bsl::errc_type @@ -809,27 +931,29 @@ namespace mk } if (bsl::unlikely(!field)) { - bsl::error() << "invalid field: " // -- - << bsl::hex(field) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid field " // -- + << bsl::hex(field) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } if (bsl::unlikely(nullptr == val)) { - bsl::error() << "invalid val: " // -- - << val // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << val // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - auto const ret{details::intrinsic_vmread16(field.get(), val)}; - if (bsl::unlikely(ret != bsl::ZERO_UMAX)) { + bsl::exit_code const ret{intrinsic_vmread16(field.get(), val)}; + if (bsl::unlikely(ret != bsl::exit_success)) { bsl::error() << "vmread failed for field " // -- << bsl::hex(field) // -- + << " with error code " // -- + << ret // -- << bsl::endl // -- << bsl::here(); // -- @@ -846,7 +970,7 @@ namespace mk /// @param field the 32 bit VMCS field to read /// @param val the value to store the 32 bit VMCS field to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] static constexpr auto vmread32(bsl::safe_uint64 const &field, bsl::uint32 *const val) noexcept -> bsl::errc_type @@ -856,27 +980,29 @@ namespace mk } if (bsl::unlikely(!field)) { - bsl::error() << "invalid field: " // -- - << bsl::hex(field) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid field " // -- + << bsl::hex(field) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } if (bsl::unlikely(nullptr == val)) { - bsl::error() << "invalid val: " // -- - << val // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << val // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - auto const ret{details::intrinsic_vmread32(field.get(), val)}; - if (bsl::unlikely(ret != bsl::ZERO_UMAX)) { + bsl::exit_code const ret{intrinsic_vmread32(field.get(), val)}; + if (bsl::unlikely(ret != bsl::exit_success)) { bsl::error() << "vmread failed for field " // -- << bsl::hex(field) // -- + << " with error code " // -- + << ret // -- << bsl::endl // -- << bsl::here(); // -- @@ -893,7 +1019,7 @@ namespace mk /// @param field the 64 bit VMCS field to read /// @param val the value to store the 32 bit VMCS field to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] static constexpr auto vmread64(bsl::safe_uint64 const &field, bsl::uint64 *const val) noexcept -> bsl::errc_type @@ -903,27 +1029,29 @@ namespace mk } if (bsl::unlikely(!field)) { - bsl::error() << "invalid field: " // -- - << bsl::hex(field) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid field " // -- + << bsl::hex(field) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } if (bsl::unlikely(nullptr == val)) { - bsl::error() << "invalid val: " // -- - << val // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << val // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - auto const ret{details::intrinsic_vmread64(field.get(), val)}; - if (bsl::unlikely(ret != bsl::ZERO_UMAX)) { + bsl::exit_code const ret{intrinsic_vmread64(field.get(), val)}; + if (bsl::unlikely(ret != bsl::exit_success)) { bsl::error() << "vmread failed for field " // -- << bsl::hex(field) // -- + << " with error code " // -- + << ret // -- << bsl::endl // -- << bsl::here(); // -- @@ -939,42 +1067,28 @@ namespace mk /// /// /// @param field the 16 bit VMCS field to read - /// @param val the value to store the 32 bit VMCS field to - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// @return Returns the value read from the VMS, or + /// bsl::safe_uint16::failure() on failure. /// [[nodiscard]] static constexpr auto - vmread16_quiet(bsl::safe_uint64 const &field, bsl::uint16 *const val) noexcept - -> bsl::errc_type + vmread16_quiet(bsl::safe_uint64 const &field) noexcept -> bsl::safe_uint16 { + bsl::safe_uint16 val{}; + if (bsl::is_constant_evaluated()) { - return bsl::errc_success; + return val; } if (bsl::unlikely(!field)) { - bsl::error() << "invalid field: " // -- - << bsl::hex(field) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; + return bsl::safe_uint16::failure(); } - if (bsl::unlikely(nullptr == val)) { - bsl::error() << "invalid val: " // -- - << val // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; + bsl::exit_code const ret{intrinsic_vmread16(field.get(), val.data())}; + if (bsl::unlikely(ret != bsl::exit_success)) { + return bsl::safe_uint16::failure(); } - auto const ret{details::intrinsic_vmread16(field.get(), val)}; - if (bsl::unlikely(ret != bsl::ZERO_UMAX)) { - return bsl::errc_failure; - } - - return bsl::errc_success; + return val; } /// @@ -983,42 +1097,28 @@ namespace mk /// /// /// @param field the 32 bit VMCS field to read - /// @param val the value to store the 32 bit VMCS field to - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// @return Returns the value read from the VMS, or + /// bsl::safe_uint32::failure() on failure. /// [[nodiscard]] static constexpr auto - vmread32_quiet(bsl::safe_uint64 const &field, bsl::uint32 *const val) noexcept - -> bsl::errc_type + vmread32_quiet(bsl::safe_uint64 const &field) noexcept -> bsl::safe_uint32 { + bsl::safe_uint32 val{}; + if (bsl::is_constant_evaluated()) { - return bsl::errc_success; + return val; } if (bsl::unlikely(!field)) { - bsl::error() << "invalid field: " // -- - << bsl::hex(field) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; + return bsl::safe_uint32::failure(); } - if (bsl::unlikely(nullptr == val)) { - bsl::error() << "invalid val: " // -- - << val // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; + bsl::exit_code const ret{intrinsic_vmread32(field.get(), val.data())}; + if (bsl::unlikely(ret != bsl::exit_success)) { + return bsl::safe_uint32::failure(); } - auto const ret{details::intrinsic_vmread32(field.get(), val)}; - if (bsl::unlikely(ret != bsl::ZERO_UMAX)) { - return bsl::errc_failure; - } - - return bsl::errc_success; + return val; } /// @@ -1027,42 +1127,28 @@ namespace mk /// /// /// @param field the 64 bit VMCS field to read - /// @param val the value to store the 32 bit VMCS field to - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// @return Returns the value read from the VMS, or + /// bsl::safe_uint64::failure() on failure. /// [[nodiscard]] static constexpr auto - vmread64_quiet(bsl::safe_uint64 const &field, bsl::uint64 *const val) noexcept - -> bsl::errc_type + vmread64_quiet(bsl::safe_uint64 const &field) noexcept -> bsl::safe_uint64 { + bsl::safe_uint64 val{}; + if (bsl::is_constant_evaluated()) { - return bsl::errc_success; + return val; } if (bsl::unlikely(!field)) { - bsl::error() << "invalid field: " // -- - << bsl::hex(field) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; + return bsl::safe_uint64::failure(); } - if (bsl::unlikely(nullptr == val)) { - bsl::error() << "invalid val: " // -- - << val // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; + bsl::exit_code const ret{intrinsic_vmread64(field.get(), val.data())}; + if (bsl::unlikely(ret != bsl::exit_success)) { + return bsl::safe_uint64::failure(); } - auto const ret{details::intrinsic_vmread64(field.get(), val)}; - if (bsl::unlikely(ret != bsl::ZERO_UMAX)) { - return bsl::errc_failure; - } - - return bsl::errc_success; + return val; } /// @@ -1072,7 +1158,7 @@ namespace mk /// @param field the 16 bit VMCS field to write to /// @param val the value to set the 16 bit VMCS field to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] static constexpr auto vmwrite16(bsl::safe_uint64 const &field, bsl::safe_uint16 const &val) noexcept @@ -1083,29 +1169,31 @@ namespace mk } if (bsl::unlikely(!field)) { - bsl::error() << "invalid field: " // -- - << bsl::hex(field) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid field " // -- + << bsl::hex(field) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - auto const ret{details::intrinsic_vmwrite16(field.get(), val.get())}; - if (bsl::unlikely(ret != bsl::ZERO_UMAX)) { + bsl::exit_code const ret{intrinsic_vmwrite16(field.get(), val.get())}; + if (bsl::unlikely(ret != bsl::exit_success)) { bsl::error() << "vmwrite failed for field " // -- << bsl::hex(field) // -- << " with value " // -- << bsl::hex(val) // -- + << " with error code " // -- + << ret // -- << bsl::endl // -- << bsl::here(); // -- @@ -1122,7 +1210,7 @@ namespace mk /// @param field the 32 bit VMCS field to write to /// @param val the value to set the 32 bit VMCS field to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] static constexpr auto vmwrite32(bsl::safe_uint64 const &field, bsl::safe_uint32 const &val) noexcept @@ -1133,29 +1221,31 @@ namespace mk } if (bsl::unlikely(!field)) { - bsl::error() << "invalid field: " // -- - << bsl::hex(field) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid field " // -- + << bsl::hex(field) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - auto const ret{details::intrinsic_vmwrite32(field.get(), val.get())}; - if (bsl::unlikely(ret != bsl::ZERO_UMAX)) { + bsl::exit_code const ret{intrinsic_vmwrite32(field.get(), val.get())}; + if (bsl::unlikely(ret != bsl::exit_success)) { bsl::error() << "vmwrite failed for field " // -- << bsl::hex(field) // -- << " with value " // -- << bsl::hex(val) // -- + << " with error code " // -- + << ret // -- << bsl::endl // -- << bsl::here(); // -- @@ -1172,7 +1262,7 @@ namespace mk /// @param field the 64 bit VMCS field to write to /// @param val the value to set the 64 bit VMCS field to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] static constexpr auto vmwrite64(bsl::safe_uint64 const &field, bsl::safe_uint64 const &val) noexcept @@ -1183,29 +1273,31 @@ namespace mk } if (bsl::unlikely(!field)) { - bsl::error() << "invalid field: " // -- - << bsl::hex(field) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid field " // -- + << bsl::hex(field) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + bsl::error() << "invalid val " // -- + << bsl::hex(val) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } - auto const ret{details::intrinsic_vmwrite64(field.get(), val.get())}; - if (bsl::unlikely(ret != bsl::ZERO_UMAX)) { + bsl::exit_code const ret{intrinsic_vmwrite64(field.get(), val.get())}; + if (bsl::unlikely(ret != bsl::exit_success)) { bsl::error() << "vmwrite failed for field " // -- << bsl::hex(field) // -- << " with value " // -- << bsl::hex(val) // -- + << " with error code " // -- + << ret // -- << bsl::endl // -- << bsl::here(); // -- diff --git a/kernel/src/x64/intel/promote.S b/kernel/src/x64/intel/promote.S index 9f4dd955..4a9b998f 100644 --- a/kernel/src/x64/intel/promote.S +++ b/kernel/src/x64/intel/promote.S @@ -24,6 +24,31 @@ * SOFTWARE. */ + /** @brief defines the offset of state_save_t.rax */ + #define SS_OFFSET_RAX 0x000 + /** @brief defines the offset of state_save_t.promote_handler */ + #define SS_OFFSET_PROMOTE_HANDLER 0x2E8 + /** @brief defines the offset of state_save_t.esr_default_handler */ + #define SS_OFFSET_ESR_DEFAULT_HANDLER 0x2F0 + /** @brief defines the offset of state_save_t.esr_df_handler */ + #define SS_OFFSET_ESR_DF_HANDLER 0x2F8 + /** @brief defines the offset of state_save_t.esr_gpf_handler */ + #define SS_OFFSET_ESR_GPF_HANDLER 0x300 + /** @brief defines the offset of state_save_t.esr_nmi_handler */ + #define SS_OFFSET_ESR_NMI_HANDLER 0x308 + /** @brief defines the offset of state_save_t.esr_pf_handler */ + #define SS_OFFSET_ESR_PF_HANDLER 0x310 + /** @brief defines the offset of state_save_t.nmi */ + #define SS_OFFSET_NMI 0x318 + + /** @brief defines the offset of tls_t.nmi_pending */ + #define TLS_OFFSET_NMI_PENDING 0x260 + + /** @brief defines primary_proc_based_vm_execution_ctls */ + #define VMCS_PRIMARY_PROC_BASED_VM_EXECUTION_CTLS 0x4002 + /** @brief defines primary_proc_based_vm_execution_ctls.nmi_window */ + #define VMCS_PRIMARY_PROC_BASED_VM_EXECUTION_CTLS_NMI_WINDOW 0x0000000000400000 + .code64 .intel_syntax noprefix @@ -31,79 +56,104 @@ .type promote, @function promote: + /** + * NOTE: + * - Save off the first argument just in case we need to call other + * functions including debugging. The first argument in this case + * is a pointer to the root VP's state save. + */ + mov r15, rdi - mov [r15 + 0x000], rsi + + /** + * NOTE: + * - Store the return value for the demote() function. Once this function + * is done, it will return to the loader's promote() function which + * will return to the C portion of the loader as if demote() had returned + * and this is where we store the return value. Note that promote() + * can be called on error, or when the hypervisor is stopping. + */ + + mov [r15 + SS_OFFSET_RAX], rsi + + /** + * NOTE: + * - Restore the exception vectors. This is needed because we will no + * longer be able to use the exception vectores from the microkernel + * as we unload it, so we will use the exception vectors from the + * loader instead. + */ mov rdi, 0 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 1 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 2 - mov rsi, [r15 + 0x308] + mov rsi, [r15 + SS_OFFSET_ESR_NMI_HANDLER] call set_esr mov rdi, 3 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 4 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 5 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 6 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 7 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 8 - mov rsi, [r15 + 0x2F8] + mov rsi, [r15 + SS_OFFSET_ESR_DF_HANDLER] call set_esr mov rdi, 10 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 11 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 12 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 13 - mov rsi, [r15 + 0x300] + mov rsi, [r15 + SS_OFFSET_ESR_GPF_HANDLER] call set_esr mov rdi, 14 - mov rsi, [r15 + 0x310] + mov rsi, [r15 + SS_OFFSET_ESR_PF_HANDLER] call set_esr mov rdi, 16 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 17 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 18 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr mov rdi, 19 - mov rsi, [r15 + 0x2F0] + mov rsi, [r15 + SS_OFFSET_ESR_DEFAULT_HANDLER] call set_esr /** @@ -121,35 +171,41 @@ promote: /** * TODO: - * - There is a third was an NMI could be recorded. If an extension + * - There is a third way an NMI could be recorded. If an extension * injects an NMI and then promotes without ever allowing the * injection to process. For now we don't handle this case as it * is extremely unlikely. */ - mov rax, gs:[0x260] + mov rax, gs:[TLS_OFFSET_NMI_PENDING] cmp rax, 0x1 jne nmi_pending_transfer_complete mov rax, 0x1 - mov [r15 + 0x318], rax + mov [r15 + SS_OFFSET_NMI], rax nmi_pending_transfer_complete: - mov rax, 0x4002 + mov rax, VMCS_PRIMARY_PROC_BASED_VM_EXECUTION_CTLS vmread rax, rax jbe nmi_window_transfer_complete - mov rdx, 0x0000000000400000 + mov rdx, VMCS_PRIMARY_PROC_BASED_VM_EXECUTION_CTLS_NMI_WINDOW and rax, rdx cmp rax, 0x0 je nmi_window_transfer_complete mov rax, 0x1 - mov [r15 + 0x318], rax + mov [r15 + SS_OFFSET_NMI], rax nmi_window_transfer_complete: + /** + * NOTE: + * - Call the loader's promote() handler. This will conclude execution + * from the microkernel. + */ + call set_up_target capture_spec: pause diff --git a/kernel/src/x64/intel/vmcs_t.hpp b/kernel/src/x64/intel/vmcs_t.hpp deleted file mode 100644 index c2fe4a01..00000000 --- a/kernel/src/x64/intel/vmcs_t.hpp +++ /dev/null @@ -1,402 +0,0 @@ -/// @copyright -/// Copyright (C) 2020 Assured Information Security, Inc. -/// -/// @copyright -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// @copyright -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// @copyright -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -/// SOFTWARE. - -#ifndef VMCS_HPP -#define VMCS_HPP - -#pragma pack(push, 1) - -#include -#include -#include -#include - -namespace mk -{ - namespace details - { - /// @brief the size of reserved field - constexpr bsl::safe_uintmax RESERVED_SIZE{bsl::to_umax(0xFFC)}; - } - - /// @brief defines an unusable segment descriptor - constexpr bsl::safe_uint32 VMCS_UNUSABLE_SEGMENT{bsl::to_u32(0x10000)}; - - /// @brief encoding for: virtual_processor_identifier - constexpr bsl::safe_uintmax VMCS_VIRTUAL_PROCESSOR_IDENTIFIER{bsl::to_umax(0x0000U)}; - /// @brief encoding for: posted_interrupt_notification_vector - constexpr bsl::safe_uintmax VMCS_POSTED_INTERRUPT_NOTIFICATION_VECTOR{bsl::to_umax(0x0002U)}; - /// @brief encoding for: eptp_index - constexpr bsl::safe_uintmax VMCS_EPTP_INDEX{bsl::to_umax(0x0004U)}; - - /// @brief encoding for: guest_es_selector - constexpr bsl::safe_uintmax VMCS_GUEST_ES_SELECTOR{bsl::to_umax(0x0800U)}; - /// @brief encoding for: guest_cs_selector - constexpr bsl::safe_uintmax VMCS_GUEST_CS_SELECTOR{bsl::to_umax(0x0802U)}; - /// @brief encoding for: guest_ss_selector - constexpr bsl::safe_uintmax VMCS_GUEST_SS_SELECTOR{bsl::to_umax(0x0804U)}; - /// @brief encoding for: guest_ds_selector - constexpr bsl::safe_uintmax VMCS_GUEST_DS_SELECTOR{bsl::to_umax(0x0806U)}; - /// @brief encoding for: guest_fs_selector - constexpr bsl::safe_uintmax VMCS_GUEST_FS_SELECTOR{bsl::to_umax(0x0808U)}; - /// @brief encoding for: guest_gs_selector - constexpr bsl::safe_uintmax VMCS_GUEST_GS_SELECTOR{bsl::to_umax(0x080AU)}; - /// @brief encoding for: guest_ldtr_selector - constexpr bsl::safe_uintmax VMCS_GUEST_LDTR_SELECTOR{bsl::to_umax(0x080CU)}; - /// @brief encoding for: guest_tr_selector - constexpr bsl::safe_uintmax VMCS_GUEST_TR_SELECTOR{bsl::to_umax(0x080EU)}; - /// @brief encoding for: guest_interrupt_status - constexpr bsl::safe_uintmax VMCS_GUEST_INTERRUPT_STATUS{bsl::to_umax(0x0810U)}; - /// @brief encoding for: pml_index - constexpr bsl::safe_uintmax VMCS_PML_INDEX{bsl::to_umax(0x0812U)}; - - /// @brief encoding for: host_es_selector - constexpr bsl::safe_uintmax VMCS_HOST_ES_SELECTOR{bsl::to_umax(0x0C00U)}; - /// @brief encoding for: host_cs_selector - constexpr bsl::safe_uintmax VMCS_HOST_CS_SELECTOR{bsl::to_umax(0x0C02U)}; - /// @brief encoding for: host_ss_selector - constexpr bsl::safe_uintmax VMCS_HOST_SS_SELECTOR{bsl::to_umax(0x0C04U)}; - /// @brief encoding for: host_ds_selector - constexpr bsl::safe_uintmax VMCS_HOST_DS_SELECTOR{bsl::to_umax(0x0C06U)}; - /// @brief encoding for: host_fs_selector - constexpr bsl::safe_uintmax VMCS_HOST_FS_SELECTOR{bsl::to_umax(0x0C08U)}; - /// @brief encoding for: host_gs_selector - constexpr bsl::safe_uintmax VMCS_HOST_GS_SELECTOR{bsl::to_umax(0x0C0AU)}; - /// @brief encoding for: host_tr_selector - constexpr bsl::safe_uintmax VMCS_HOST_TR_SELECTOR{bsl::to_umax(0x0C0CU)}; - - /// @brief encoding for: address_of_io_bitmap_a - constexpr bsl::safe_uintmax VMCS_ADDRESS_OF_IO_BITMAP_A{bsl::to_umax(0x2000U)}; - /// @brief encoding for: address_of_io_bitmap_b - constexpr bsl::safe_uintmax VMCS_ADDRESS_OF_IO_BITMAP_B{bsl::to_umax(0x2002U)}; - /// @brief encoding for: address_of_msr_bitmaps - constexpr bsl::safe_uintmax VMCS_ADDRESS_OF_MSR_BITMAPS{bsl::to_umax(0x2004U)}; - /// @brief encoding for: vmexit_msr_store_address - constexpr bsl::safe_uintmax VMCS_VMEXIT_MSR_STORE_ADDRESS{bsl::to_umax(0x2006U)}; - /// @brief encoding for: vmexit_msr_load_address - constexpr bsl::safe_uintmax VMCS_VMEXIT_MSR_LOAD_ADDRESS{bsl::to_umax(0x2008U)}; - /// @brief encoding for: vmentry_msr_load_address - constexpr bsl::safe_uintmax VMCS_VMENTRY_MSR_LOAD_ADDRESS{bsl::to_umax(0x200AU)}; - /// @brief encoding for: executive_vmcs_pointer - constexpr bsl::safe_uintmax VMCS_EXECUTIVE_VMCS_POINTER{bsl::to_umax(0x200CU)}; - /// @brief encoding for: pml_address - constexpr bsl::safe_uintmax VMCS_PML_ADDRESS{bsl::to_umax(0x200EU)}; - /// @brief encoding for: tsc_offset - constexpr bsl::safe_uintmax VMCS_TSC_OFFSET{bsl::to_umax(0x2010U)}; - /// @brief encoding for: virtual_apic_address - constexpr bsl::safe_uintmax VMCS_VIRTUAL_APIC_ADDRESS{bsl::to_umax(0x2012U)}; - /// @brief encoding for: apic_access_address - constexpr bsl::safe_uintmax VMCS_APIC_ACCESS_ADDRESS{bsl::to_umax(0x2014U)}; - /// @brief encoding for: posted_interrupt_descriptor_address - constexpr bsl::safe_uintmax VMCS_POSTED_INTERRUPT_DESCRIPTOR_ADDRESS{bsl::to_umax(0x2016U)}; - /// @brief encoding for: vm_function_controls - constexpr bsl::safe_uintmax VMCS_VM_FUNCTION_CONTROLS{bsl::to_umax(0x2018U)}; - /// @brief encoding for: ept_pointer - constexpr bsl::safe_uintmax VMCS_EPT_POINTER{bsl::to_umax(0x201AU)}; - /// @brief encoding for: eoi_exit_bitmap0 - constexpr bsl::safe_uintmax VMCS_EOI_EXIT_BITMAP0{bsl::to_umax(0x201CU)}; - /// @brief encoding for: eoi_exit_bitmap1 - constexpr bsl::safe_uintmax VMCS_EOI_EXIT_BITMAP1{bsl::to_umax(0x201EU)}; - /// @brief encoding for: eoi_exit_bitmap2 - constexpr bsl::safe_uintmax VMCS_EOI_EXIT_BITMAP2{bsl::to_umax(0x2020U)}; - /// @brief encoding for: eoi_exit_bitmap3 - constexpr bsl::safe_uintmax VMCS_EOI_EXIT_BITMAP3{bsl::to_umax(0x2022U)}; - /// @brief encoding for: eptp_list_address - constexpr bsl::safe_uintmax VMCS_EPTP_LIST_ADDRESS{bsl::to_umax(0x2024U)}; - /// @brief encoding for: vmread_bitmap_address - constexpr bsl::safe_uintmax VMCS_VMREAD_BITMAP_ADDRESS{bsl::to_umax(0x2026U)}; - /// @brief encoding for: vmwrite_bitmap_address - constexpr bsl::safe_uintmax VMCS_VMWRITE_BITMAP_ADDRESS{bsl::to_umax(0x2028U)}; - /// @brief encoding for: virt_exception_information_address - constexpr bsl::safe_uintmax VMCS_VIRT_EXCEPTION_INFORMATION_ADDRESS{bsl::to_umax(0x202AU)}; - /// @brief encoding for: xss_exiting_bitmap - constexpr bsl::safe_uintmax VMCS_XSS_EXITING_BITMAP{bsl::to_umax(0x202CU)}; - /// @brief encoding for: encls_exiting_bitmap - constexpr bsl::safe_uintmax VMCS_ENCLS_EXITING_BITMAP{bsl::to_umax(0x202EU)}; - /// @brief encoding for: sub_page_permission_table_pointer - constexpr bsl::safe_uintmax VMCS_SUB_PAGE_PERMISSION_TABLE_POINTER{bsl::to_umax(0x2030U)}; - /// @brief encoding for: tls_multiplier - constexpr bsl::safe_uintmax VMCS_TLS_MULTIPLIER{bsl::to_umax(0x2032U)}; - - /// @brief encoding for: guest_physical_address - constexpr bsl::safe_uintmax VMCS_GUEST_PHYSICAL_ADDRESS{bsl::to_umax(0x2400U)}; - - /// @brief encoding for: vmcs_link_pointer - constexpr bsl::safe_uintmax VMCS_VMCS_LINK_POINTER{bsl::to_umax(0x2800U)}; - /// @brief encoding for: guest_ia32_debugctl - constexpr bsl::safe_uintmax VMCS_GUEST_IA32_DEBUGCTL{bsl::to_umax(0x2802U)}; - /// @brief encoding for: guest_ia32_pat - constexpr bsl::safe_uintmax VMCS_GUEST_IA32_PAT{bsl::to_umax(0x2804U)}; - /// @brief encoding for: guest_ia32_efer - constexpr bsl::safe_uintmax VMCS_GUEST_IA32_EFER{bsl::to_umax(0x2806U)}; - /// @brief encoding for: guest_ia32_perf_global_ctrl - constexpr bsl::safe_uintmax VMCS_GUEST_IA32_PERF_GLOBAL_CTRL{bsl::to_umax(0x2808U)}; - /// @brief encoding for: guest_pdpte0 - constexpr bsl::safe_uintmax VMCS_GUEST_PDPTE0{bsl::to_umax(0x280AU)}; - /// @brief encoding for: guest_pdpte1 - constexpr bsl::safe_uintmax VMCS_GUEST_PDPTE1{bsl::to_umax(0x280CU)}; - /// @brief encoding for: guest_pdpte2 - constexpr bsl::safe_uintmax VMCS_GUEST_PDPTE2{bsl::to_umax(0x280EU)}; - /// @brief encoding for: guest_pdpte3 - constexpr bsl::safe_uintmax VMCS_GUEST_PDPTE3{bsl::to_umax(0x2810U)}; - /// @brief encoding for: guest_ia32_bndcfgs - constexpr bsl::safe_uintmax VMCS_GUEST_IA32_BNDCFGS{bsl::to_umax(0x2812U)}; - /// @brief encoding for: guest_rtit_ctl - constexpr bsl::safe_uintmax VMCS_GUEST_RTIT_CTL{bsl::to_umax(0x2814U)}; - - /// @brief encoding for: host_ia32_pat - constexpr bsl::safe_uintmax VMCS_HOST_IA32_PAT{bsl::to_umax(0x2C00U)}; - /// @brief encoding for: host_ia32_efer - constexpr bsl::safe_uintmax VMCS_HOST_IA32_EFER{bsl::to_umax(0x2C02U)}; - /// @brief encoding for: host_ia32_perf_global_ctrl - constexpr bsl::safe_uintmax VMCS_HOST_IA32_PERF_GLOBAL_CTRL{bsl::to_umax(0x2C04U)}; - - /// @brief encoding for: pin_based_vm_execution_ctls - constexpr bsl::safe_uintmax VMCS_PIN_BASED_VM_EXECUTION_CTLS{bsl::to_umax(0x4000U)}; - /// @brief encoding for: primary_proc_based_vm_execution_ctls - constexpr bsl::safe_uintmax VMCS_PRIMARY_PROC_BASED_VM_EXECUTION_CTLS{bsl::to_umax(0x4002U)}; - /// @brief encoding for: exception_bitmap - constexpr bsl::safe_uintmax VMCS_EXCEPTION_BITMAP{bsl::to_umax(0x4004U)}; - /// @brief encoding for: page_fault_error_code_mask - constexpr bsl::safe_uintmax VMCS_PAGE_FAULT_ERROR_CODE_MASK{bsl::to_umax(0x4006U)}; - /// @brief encoding for: page_fault_error_code_match - constexpr bsl::safe_uintmax VMCS_PAGE_FAULT_ERROR_CODE_MATCH{bsl::to_umax(0x4008U)}; - /// @brief encoding for: cr3_target_count - constexpr bsl::safe_uintmax VMCS_CR3_TARGET_COUNT{bsl::to_umax(0x400AU)}; - /// @brief encoding for: vmexit_ctls - constexpr bsl::safe_uintmax VMCS_VMEXIT_CTLS{bsl::to_umax(0x400CU)}; - /// @brief encoding for: vmexit_msr_store_count - constexpr bsl::safe_uintmax VMCS_VMEXIT_MSR_STORE_COUNT{bsl::to_umax(0x400EU)}; - /// @brief encoding for: vmexit_msr_load_count - constexpr bsl::safe_uintmax VMCS_VMEXIT_MSR_LOAD_COUNT{bsl::to_umax(0x4010U)}; - /// @brief encoding for: vmentry_ctls - constexpr bsl::safe_uintmax VMCS_VMENTRY_CTLS{bsl::to_umax(0x4012U)}; - /// @brief encoding for: vmentry_msr_load_count - constexpr bsl::safe_uintmax VMCS_VMENTRY_MSR_LOAD_COUNT{bsl::to_umax(0x4014U)}; - /// @brief encoding for: vmentry_interrupt_information_field - constexpr bsl::safe_uintmax VMCS_VMENTRY_INTERRUPT_INFORMATION_FIELD{bsl::to_umax(0x4016U)}; - /// @brief encoding for: vmentry_exception_error_code - constexpr bsl::safe_uintmax VMCS_VMENTRY_EXCEPTION_ERROR_CODE{bsl::to_umax(0x4018U)}; - /// @brief encoding for: vmentry_instruction_length - constexpr bsl::safe_uintmax VMCS_VMENTRY_INSTRUCTION_LENGTH{bsl::to_umax(0x401AU)}; - /// @brief encoding for: tpr_threshold - constexpr bsl::safe_uintmax VMCS_TPR_THRESHOLD{bsl::to_umax(0x401CU)}; - /// @brief encoding for: secondary_proc_based_vm_execution_ctls - constexpr bsl::safe_uintmax VMCS_SECONDARY_PROC_BASED_VM_EXECUTION_CTLS{bsl::to_umax(0x401EU)}; - /// @brief encoding for: ple_gap - constexpr bsl::safe_uintmax VMCS_PLE_GAP{bsl::to_umax(0x4020U)}; - /// @brief encoding for: ple_window - constexpr bsl::safe_uintmax VMCS_PLE_WINDOW{bsl::to_umax(0x4022U)}; - - /// @brief encoding for: vm_instruction_error - constexpr bsl::safe_uintmax VMCS_VM_INSTRUCTION_ERROR{bsl::to_umax(0x4400U)}; - /// @brief encoding for: exit_reason - constexpr bsl::safe_uintmax VMCS_EXIT_REASON{bsl::to_umax(0x4402U)}; - /// @brief encoding for: vmexit_interruption_information - constexpr bsl::safe_uintmax VMCS_VMEXIT_INTERRUPTION_INFORMATION{bsl::to_umax(0x4404U)}; - /// @brief encoding for: vmexit_interruption_error_code - constexpr bsl::safe_uintmax VMCS_VMEXIT_INTERRUPTION_ERROR_CODE{bsl::to_umax(0x4406U)}; - /// @brief encoding for: idt_vectoring_information_field - constexpr bsl::safe_uintmax VMCS_IDT_VECTORING_INFORMATION_FIELD{bsl::to_umax(0x4408U)}; - /// @brief encoding for: idt_vectoring_error_code - constexpr bsl::safe_uintmax VMCS_IDT_VECTORING_ERROR_CODE{bsl::to_umax(0x440AU)}; - /// @brief encoding for: vmexit_instruction_length - constexpr bsl::safe_uintmax VMCS_VMEXIT_INSTRUCTION_LENGTH{bsl::to_umax(0x440CU)}; - /// @brief encoding for: vmexit_instruction_information - constexpr bsl::safe_uintmax VMCS_VMEXIT_INSTRUCTION_INFORMATION{bsl::to_umax(0x440EU)}; - - /// @brief encoding for: guest_es_limit - constexpr bsl::safe_uintmax VMCS_GUEST_ES_LIMIT{bsl::to_umax(0x4800U)}; - /// @brief encoding for: guest_cs_limit - constexpr bsl::safe_uintmax VMCS_GUEST_CS_LIMIT{bsl::to_umax(0x4802U)}; - /// @brief encoding for: guest_ss_limit - constexpr bsl::safe_uintmax VMCS_GUEST_SS_LIMIT{bsl::to_umax(0x4804U)}; - /// @brief encoding for: guest_ds_limit - constexpr bsl::safe_uintmax VMCS_GUEST_DS_LIMIT{bsl::to_umax(0x4806U)}; - /// @brief encoding for: guest_fs_limit - constexpr bsl::safe_uintmax VMCS_GUEST_FS_LIMIT{bsl::to_umax(0x4808U)}; - /// @brief encoding for: guest_gs_limit - constexpr bsl::safe_uintmax VMCS_GUEST_GS_LIMIT{bsl::to_umax(0x480AU)}; - /// @brief encoding for: guest_ldtr_limit - constexpr bsl::safe_uintmax VMCS_GUEST_LDTR_LIMIT{bsl::to_umax(0x480CU)}; - /// @brief encoding for: guest_tr_limit - constexpr bsl::safe_uintmax VMCS_GUEST_TR_LIMIT{bsl::to_umax(0x480EU)}; - /// @brief encoding for: guest_gdtr_limit - constexpr bsl::safe_uintmax VMCS_GUEST_GDTR_LIMIT{bsl::to_umax(0x4810U)}; - /// @brief encoding for: guest_idtr_limit - constexpr bsl::safe_uintmax VMCS_GUEST_IDTR_LIMIT{bsl::to_umax(0x4812U)}; - /// @brief encoding for: guest_es_access_rights - constexpr bsl::safe_uintmax VMCS_GUEST_ES_ACCESS_RIGHTS{bsl::to_umax(0x4814U)}; - /// @brief encoding for: guest_cs_access_rights - constexpr bsl::safe_uintmax VMCS_GUEST_CS_ACCESS_RIGHTS{bsl::to_umax(0x4816U)}; - /// @brief encoding for: guest_ss_access_rights - constexpr bsl::safe_uintmax VMCS_GUEST_SS_ACCESS_RIGHTS{bsl::to_umax(0x4818U)}; - /// @brief encoding for: guest_ds_access_rights - constexpr bsl::safe_uintmax VMCS_GUEST_DS_ACCESS_RIGHTS{bsl::to_umax(0x481AU)}; - /// @brief encoding for: guest_fs_access_rights - constexpr bsl::safe_uintmax VMCS_GUEST_FS_ACCESS_RIGHTS{bsl::to_umax(0x481CU)}; - /// @brief encoding for: guest_gs_access_rights - constexpr bsl::safe_uintmax VMCS_GUEST_GS_ACCESS_RIGHTS{bsl::to_umax(0x481EU)}; - /// @brief encoding for: guest_ldtr_access_rights - constexpr bsl::safe_uintmax VMCS_GUEST_LDTR_ACCESS_RIGHTS{bsl::to_umax(0x4820U)}; - /// @brief encoding for: guest_tr_access_rights - constexpr bsl::safe_uintmax VMCS_GUEST_TR_ACCESS_RIGHTS{bsl::to_umax(0x4822U)}; - /// @brief encoding for: guest_interruptibility_state - constexpr bsl::safe_uintmax VMCS_GUEST_INTERRUPTIBILITY_STATE{bsl::to_umax(0x4824U)}; - /// @brief encoding for: guest_activity_state - constexpr bsl::safe_uintmax VMCS_GUEST_ACTIVITY_STATE{bsl::to_umax(0x4826U)}; - /// @brief encoding for: guest_smbase - constexpr bsl::safe_uintmax VMCS_GUEST_SMBASE{bsl::to_umax(0x4828U)}; - /// @brief encoding for: guest_ia32_sysenter_cs - constexpr bsl::safe_uintmax VMCS_GUEST_IA32_SYSENTER_CS{bsl::to_umax(0x482AU)}; - /// @brief encoding for: vmx_preemption_timer_value - constexpr bsl::safe_uintmax VMCS_VMX_PREEMPTION_TIMER_VALUE{bsl::to_umax(0x482EU)}; - - /// @brief encoding for: host_ia32_sysenter_cs - constexpr bsl::safe_uintmax VMCS_HOST_IA32_SYSENTER_CS{bsl::to_umax(0x4C00U)}; - - /// @brief encoding for: cr0_guest_host_mask - constexpr bsl::safe_uintmax VMCS_CR0_GUEST_HOST_MASK{bsl::to_umax(0x6000U)}; - /// @brief encoding for: cr4_guest_host_mask - constexpr bsl::safe_uintmax VMCS_CR4_GUEST_HOST_MASK{bsl::to_umax(0x6002U)}; - /// @brief encoding for: cr0_read_shadow - constexpr bsl::safe_uintmax VMCS_CR0_READ_SHADOW{bsl::to_umax(0x6004U)}; - /// @brief encoding for: cr4_read_shadow - constexpr bsl::safe_uintmax VMCS_CR4_READ_SHADOW{bsl::to_umax(0x6006U)}; - /// @brief encoding for: cr3_target_value0 - constexpr bsl::safe_uintmax VMCS_CR3_TARGET_VALUE0{bsl::to_umax(0x6008U)}; - /// @brief encoding for: cr3_target_value1 - constexpr bsl::safe_uintmax VMCS_CR3_TARGET_VALUE1{bsl::to_umax(0x600AU)}; - /// @brief encoding for: cr3_target_value2 - constexpr bsl::safe_uintmax VMCS_CR3_TARGET_VALUE2{bsl::to_umax(0x600CU)}; - /// @brief encoding for: cr3_target_value3 - constexpr bsl::safe_uintmax VMCS_CR3_TARGET_VALUE3{bsl::to_umax(0x600EU)}; - - /// @brief encoding for: exit_qualification - constexpr bsl::safe_uintmax VMCS_EXIT_QUALIFICATION{bsl::to_umax(0x6400U)}; - /// @brief encoding for: io_rcx - constexpr bsl::safe_uintmax VMCS_IO_RCX{bsl::to_umax(0x6402U)}; - /// @brief encoding for: io_rsi - constexpr bsl::safe_uintmax VMCS_IO_RSI{bsl::to_umax(0x6404U)}; - /// @brief encoding for: io_rdi - constexpr bsl::safe_uintmax VMCS_IO_RDI{bsl::to_umax(0x6406U)}; - /// @brief encoding for: io_rip - constexpr bsl::safe_uintmax VMCS_IO_RIP{bsl::to_umax(0x6408U)}; - /// @brief encoding for: guest_linear_address - constexpr bsl::safe_uintmax VMCS_GUEST_LINEAR_ADDRESS{bsl::to_umax(0x640AU)}; - - /// @brief encoding for: guest_cr0 - constexpr bsl::safe_uintmax VMCS_GUEST_CR0{bsl::to_umax(0x6800U)}; - /// @brief encoding for: guest_cr3 - constexpr bsl::safe_uintmax VMCS_GUEST_CR3{bsl::to_umax(0x6802U)}; - /// @brief encoding for: guest_cr4 - constexpr bsl::safe_uintmax VMCS_GUEST_CR4{bsl::to_umax(0x6804U)}; - /// @brief encoding for: guest_es_base - constexpr bsl::safe_uintmax VMCS_GUEST_ES_BASE{bsl::to_umax(0x6806U)}; - /// @brief encoding for: guest_cs_base - constexpr bsl::safe_uintmax VMCS_GUEST_CS_BASE{bsl::to_umax(0x6808U)}; - /// @brief encoding for: guest_ss_base - constexpr bsl::safe_uintmax VMCS_GUEST_SS_BASE{bsl::to_umax(0x680AU)}; - /// @brief encoding for: guest_ds_base - constexpr bsl::safe_uintmax VMCS_GUEST_DS_BASE{bsl::to_umax(0x680CU)}; - /// @brief encoding for: guest_fs_base - constexpr bsl::safe_uintmax VMCS_GUEST_FS_BASE{bsl::to_umax(0x680EU)}; - /// @brief encoding for: guest_gs_base - constexpr bsl::safe_uintmax VMCS_GUEST_GS_BASE{bsl::to_umax(0x6810U)}; - /// @brief encoding for: guest_ldtr_base - constexpr bsl::safe_uintmax VMCS_GUEST_LDTR_BASE{bsl::to_umax(0x6812U)}; - /// @brief encoding for: guest_tr_base - constexpr bsl::safe_uintmax VMCS_GUEST_TR_BASE{bsl::to_umax(0x6814U)}; - /// @brief encoding for: guest_gdtr_base - constexpr bsl::safe_uintmax VMCS_GUEST_GDTR_BASE{bsl::to_umax(0x6816U)}; - /// @brief encoding for: guest_idtr_base - constexpr bsl::safe_uintmax VMCS_GUEST_IDTR_BASE{bsl::to_umax(0x6818U)}; - /// @brief encoding for: guest_dr7 - constexpr bsl::safe_uintmax VMCS_GUEST_DR7{bsl::to_umax(0x681AU)}; - /// @brief encoding for: guest_rsp - constexpr bsl::safe_uintmax VMCS_GUEST_RSP{bsl::to_umax(0x681CU)}; - /// @brief encoding for: guest_rip - constexpr bsl::safe_uintmax VMCS_GUEST_RIP{bsl::to_umax(0x681EU)}; - /// @brief encoding for: guest_rflags - constexpr bsl::safe_uintmax VMCS_GUEST_RFLAGS{bsl::to_umax(0x6820U)}; - /// @brief encoding for: guest_pending_debug_exceptions - constexpr bsl::safe_uintmax VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS{bsl::to_umax(0x6822U)}; - /// @brief encoding for: guest_ia32_sysenter_esp - constexpr bsl::safe_uintmax VMCS_GUEST_IA32_SYSENTER_ESP{bsl::to_umax(0x6824U)}; - /// @brief encoding for: guest_ia32_sysenter_eip - constexpr bsl::safe_uintmax VMCS_GUEST_IA32_SYSENTER_EIP{bsl::to_umax(0x6826U)}; - - /// @brief encoding for: host_cr0 - constexpr bsl::safe_uintmax VMCS_HOST_CR0{bsl::to_umax(0x6C00U)}; - /// @brief encoding for: host_cr3 - constexpr bsl::safe_uintmax VMCS_HOST_CR3{bsl::to_umax(0x6C02U)}; - /// @brief encoding for: host_cr4 - constexpr bsl::safe_uintmax VMCS_HOST_CR4{bsl::to_umax(0x6C04U)}; - /// @brief encoding for: host_fs_base - constexpr bsl::safe_uintmax VMCS_HOST_FS_BASE{bsl::to_umax(0x6C06U)}; - /// @brief encoding for: host_gs_base - constexpr bsl::safe_uintmax VMCS_HOST_GS_BASE{bsl::to_umax(0x6C08U)}; - /// @brief encoding for: host_tr_baseD - constexpr bsl::safe_uintmax VMCS_HOST_TR_BASE{bsl::to_umax(0x6C0AU)}; - /// @brief encoding for: host_gdtr_base - constexpr bsl::safe_uintmax VMCS_HOST_GDTR_BASE{bsl::to_umax(0x6C0CU)}; - /// @brief encoding for: host_idtr_base - constexpr bsl::safe_uintmax VMCS_HOST_IDTR_BASE{bsl::to_umax(0x6C0EU)}; - /// @brief encoding for: host_ia32_sysenter_esp - constexpr bsl::safe_uintmax VMCS_HOST_IA32_SYSENTER_ESP{bsl::to_umax(0x6C10U)}; - /// @brief encoding for: host_ia32_sysenter_eip - constexpr bsl::safe_uintmax VMCS_HOST_IA32_SYSENTER_EIP{bsl::to_umax(0x6C12U)}; - /// @brief encoding for: host_rsp - constexpr bsl::safe_uintmax VMCS_HOST_RSP{bsl::to_umax(0x6C14U)}; - /// @brief encoding for: host_rip - constexpr bsl::safe_uintmax VMCS_HOST_RIP{bsl::to_umax(0x6C16U)}; - - /// @struct mk::vmcs_t - /// - /// - /// @brief The following defines the structure of the VMCS used by - /// Intel's hypervisor extensions. - /// - struct vmcs_t final - { - /// @brief defines the revision ID - bsl::uint32 revision_id; - - /// @brief reserved - bsl::details::carray reserved; - }; - - namespace details - { - /// @brief defined the expected size of the pdt_t struct - constexpr bsl::safe_uintmax EXPECTED_VMCS_T_SIZE{bsl::to_umax(HYPERVISOR_PAGE_SIZE)}; - - /// Check to make sure the pdt_t is the right size. - static_assert(sizeof(vmcs_t) == EXPECTED_VMCS_T_SIZE); - } -} - -#pragma pack(pop) - -#endif diff --git a/kernel/src/x64/intel/vps_t.hpp b/kernel/src/x64/intel/vps_t.hpp index 058e6121..0bbb8890 100644 --- a/kernel/src/x64/intel/vps_t.hpp +++ b/kernel/src/x64/intel/vps_t.hpp @@ -25,10 +25,19 @@ #ifndef VPS_T_HPP #define VPS_T_HPP -#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include #include #include #include @@ -36,142 +45,137 @@ #include #include #include +#include namespace mk { /// @brief entry point prototype extern "C" void intrinsic_vmexit(void) noexcept; - /// @brief defines the value of an invalid VPSID - constexpr bsl::safe_uint16 INVALID_VPSID{bsl::to_u16(0xFFFFU)}; - - namespace details - { - /// @brief defines the IA32_VMX_BASIC MSR - constexpr bsl::safe_uint32 IA32_VMX_BASIC{bsl::to_u32(0x480U)}; - /// @brief defines the IA32_PAT MSR - constexpr bsl::safe_uint32 IA32_PAT{bsl::to_u32(0x277U)}; - /// @brief defines the IA32_SYSENTER_CS MSR - constexpr bsl::safe_uint32 IA32_SYSENTER_CS{bsl::to_u32(0x174U)}; - /// @brief defines the IA32_SYSENTER_ESP MSR - constexpr bsl::safe_uint32 IA32_SYSENTER_ESP{bsl::to_u32(0x175U)}; - /// @brief defines the IA32_SYSENTER_EIP MSR - constexpr bsl::safe_uint32 IA32_SYSENTER_EIP{bsl::to_u32(0x176U)}; - /// @brief defines the IA32_EFER MSR - constexpr bsl::safe_uint32 IA32_EFER{bsl::to_u32(0xC0000080U)}; - /// @brief defines the IA32_STAR MSR - constexpr bsl::safe_uint32 IA32_STAR{bsl::to_u32(0xC0000081U)}; - /// @brief defines the IA32_LSTAR MSR - constexpr bsl::safe_uint32 IA32_LSTAR{bsl::to_u32(0xC0000082U)}; - /// @brief defines the IA32_CSTAR MSR - constexpr bsl::safe_uint32 IA32_CSTAR{bsl::to_u32(0xC0000083U)}; - /// @brief defines the IA32_FMASK MSR - constexpr bsl::safe_uint32 IA32_FMASK{bsl::to_u32(0xC0000084U)}; - /// @brief defines the IA32_FS_BASE MSR - constexpr bsl::safe_uint32 IA32_FS_BASE{bsl::to_u32(0xC0000100U)}; - /// @brief defines the IA32_GS_BASE MSR - constexpr bsl::safe_uint32 IA32_GS_BASE{bsl::to_u32(0xC0000101U)}; - /// @brief defines the IA32_KERNEL_GS_BASE MSR - constexpr bsl::safe_uint32 IA32_KERNEL_GS_BASE{bsl::to_u32(0xC0000102U)}; - } + /// @brief defines the IA32_VMX_BASIC MSR + constexpr auto IA32_VMX_BASIC{0x480_u32}; + /// @brief defines the IA32_PAT MSR + constexpr auto IA32_PAT{0x277_u32}; + /// @brief defines the IA32_SYSENTER_CS MSR + constexpr auto IA32_SYSENTER_CS{0x174_u32}; + /// @brief defines the IA32_SYSENTER_ESP MSR + constexpr auto IA32_SYSENTER_ESP{0x175_u32}; + /// @brief defines the IA32_SYSENTER_EIP MSR + constexpr auto IA32_SYSENTER_EIP{0x176_u32}; + /// @brief defines the IA32_EFER MSR + constexpr auto IA32_EFER{0xC0000080_u32}; + /// @brief defines the IA32_STAR MSR + constexpr auto IA32_STAR{0xC0000081_u32}; + /// @brief defines the IA32_LSTAR MSR + constexpr auto IA32_LSTAR{0xC0000082_u32}; + /// @brief defines the IA32_CSTAR MSR + constexpr auto IA32_CSTAR{0xC0000083_u32}; + /// @brief defines the IA32_FMASK MSR + constexpr auto IA32_FMASK{0xC0000084_u32}; + /// @brief defines the IA32_FS_BASE MSR + constexpr auto IA32_FS_BASE{0xC0000100_u32}; + /// @brief defines the IA32_GS_BASE MSR + constexpr auto IA32_GS_BASE{0xC0000101_u32}; + /// @brief defines the IA32_KERNEL_GS_BASE MSR + constexpr auto IA32_KERNEL_GS_BASE{0xC0000102_u32}; /// @class mk::vps_t /// /// - /// @brief TODO + /// @brief Defines the microkernel's notion of a VPS. /// - /// - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use - /// - template class vps_t final { - /// @brief stores true if initialized() has been executed - bool m_initialized{}; - /// @brief stores a reference to the intrinsics to use - INTRINSIC_CONCEPT *m_intrinsic{}; - /// @brief stores a reference to the page pool to use - PAGE_POOL_CONCEPT *m_page_pool{}; - /// @brief stores the ID associated with this vps_t - bsl::safe_uint16 m_id{bsl::safe_uint16::zero(true)}; - /// @brief stores the next vps_t in the vp_pool_t linked list - vps_t *m_next{}; + /// @brief stores the ID associated with this vp_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + /// @brief stores whether or not this vp_t is allocated. + allocated_status_t m_allocated{allocated_status_t::deallocated}; + /// @brief stores the ID of the VP this vps_t is assigned to + bsl::safe_uint16 m_assigned_vpid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vp_t is assigned to + bsl::safe_uint16 m_assigned_ppid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vp_t is active on + bsl::safe_uint16 m_active_ppid{bsl::safe_uint16::failure()}; - /// @brief stores true if initialized() has been executed - bool m_allocated{}; /// @brief stores a pointer to the guest vmcs being managed by this VPS vmcs_t *m_vmcs{}; /// @brief stores the physical address of the guest vmcs - bsl::safe_uintmax m_vmcs_phys{bsl::safe_uintmax::zero(true)}; + bsl::safe_uintmax m_vmcs_phys{bsl::safe_uintmax::failure()}; /// @brief stores the rest of the state the vmcs doesn't vmcs_missing_registers_t m_vmcs_missing_registers{}; + /// @brief stores the general purpose registers + general_purpose_regs_t m_gprs{}; /// /// @brief Stores the provided ES segment state info in the VPS. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set the VPS to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - set_es_segment_descriptor(STATE_SAVE_CONCEPT const *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + set_es_segment_descriptor( + intrinsic_t &intrinsic, loader::state_save_t const &state) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (bsl::ZERO_U16 == state->es_selector) { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_ES_SELECTOR, bsl::ZERO_U16); - if (bsl::unlikely(!ret)) { + constexpr auto unused{0_u16}; + if (unused == state.es_selector) { + ret = intrinsic.vmwrite16(VMCS_GUEST_ES_SELECTOR, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_ES_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_ES_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_ES_LIMIT, bsl::ZERO_U32); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_ES_LIMIT, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_ES_BASE, bsl::ZERO_U64); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_ES_BASE, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } else { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_ES_SELECTOR, state->es_selector); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_GUEST_ES_SELECTOR, state.es_selector); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32( - VMCS_GUEST_ES_ACCESS_RIGHTS, bsl::to_u32(state->es_attrib)); - if (bsl::unlikely(!ret)) { + ret = + intrinsic.vmwrite32(VMCS_GUEST_ES_ACCESS_RIGHTS, bsl::to_u32(state.es_attrib)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_ES_LIMIT, state->es_limit); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_ES_LIMIT, state.es_limit); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_ES_BASE, state->es_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_ES_BASE, state.es_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } return bsl::errc_success; @@ -181,67 +185,72 @@ namespace mk /// @brief Stores the provided CS segment state info in the VPS. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set the VPS to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - set_cs_segment_descriptor(STATE_SAVE_CONCEPT const *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + set_cs_segment_descriptor( + intrinsic_t &intrinsic, loader::state_save_t const &state) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (bsl::ZERO_U16 == state->cs_selector) { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_CS_SELECTOR, bsl::ZERO_U16); - if (bsl::unlikely(!ret)) { + constexpr auto unused{0_u16}; + if (unused == state.cs_selector) { + ret = intrinsic.vmwrite16(VMCS_GUEST_CS_SELECTOR, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_CS_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_CS_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_CS_LIMIT, bsl::ZERO_U32); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_CS_LIMIT, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_CS_BASE, bsl::ZERO_U64); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_CS_BASE, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } else { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_CS_SELECTOR, state->cs_selector); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_GUEST_CS_SELECTOR, state.cs_selector); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32( - VMCS_GUEST_CS_ACCESS_RIGHTS, bsl::to_u32(state->cs_attrib)); - if (bsl::unlikely(!ret)) { + ret = + intrinsic.vmwrite32(VMCS_GUEST_CS_ACCESS_RIGHTS, bsl::to_u32(state.cs_attrib)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_CS_LIMIT, state->cs_limit); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_CS_LIMIT, state.cs_limit); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_CS_BASE, state->cs_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_CS_BASE, state.cs_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } return bsl::errc_success; @@ -251,67 +260,72 @@ namespace mk /// @brief Stores the provided SS segment state info in the VPS. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set the VPS to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - set_ss_segment_descriptor(STATE_SAVE_CONCEPT const *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + set_ss_segment_descriptor( + intrinsic_t &intrinsic, loader::state_save_t const &state) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (bsl::ZERO_U16 == state->ss_selector) { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_SS_SELECTOR, bsl::ZERO_U16); - if (bsl::unlikely(!ret)) { + constexpr auto unused{0_u16}; + if (unused == state.ss_selector) { + ret = intrinsic.vmwrite16(VMCS_GUEST_SS_SELECTOR, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_SS_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_SS_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_SS_LIMIT, bsl::ZERO_U32); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_SS_LIMIT, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_SS_BASE, bsl::ZERO_U64); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_SS_BASE, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } else { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_SS_SELECTOR, state->ss_selector); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_GUEST_SS_SELECTOR, state.ss_selector); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32( - VMCS_GUEST_SS_ACCESS_RIGHTS, bsl::to_u32(state->ss_attrib)); - if (bsl::unlikely(!ret)) { + ret = + intrinsic.vmwrite32(VMCS_GUEST_SS_ACCESS_RIGHTS, bsl::to_u32(state.ss_attrib)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_SS_LIMIT, state->ss_limit); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_SS_LIMIT, state.ss_limit); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_SS_BASE, state->ss_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_SS_BASE, state.ss_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } return bsl::errc_success; @@ -321,67 +335,72 @@ namespace mk /// @brief Stores the provided DS segment state info in the VPS. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set the VPS to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - set_ds_segment_descriptor(STATE_SAVE_CONCEPT const *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + set_ds_segment_descriptor( + intrinsic_t &intrinsic, loader::state_save_t const &state) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (bsl::ZERO_U16 == state->ds_selector) { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_DS_SELECTOR, bsl::ZERO_U16); - if (bsl::unlikely(!ret)) { + constexpr auto unused{0_u16}; + if (unused == state.ds_selector) { + ret = intrinsic.vmwrite16(VMCS_GUEST_DS_SELECTOR, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_DS_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_DS_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_DS_LIMIT, bsl::ZERO_U32); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_DS_LIMIT, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_DS_BASE, bsl::ZERO_U64); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_DS_BASE, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } else { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_DS_SELECTOR, state->ds_selector); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_GUEST_DS_SELECTOR, state.ds_selector); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32( - VMCS_GUEST_DS_ACCESS_RIGHTS, bsl::to_u32(state->ds_attrib)); - if (bsl::unlikely(!ret)) { + ret = + intrinsic.vmwrite32(VMCS_GUEST_DS_ACCESS_RIGHTS, bsl::to_u32(state.ds_attrib)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_DS_LIMIT, state->ds_limit); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_DS_LIMIT, state.ds_limit); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_DS_BASE, state->ds_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_DS_BASE, state.ds_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } return bsl::errc_success; @@ -391,67 +410,72 @@ namespace mk /// @brief Stores the provided FS segment state info in the VPS. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set the VPS to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - set_fs_segment_descriptor(STATE_SAVE_CONCEPT const *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + set_fs_segment_descriptor( + intrinsic_t &intrinsic, loader::state_save_t const &state) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (bsl::ZERO_U16 == state->fs_selector) { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_FS_SELECTOR, bsl::ZERO_U16); - if (bsl::unlikely(!ret)) { + constexpr auto unused{0_u16}; + if (unused == state.fs_selector) { + ret = intrinsic.vmwrite16(VMCS_GUEST_FS_SELECTOR, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_FS_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_FS_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_FS_LIMIT, bsl::ZERO_U32); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_FS_LIMIT, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_FS_BASE, bsl::ZERO_U64); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_FS_BASE, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } else { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_FS_SELECTOR, state->fs_selector); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_GUEST_FS_SELECTOR, state.fs_selector); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32( - VMCS_GUEST_FS_ACCESS_RIGHTS, bsl::to_u32(state->fs_attrib)); - if (bsl::unlikely(!ret)) { + ret = + intrinsic.vmwrite32(VMCS_GUEST_FS_ACCESS_RIGHTS, bsl::to_u32(state.fs_attrib)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_FS_LIMIT, state->fs_limit); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_FS_LIMIT, state.fs_limit); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_FS_BASE, state->fs_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_FS_BASE, state.fs_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } return bsl::errc_success; @@ -461,67 +485,72 @@ namespace mk /// @brief Stores the provided GS segment state info in the VPS. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set the VPS to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - set_gs_segment_descriptor(STATE_SAVE_CONCEPT const *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + set_gs_segment_descriptor( + intrinsic_t &intrinsic, loader::state_save_t const &state) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (bsl::ZERO_U16 == state->gs_selector) { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_GS_SELECTOR, bsl::ZERO_U16); - if (bsl::unlikely(!ret)) { + constexpr auto unused{0_u16}; + if (unused == state.gs_selector) { + ret = intrinsic.vmwrite16(VMCS_GUEST_GS_SELECTOR, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_GS_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_GS_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_GS_LIMIT, bsl::ZERO_U32); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_GS_LIMIT, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_GS_BASE, bsl::ZERO_U64); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_GS_BASE, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } else { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_GS_SELECTOR, state->gs_selector); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_GUEST_GS_SELECTOR, state.gs_selector); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32( - VMCS_GUEST_GS_ACCESS_RIGHTS, bsl::to_u32(state->gs_attrib)); - if (bsl::unlikely(!ret)) { + ret = + intrinsic.vmwrite32(VMCS_GUEST_GS_ACCESS_RIGHTS, bsl::to_u32(state.gs_attrib)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_GS_LIMIT, state->gs_limit); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_GS_LIMIT, state.gs_limit); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_GS_BASE, state->gs_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_GS_BASE, state.gs_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } return bsl::errc_success; @@ -531,68 +560,72 @@ namespace mk /// @brief Stores the provided LDTR segment state info in the VPS. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set the VPS to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - set_ldtr_segment_descriptor(STATE_SAVE_CONCEPT const *const state) &noexcept - -> bsl::errc_type + [[nodiscard]] static constexpr auto + set_ldtr_segment_descriptor( + intrinsic_t &intrinsic, loader::state_save_t const &state) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (bsl::ZERO_U16 == state->ldtr_selector) { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_LDTR_SELECTOR, bsl::ZERO_U16); - if (bsl::unlikely(!ret)) { + constexpr auto unused{0_u16}; + if (unused == state.ldtr_selector) { + ret = intrinsic.vmwrite16(VMCS_GUEST_LDTR_SELECTOR, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_LDTR_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_LDTR_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_LDTR_LIMIT, bsl::ZERO_U32); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_LDTR_LIMIT, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_LDTR_BASE, bsl::ZERO_U64); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_LDTR_BASE, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } else { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_LDTR_SELECTOR, state->ldtr_selector); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_GUEST_LDTR_SELECTOR, state.ldtr_selector); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32( - VMCS_GUEST_LDTR_ACCESS_RIGHTS, bsl::to_u32(state->ldtr_attrib)); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32( + VMCS_GUEST_LDTR_ACCESS_RIGHTS, bsl::to_u32(state.ldtr_attrib)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_LDTR_LIMIT, state->ldtr_limit); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_LDTR_LIMIT, state.ldtr_limit); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_LDTR_BASE, state->ldtr_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_LDTR_BASE, state.ldtr_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } return bsl::errc_success; @@ -602,67 +635,72 @@ namespace mk /// @brief Stores the provided TR segment state info in the VPS. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set the VPS to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - set_tr_segment_descriptor(STATE_SAVE_CONCEPT const *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + set_tr_segment_descriptor( + intrinsic_t &intrinsic, loader::state_save_t const &state) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (bsl::ZERO_U16 == state->tr_selector) { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_TR_SELECTOR, bsl::ZERO_U16); - if (bsl::unlikely(!ret)) { + constexpr auto unused{0_u16}; + if (unused == state.tr_selector) { + ret = intrinsic.vmwrite16(VMCS_GUEST_TR_SELECTOR, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_TR_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_TR_ACCESS_RIGHTS, VMCS_UNUSABLE_SEGMENT); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_TR_LIMIT, bsl::ZERO_U32); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_TR_LIMIT, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_TR_BASE, bsl::ZERO_U64); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_TR_BASE, {}); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } else { - ret = m_intrinsic->vmwrite16(VMCS_GUEST_TR_SELECTOR, state->tr_selector); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_GUEST_TR_SELECTOR, state.tr_selector); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32( - VMCS_GUEST_TR_ACCESS_RIGHTS, bsl::to_u32(state->tr_attrib)); - if (bsl::unlikely(!ret)) { + ret = + intrinsic.vmwrite32(VMCS_GUEST_TR_ACCESS_RIGHTS, bsl::to_u32(state.tr_attrib)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite32(VMCS_GUEST_TR_LIMIT, state->tr_limit); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite32(VMCS_GUEST_TR_LIMIT, state.tr_limit); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_TR_BASE, state->tr_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_TR_BASE, state.tr_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } + + bsl::touch(); } return bsl::errc_success; @@ -673,14 +711,14 @@ namespace mk /// state save. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - get_es_segment_descriptor(STATE_SAVE_CONCEPT *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + get_es_segment_descriptor(intrinsic_t &intrinsic, loader::state_save_t &state) noexcept + -> bsl::errc_type { bsl::errc_type ret{}; bsl::safe_uint16 selector{}; @@ -688,41 +726,41 @@ namespace mk bsl::safe_uint32 limit{}; bsl::safe_uint64 base{}; - ret = m_intrinsic->vmread16(VMCS_GUEST_ES_SELECTOR, selector.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread16(VMCS_GUEST_ES_SELECTOR, selector.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_ES_ACCESS_RIGHTS, access_rights.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_ES_ACCESS_RIGHTS, access_rights.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_ES_LIMIT, limit.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_ES_LIMIT, limit.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_ES_BASE, base.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_ES_BASE, base.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } if (VMCS_UNUSABLE_SEGMENT == access_rights) { - state->es_selector = bsl::ZERO_U16.get(); - state->es_attrib = bsl::ZERO_U16.get(); - state->es_limit = bsl::ZERO_U32.get(); - state->es_base = bsl::ZERO_U64.get(); + state.es_selector = {}; + state.es_attrib = {}; + state.es_limit = {}; + state.es_base = {}; } else { - state->es_selector = selector.get(); - state->es_attrib = bsl::to_u16(access_rights).get(); - state->es_limit = limit.get(); - state->es_base = base.get(); + state.es_selector = selector.get(); + state.es_attrib = bsl::to_u16(access_rights).get(); + state.es_limit = limit.get(); + state.es_base = base.get(); } return bsl::errc_success; @@ -733,14 +771,14 @@ namespace mk /// state save. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - get_cs_segment_descriptor(STATE_SAVE_CONCEPT *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + get_cs_segment_descriptor(intrinsic_t &intrinsic, loader::state_save_t &state) noexcept + -> bsl::errc_type { bsl::errc_type ret{}; bsl::safe_uint16 selector{}; @@ -748,41 +786,41 @@ namespace mk bsl::safe_uint32 limit{}; bsl::safe_uint64 base{}; - ret = m_intrinsic->vmread16(VMCS_GUEST_CS_SELECTOR, selector.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread16(VMCS_GUEST_CS_SELECTOR, selector.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_CS_ACCESS_RIGHTS, access_rights.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_CS_ACCESS_RIGHTS, access_rights.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_CS_LIMIT, limit.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_CS_LIMIT, limit.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_CS_BASE, base.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_CS_BASE, base.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } if (VMCS_UNUSABLE_SEGMENT == access_rights) { - state->cs_selector = bsl::ZERO_U16.get(); - state->cs_attrib = bsl::ZERO_U16.get(); - state->cs_limit = bsl::ZERO_U32.get(); - state->cs_base = bsl::ZERO_U64.get(); + state.cs_selector = {}; + state.cs_attrib = {}; + state.cs_limit = {}; + state.cs_base = {}; } else { - state->cs_selector = selector.get(); - state->cs_attrib = bsl::to_u16(access_rights).get(); - state->cs_limit = limit.get(); - state->cs_base = base.get(); + state.cs_selector = selector.get(); + state.cs_attrib = bsl::to_u16(access_rights).get(); + state.cs_limit = limit.get(); + state.cs_base = base.get(); } return bsl::errc_success; @@ -793,14 +831,14 @@ namespace mk /// state save. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - get_ss_segment_descriptor(STATE_SAVE_CONCEPT *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + get_ss_segment_descriptor(intrinsic_t &intrinsic, loader::state_save_t &state) noexcept + -> bsl::errc_type { bsl::errc_type ret{}; bsl::safe_uint16 selector{}; @@ -808,41 +846,41 @@ namespace mk bsl::safe_uint32 limit{}; bsl::safe_uint64 base{}; - ret = m_intrinsic->vmread16(VMCS_GUEST_SS_SELECTOR, selector.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread16(VMCS_GUEST_SS_SELECTOR, selector.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_SS_ACCESS_RIGHTS, access_rights.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_SS_ACCESS_RIGHTS, access_rights.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_SS_LIMIT, limit.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_SS_LIMIT, limit.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_SS_BASE, base.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_SS_BASE, base.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } if (VMCS_UNUSABLE_SEGMENT == access_rights) { - state->ss_selector = bsl::ZERO_U16.get(); - state->ss_attrib = bsl::ZERO_U16.get(); - state->ss_limit = bsl::ZERO_U32.get(); - state->ss_base = bsl::ZERO_U64.get(); + state.ss_selector = {}; + state.ss_attrib = {}; + state.ss_limit = {}; + state.ss_base = {}; } else { - state->ss_selector = selector.get(); - state->ss_attrib = bsl::to_u16(access_rights).get(); - state->ss_limit = limit.get(); - state->ss_base = base.get(); + state.ss_selector = selector.get(); + state.ss_attrib = bsl::to_u16(access_rights).get(); + state.ss_limit = limit.get(); + state.ss_base = base.get(); } return bsl::errc_success; @@ -853,14 +891,14 @@ namespace mk /// state save. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - get_ds_segment_descriptor(STATE_SAVE_CONCEPT *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + get_ds_segment_descriptor(intrinsic_t &intrinsic, loader::state_save_t &state) noexcept + -> bsl::errc_type { bsl::errc_type ret{}; bsl::safe_uint16 selector{}; @@ -868,41 +906,41 @@ namespace mk bsl::safe_uint32 limit{}; bsl::safe_uint64 base{}; - ret = m_intrinsic->vmread16(VMCS_GUEST_DS_SELECTOR, selector.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread16(VMCS_GUEST_DS_SELECTOR, selector.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_DS_ACCESS_RIGHTS, access_rights.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_DS_ACCESS_RIGHTS, access_rights.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_DS_LIMIT, limit.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_DS_LIMIT, limit.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_DS_BASE, base.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_DS_BASE, base.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } if (VMCS_UNUSABLE_SEGMENT == access_rights) { - state->ds_selector = bsl::ZERO_U16.get(); - state->ds_attrib = bsl::ZERO_U16.get(); - state->ds_limit = bsl::ZERO_U32.get(); - state->ds_base = bsl::ZERO_U64.get(); + state.ds_selector = {}; + state.ds_attrib = {}; + state.ds_limit = {}; + state.ds_base = {}; } else { - state->ds_selector = selector.get(); - state->ds_attrib = bsl::to_u16(access_rights).get(); - state->ds_limit = limit.get(); - state->ds_base = base.get(); + state.ds_selector = selector.get(); + state.ds_attrib = bsl::to_u16(access_rights).get(); + state.ds_limit = limit.get(); + state.ds_base = base.get(); } return bsl::errc_success; @@ -913,14 +951,14 @@ namespace mk /// state save. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - get_gs_segment_descriptor(STATE_SAVE_CONCEPT *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + get_gs_segment_descriptor(intrinsic_t &intrinsic, loader::state_save_t &state) noexcept + -> bsl::errc_type { bsl::errc_type ret{}; bsl::safe_uint16 selector{}; @@ -928,41 +966,41 @@ namespace mk bsl::safe_uint32 limit{}; bsl::safe_uint64 base{}; - ret = m_intrinsic->vmread16(VMCS_GUEST_GS_SELECTOR, selector.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread16(VMCS_GUEST_GS_SELECTOR, selector.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_GS_ACCESS_RIGHTS, access_rights.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_GS_ACCESS_RIGHTS, access_rights.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_GS_LIMIT, limit.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_GS_LIMIT, limit.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_GS_BASE, base.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_GS_BASE, base.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } if (VMCS_UNUSABLE_SEGMENT == access_rights) { - state->gs_selector = bsl::ZERO_U16.get(); - state->gs_attrib = bsl::ZERO_U16.get(); - state->gs_limit = bsl::ZERO_U32.get(); - state->gs_base = bsl::ZERO_U64.get(); + state.gs_selector = {}; + state.gs_attrib = {}; + state.gs_limit = {}; + state.gs_base = {}; } else { - state->gs_selector = selector.get(); - state->gs_attrib = bsl::to_u16(access_rights).get(); - state->gs_limit = limit.get(); - state->gs_base = base.get(); + state.gs_selector = selector.get(); + state.gs_attrib = bsl::to_u16(access_rights).get(); + state.gs_limit = limit.get(); + state.gs_base = base.get(); } return bsl::errc_success; @@ -973,14 +1011,14 @@ namespace mk /// state save. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - get_fs_segment_descriptor(STATE_SAVE_CONCEPT *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + get_fs_segment_descriptor(intrinsic_t &intrinsic, loader::state_save_t &state) noexcept + -> bsl::errc_type { bsl::errc_type ret{}; bsl::safe_uint16 selector{}; @@ -988,41 +1026,41 @@ namespace mk bsl::safe_uint32 limit{}; bsl::safe_uint64 base{}; - ret = m_intrinsic->vmread16(VMCS_GUEST_FS_SELECTOR, selector.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread16(VMCS_GUEST_FS_SELECTOR, selector.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_FS_ACCESS_RIGHTS, access_rights.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_FS_ACCESS_RIGHTS, access_rights.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_FS_LIMIT, limit.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_FS_LIMIT, limit.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_FS_BASE, base.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_FS_BASE, base.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } if (VMCS_UNUSABLE_SEGMENT == access_rights) { - state->fs_selector = bsl::ZERO_U16.get(); - state->fs_attrib = bsl::ZERO_U16.get(); - state->fs_limit = bsl::ZERO_U32.get(); - state->fs_base = bsl::ZERO_U64.get(); + state.fs_selector = {}; + state.fs_attrib = {}; + state.fs_limit = {}; + state.fs_base = {}; } else { - state->fs_selector = selector.get(); - state->fs_attrib = bsl::to_u16(access_rights).get(); - state->fs_limit = limit.get(); - state->fs_base = base.get(); + state.fs_selector = selector.get(); + state.fs_attrib = bsl::to_u16(access_rights).get(); + state.fs_limit = limit.get(); + state.fs_base = base.get(); } return bsl::errc_success; @@ -1033,14 +1071,14 @@ namespace mk /// state save. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - get_ldtr_segment_descriptor(STATE_SAVE_CONCEPT *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + get_ldtr_segment_descriptor(intrinsic_t &intrinsic, loader::state_save_t &state) noexcept + -> bsl::errc_type { bsl::errc_type ret{}; bsl::safe_uint16 selector{}; @@ -1048,41 +1086,41 @@ namespace mk bsl::safe_uint32 limit{}; bsl::safe_uint64 base{}; - ret = m_intrinsic->vmread16(VMCS_GUEST_LDTR_SELECTOR, selector.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread16(VMCS_GUEST_LDTR_SELECTOR, selector.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_LDTR_ACCESS_RIGHTS, access_rights.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_LDTR_ACCESS_RIGHTS, access_rights.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_LDTR_LIMIT, limit.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_LDTR_LIMIT, limit.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_LDTR_BASE, base.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_LDTR_BASE, base.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } if (VMCS_UNUSABLE_SEGMENT == access_rights) { - state->ldtr_selector = bsl::ZERO_U16.get(); - state->ldtr_attrib = bsl::ZERO_U16.get(); - state->ldtr_limit = bsl::ZERO_U32.get(); - state->ldtr_base = bsl::ZERO_U64.get(); + state.ldtr_selector = {}; + state.ldtr_attrib = {}; + state.ldtr_limit = {}; + state.ldtr_base = {}; } else { - state->ldtr_selector = selector.get(); - state->ldtr_attrib = bsl::to_u16(access_rights).get(); - state->ldtr_limit = limit.get(); - state->ldtr_base = base.get(); + state.ldtr_selector = selector.get(); + state.ldtr_attrib = bsl::to_u16(access_rights).get(); + state.ldtr_limit = limit.get(); + state.ldtr_base = base.get(); } return bsl::errc_success; @@ -1093,14 +1131,14 @@ namespace mk /// state save. /// /// - /// @tparam STATE_SAVE_CONCEPT the type of state save to use + /// @param intrinsic the intrinsics to use /// @param state the state to set /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template - [[nodiscard]] constexpr auto - get_tr_segment_descriptor(STATE_SAVE_CONCEPT *const state) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + get_tr_segment_descriptor(intrinsic_t &intrinsic, loader::state_save_t &state) noexcept + -> bsl::errc_type { bsl::errc_type ret{}; bsl::safe_uint16 selector{}; @@ -1108,41 +1146,41 @@ namespace mk bsl::safe_uint32 limit{}; bsl::safe_uint64 base{}; - ret = m_intrinsic->vmread16(VMCS_GUEST_TR_SELECTOR, selector.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread16(VMCS_GUEST_TR_SELECTOR, selector.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_TR_ACCESS_RIGHTS, access_rights.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_TR_ACCESS_RIGHTS, access_rights.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread32(VMCS_GUEST_TR_LIMIT, limit.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread32(VMCS_GUEST_TR_LIMIT, limit.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_TR_BASE, base.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_TR_BASE, base.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } if (VMCS_UNUSABLE_SEGMENT == access_rights) { - state->tr_selector = bsl::ZERO_U16.get(); - state->tr_attrib = bsl::ZERO_U16.get(); - state->tr_limit = bsl::ZERO_U32.get(); - state->tr_base = bsl::ZERO_U64.get(); + state.tr_selector = {}; + state.tr_attrib = {}; + state.tr_limit = {}; + state.tr_base = {}; } else { - state->tr_selector = selector.get(); - state->tr_attrib = bsl::to_u16(access_rights).get(); - state->tr_limit = limit.get(); - state->tr_base = base.get(); + state.tr_selector = selector.get(); + state.tr_attrib = bsl::to_u16(access_rights).get(); + state.tr_limit = limit.get(); + state.tr_base = base.get(); } return bsl::errc_success; @@ -1152,29 +1190,28 @@ namespace mk /// @brief Ensures that this VPS is loaded /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - ensure_this_vps_is_loaded(TLS_CONCEPT &tls) noexcept -> bsl::errc_type + ensure_this_vps_is_loaded(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (this == tls.loaded_vps) { + if (m_id == tls.loaded_vpsid) { return bsl::errc_success; } - ret = m_intrinsic->vmload(&m_vmcs_phys); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmload(&m_vmcs_phys); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - tls.loaded_vps = this; - return bsl::errc_success; + tls.loaded_vpsid = m_id.get(); + return ret; } /// @@ -1185,286 +1222,313 @@ namespace mk /// microkernel completes it's bootstrapping process. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - init_vmcs(TLS_CONCEPT &tls) noexcept -> bsl::errc_type + init_vmcs(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { bsl::errc_type ret{}; auto *const state{tls.mk_state}; - m_vmcs->revision_id = - bsl::to_u32_unsafe(m_intrinsic->rdmsr(details::IA32_VMX_BASIC)).get(); - - if (bsl::unlikely(!this->ensure_this_vps_is_loaded(tls))) { + auto const revision_id{intrinsic.rdmsr(IA32_VMX_BASIC)}; + if (bsl::unlikely_assert(!revision_id)) { bsl::print() << bsl::here(); return bsl::errc_failure; } - ret = m_intrinsic->vmwrite16(VMCS_HOST_ES_SELECTOR, m_intrinsic->es_selector()); - if (bsl::unlikely(!ret)) { + m_vmcs->revision_id = bsl::to_u32_unsafe(revision_id).get(); + + ret = this->ensure_this_vps_is_loaded(tls, intrinsic); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite16(VMCS_HOST_CS_SELECTOR, m_intrinsic->cs_selector()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_HOST_ES_SELECTOR, intrinsic.es_selector()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite16(VMCS_HOST_SS_SELECTOR, m_intrinsic->ss_selector()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_HOST_CS_SELECTOR, intrinsic.cs_selector()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite16(VMCS_HOST_DS_SELECTOR, m_intrinsic->ds_selector()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_HOST_SS_SELECTOR, intrinsic.ss_selector()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite16(VMCS_HOST_FS_SELECTOR, m_intrinsic->fs_selector()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_HOST_DS_SELECTOR, intrinsic.ds_selector()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite16(VMCS_HOST_GS_SELECTOR, m_intrinsic->gs_selector()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_HOST_FS_SELECTOR, intrinsic.fs_selector()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite16(VMCS_HOST_TR_SELECTOR, m_intrinsic->tr_selector()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_HOST_GS_SELECTOR, intrinsic.gs_selector()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_HOST_IA32_PAT, m_intrinsic->rdmsr(details::IA32_PAT)); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite16(VMCS_HOST_TR_SELECTOR, intrinsic.tr_selector()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; + } + + ret = intrinsic.vmwrite64(VMCS_HOST_IA32_PAT, intrinsic.rdmsr(IA32_PAT)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + ret = intrinsic.vmwrite64(VMCS_HOST_IA32_EFER, intrinsic.rdmsr(IA32_EFER)); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; } ret = - m_intrinsic->vmwrite64(VMCS_HOST_IA32_EFER, m_intrinsic->rdmsr(details::IA32_EFER)); - if (bsl::unlikely(!ret)) { + intrinsic.vmwrite64(VMCS_HOST_IA32_SYSENTER_CS, intrinsic.rdmsr(IA32_SYSENTER_CS)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64( - VMCS_HOST_IA32_SYSENTER_CS, m_intrinsic->rdmsr(details::IA32_SYSENTER_CS)); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_HOST_CR0, intrinsic.cr0()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_HOST_CR0, m_intrinsic->cr0()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_HOST_CR3, intrinsic.cr3()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_HOST_CR3, m_intrinsic->cr3()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_HOST_CR4, intrinsic.cr4()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_HOST_CR4, m_intrinsic->cr4()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_HOST_FS_BASE, intrinsic.rdmsr(IA32_FS_BASE)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64( - VMCS_HOST_FS_BASE, m_intrinsic->rdmsr(details::IA32_FS_BASE)); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_HOST_GS_BASE, intrinsic.rdmsr(IA32_GS_BASE)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64( - VMCS_HOST_GS_BASE, m_intrinsic->rdmsr(details::IA32_GS_BASE)); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_HOST_TR_BASE, state->tr_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_HOST_TR_BASE, state->tr_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_HOST_GDTR_BASE, bsl::to_umax(state->gdtr.base)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_HOST_GDTR_BASE, bsl::to_umax(state->gdtr.base)); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_HOST_IDTR_BASE, bsl::to_umax(state->idtr.base)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_HOST_IDTR_BASE, bsl::to_umax(state->idtr.base)); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64( + VMCS_HOST_IA32_SYSENTER_ESP, intrinsic.rdmsr(IA32_SYSENTER_ESP)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64( - VMCS_HOST_IA32_SYSENTER_ESP, m_intrinsic->rdmsr(details::IA32_SYSENTER_ESP)); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64( + VMCS_HOST_IA32_SYSENTER_EIP, intrinsic.rdmsr(IA32_SYSENTER_EIP)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64( - VMCS_HOST_IA32_SYSENTER_EIP, m_intrinsic->rdmsr(details::IA32_SYSENTER_EIP)); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_HOST_RIP, bsl::to_umax(&intrinsic_vmexit)); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_HOST_RIP, bsl::to_umax(&intrinsic_vmexit)); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - m_vmcs_missing_registers.host_ia32_star = // -- - m_intrinsic->rdmsr(details::IA32_STAR).get(); // -- - m_vmcs_missing_registers.host_ia32_lstar = // -- - m_intrinsic->rdmsr(details::IA32_LSTAR).get(); // -- - m_vmcs_missing_registers.host_ia32_cstar = // -- - m_intrinsic->rdmsr(details::IA32_CSTAR).get(); // -- - m_vmcs_missing_registers.host_ia32_fmask = // -- - m_intrinsic->rdmsr(details::IA32_FMASK).get(); // -- - m_vmcs_missing_registers.host_ia32_kernel_gs_base = // -- - m_intrinsic->rdmsr(details::IA32_KERNEL_GS_BASE).get(); // -- + m_vmcs_missing_registers.host_ia32_star = // -- + intrinsic.rdmsr(IA32_STAR).get(); // -- + m_vmcs_missing_registers.host_ia32_lstar = // -- + intrinsic.rdmsr(IA32_LSTAR).get(); // -- + m_vmcs_missing_registers.host_ia32_cstar = // -- + intrinsic.rdmsr(IA32_CSTAR).get(); // -- + m_vmcs_missing_registers.host_ia32_fmask = // -- + intrinsic.rdmsr(IA32_FMASK).get(); // -- + m_vmcs_missing_registers.host_ia32_kernel_gs_base = // -- + intrinsic.rdmsr(IA32_KERNEL_GS_BASE).get(); // -- return bsl::errc_success; } - public: - /// @brief an alias for INTRINSIC_CONCEPT - using intrinsic_type = INTRINSIC_CONCEPT; - /// @brief an alias for PAGE_POOL_CONCEPT - using page_pool_type = PAGE_POOL_CONCEPT; - /// - /// @brief Default constructor + /// @brief Dumps the contents of a field /// - constexpr vps_t() noexcept = default; + /// + /// @tparam T the type of field to dump + /// @param str the name of the field + /// @param val the field to dump + /// + template + constexpr void + dump(bsl::string_view const &str, bsl::safe_integral const &val) const noexcept + { + auto const *rowcolor{bsl::rst}; + if (val.is_zero()) { + rowcolor = bsl::blk; + } + else { + bsl::touch(); + } + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<40s", str}; + bsl::print() << bsl::ylw << "| "; + + if (val) { + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << " " << bsl::hex(val) << " "; + } + + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << " " << bsl::hex(val) << " "; + } + + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << " " << bsl::hex(val) << " "; + } + + if constexpr (bsl::is_same::value) { + bsl::print() << rowcolor << bsl::hex(val) << ' '; + } + } + else { + bsl::print() << bsl::blk << bsl::fmt{"^19s", "unsupported"}; + } + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; + } + + public: /// /// @brief Initializes this vps_t /// /// - /// @param intrinsic the intrinsics to use - /// @param page_pool the page pool to use /// @param i the ID for this vps_t /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - initialize( - INTRINSIC_CONCEPT *const intrinsic, - PAGE_POOL_CONCEPT *const page_pool, - bsl::safe_uint16 const &i) &noexcept -> bsl::errc_type + initialize(bsl::safe_uint16 const &i) noexcept -> bsl::errc_type { - if (bsl::unlikely(m_initialized)) { - bsl::error() << "vm_t already initialized\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(m_id)) { + bsl::error() << "vps_t already initialized\n" << bsl::here(); + return bsl::errc_precondition; } - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); - }}; - - m_intrinsic = intrinsic; - if (bsl::unlikely(nullptr == m_intrinsic)) { - bsl::error() << "invalid intrinsic\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(!i)) { + bsl::error() << "invalid id\n" << bsl::here(); + return bsl::errc_precondition; } - m_page_pool = page_pool; - if (bsl::unlikely(nullptr == m_page_pool)) { - bsl::error() << "invalid page_pool\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == i)) { + bsl::error() << "id " // -- + << bsl::hex(i) // -- + << " is invalid and cannot be used for initialization" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; } m_id = i; - if (bsl::unlikely(!i)) { - bsl::error() << "invalid id\n" << bsl::here(); - return bsl::errc_failure; - } - - release_on_error.ignore(); - m_initialized = true; - return bsl::errc_success; } /// - /// @brief Release the vps_t + /// @brief Release the vp_t. Note that if this function fails, + /// the microkernel is left in a corrupt state and all use of the + /// vp_t after calling this function will results in UB. /// - constexpr void - release() &noexcept + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + release(tls_t &tls, page_pool_t &page_pool) noexcept -> bsl::errc_type { - this->deallocate(); + if (this->is_zombie()) { + return bsl::errc_success; + } - m_next = {}; - m_id = bsl::safe_uint16::zero(true); - m_page_pool = {}; - m_intrinsic = {}; - m_initialized = {}; + tls.state_reversal_required = true; + bsl::finally zombify_on_error{[this]() noexcept -> void { + this->zombify(); + }}; + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is active on pp " // -- + << bsl::hex(m_active_ppid) // -- + << " and therefore vp " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + m_gprs = {}; + m_vmcs_missing_registers = {}; + + m_vmcs_phys = bsl::safe_uintmax::failure(); + page_pool.deallocate(tls, m_vmcs, ALLOCATE_TAG_VMCS); + m_vmcs = {}; + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vpid = syscall::BF_INVALID_ID; + m_allocated = allocated_status_t::deallocated; + m_id = bsl::safe_uint16::failure(); + + zombify_on_error.ignore(); + return bsl::errc_success; } - /// - /// @brief Destructor - /// - constexpr ~vps_t() noexcept = default; - - /// - /// @brief copy constructor - /// - /// - /// @param o the object being copied - /// - constexpr vps_t(vps_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr vps_t(vps_t &&o) noexcept = default; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vps_t const &o) &noexcept -> vps_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(vps_t &&o) &noexcept -> vps_t & = default; - /// /// @brief Returns the ID of this vps_t /// @@ -1472,320 +1536,891 @@ namespace mk /// @return Returns the ID of this vps_t /// [[nodiscard]] constexpr auto - id() const &noexcept -> bsl::safe_uint16 const & + id() const noexcept -> bsl::safe_uint16 const & { return m_id; } - /// - /// @brief Returns the next vps_t in the vps_pool_t linked list - /// - /// - /// @return Returns the next vps_t in the vps_pool_t linked list - /// - [[nodiscard]] constexpr auto - next() const &noexcept -> vps_t * - { - return m_next; - } - - /// - /// @brief Sets the next vps_t in the vps_pool_t linked list - /// - /// - /// @param val the next vps_t in the vps_pool_t linked list to set - /// - constexpr void - set_next(vps_t *val) &noexcept - { - m_next = val; - } - /// /// @brief Allocates this vps_t /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// @param intrinsic the intrinsics to use + /// @param page_pool the page pool to use + /// @param vpid The ID of the VP to assign the newly created VP to + /// @param ppid The ID of the PP to assign the newly created VP to + /// @return Returns ID of the newly allocated vps /// - template [[nodiscard]] constexpr auto - allocate(TLS_CONCEPT &tls) &noexcept -> bsl::errc_type + allocate( + tls_t &tls, + intrinsic_t &intrinsic, + page_pool_t &page_pool, + bsl::safe_uint16 const &vpid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::safe_uint16 { - if (bsl::unlikely(!m_initialized)) { + bsl::errc_type ret{}; + + if (bsl::unlikely_assert(!m_id)) { bsl::error() << "vps_t not initialized\n" << bsl::here(); - return bsl::errc_failure; + return bsl::safe_uint16::failure(); } - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); + if (bsl::unlikely_assert(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(syscall::BF_INVALID_ID == vpid)) { + bsl::error() << "vp " // -- + << bsl::hex(vpid) // -- + << " is invalid and a vps cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + // if (bsl::unlikely(vp_pool.is_zombie(tls, vpid))) { + // bsl::error() << "vp " // -- + // << bsl::hex(vpid) // -- + // << " is a zombie and a vps cannot be assigned to it" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::safe_uint16::failure(); + // } + + // if (bsl::unlikely(vp_pool.is_deallocated(tls, vpid))) { + // bsl::error() << "vp " // -- + // << bsl::hex(vpid) // -- + // << " has not been created and a vps cannot be assigned to it" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::safe_uint16::failure(); + // } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(syscall::BF_INVALID_ID == ppid)) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is invalid and a vps cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely(!(ppid < tls.online_pps))) { + bsl::error() << "pp " // -- + << bsl::hex(ppid) // -- + << " is not less than the total number of online pps " // -- + << bsl::hex(tls.online_pps) // -- + << " and a vps cannot be assigned to it" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::zombie)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is a zombie and cannot be allocated" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is already allocated and cannot be created" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uint16::failure(); + } + + tls.state_reversal_required = true; + tls.log_vpsid = m_id.get(); + + bsl::finally cleanup_on_error{[this, &tls, &page_pool]() noexcept -> void { + m_vmcs_phys = bsl::safe_uintmax::failure(); + page_pool.deallocate(tls, m_vmcs, ALLOCATE_TAG_VMCS); + m_vmcs = {}; }}; - m_vmcs = m_page_pool->template allocate(); + m_vmcs = page_pool.template allocate(tls, ALLOCATE_TAG_VMCS); if (bsl::unlikely(nullptr == m_vmcs)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return bsl::safe_uint16::failure(); } - m_vmcs_phys = m_page_pool->virt_to_phys(m_vmcs); - if (bsl::unlikely(!m_vmcs_phys)) { + m_vmcs_phys = page_pool.virt_to_phys(m_vmcs); + if (bsl::unlikely_assert(!m_vmcs_phys)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return bsl::safe_uint16::failure(); } - if (bsl::unlikely(!this->init_vmcs(tls))) { + ret = this->init_vmcs(tls, intrinsic); + if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return bsl::safe_uint16::failure(); } - /// TODO: - /// - Extensions should not be able to touch host state fields. - /// + m_assigned_vpid = vpid; + m_assigned_ppid = ppid; + m_allocated = allocated_status_t::allocated; - release_on_error.ignore(); - m_allocated = true; - - return bsl::errc_success; + cleanup_on_error.ignore(); + return m_id; } /// /// @brief Deallocates this vps_t /// - constexpr void - deallocate() &noexcept + /// + /// @param tls the current TLS block + /// @param page_pool the page pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + deallocate(tls_t &tls, page_pool_t &page_pool) noexcept -> bsl::errc_type { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated == allocated_status_t::zombie)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is a zombie and cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is already deallocated and cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + tls.state_reversal_required = true; + bsl::finally zombify_on_error{[this]() noexcept -> void { + this->zombify(); + }}; + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is active on pp " // -- + << bsl::hex(m_active_ppid) // -- + << " and therefore vps " // -- + << bsl::hex(m_id) // -- + << " cannot be destroyed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + m_gprs = {}; m_vmcs_missing_registers = {}; - m_vmcs_phys = bsl::safe_uintmax::zero(true); - if (nullptr != m_page_pool) { - m_page_pool->deallocate(m_vmcs); - m_vmcs = {}; - } - else { - bsl::touch(); + m_vmcs_phys = bsl::safe_uintmax::failure(); + page_pool.deallocate(tls, m_vmcs, ALLOCATE_TAG_VMCS); + m_vmcs = {}; + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vpid = syscall::BF_INVALID_ID; + m_allocated = allocated_status_t::deallocated; + + zombify_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Sets this vps_t's status as zombified, meaning it is no + /// longer usable. + /// + constexpr void + zombify() noexcept + { + if (bsl::unlikely_assert(!m_id)) { + return; } - m_allocated = {}; + if (m_allocated == allocated_status_t::zombie) { + return; + } + + bsl::alert() << "vps " // -- + << bsl::hex(m_id) // -- + << " has been zombified" // -- + << bsl::endl; // -- + + m_allocated = allocated_status_t::zombie; + } + + /// + /// @brief Returns true if this vps_t is deallocated, false otherwise + /// + /// + /// @return Returns true if this vps_t is deallocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_deallocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::deallocated; + } + + /// + /// @brief Returns true if this vps_t is allocated, false otherwise + /// + /// + /// @return Returns true if this vps_t is allocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_allocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::allocated; + } + + /// + /// @brief Returns true if this vps_t is a zombie, false otherwise + /// + /// + /// @return Returns true if this vps_t is a zombie, false otherwise + /// + [[nodiscard]] constexpr auto + is_zombie() const noexcept -> bool + { + return m_allocated == allocated_status_t::zombie; + } + + /// + /// @brief Sets this vps_t as active. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_active(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.active_vpid != m_assigned_vpid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is assigned to vp " // -- + << bsl::hex(m_assigned_vpid) // -- + << " and cannot be activated with vp " // -- + << bsl::hex(tls.active_vpid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be activated on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID != tls.active_vpsid)) { + bsl::error() << "vps " // -- + << bsl::hex(tls.active_vpsid) // -- + << " is still active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is already the active vps on pp " // -- + << bsl::hex(m_active_ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RAX, m_gprs.rax); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBX, m_gprs.rbx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RCX, m_gprs.rcx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDX, m_gprs.rdx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBP, m_gprs.rbp); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RSI, m_gprs.rsi); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDI, m_gprs.rdi); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R8, m_gprs.r8); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R9, m_gprs.r9); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R10, m_gprs.r10); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R11, m_gprs.r11); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R12, m_gprs.r12); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R13, m_gprs.r13); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R14, m_gprs.r14); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R15, m_gprs.r15); + + tls.active_vpsid = m_id.get(); + m_active_ppid = tls.ppid; + + return bsl::errc_success; + } + + /// + /// @brief Sets this vps_t as inactive. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_inactive(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(m_allocated == allocated_status_t::deallocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(syscall::BF_INVALID_ID == tls.active_vpsid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is not active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(tls.active_vpsid != m_id)) { + bsl::error() << "vps " // -- + << bsl::hex(tls.active_vpsid) // -- + << " is still active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(!m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is not active " // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(tls.ppid != m_active_ppid)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << " is not active on pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + m_gprs.rax = intrinsic.tls_reg(syscall::TLS_OFFSET_RAX).get(); + m_gprs.rbx = intrinsic.tls_reg(syscall::TLS_OFFSET_RBX).get(); + m_gprs.rcx = intrinsic.tls_reg(syscall::TLS_OFFSET_RCX).get(); + m_gprs.rdx = intrinsic.tls_reg(syscall::TLS_OFFSET_RDX).get(); + m_gprs.rbp = intrinsic.tls_reg(syscall::TLS_OFFSET_RBP).get(); + m_gprs.rsi = intrinsic.tls_reg(syscall::TLS_OFFSET_RSI).get(); + m_gprs.rdi = intrinsic.tls_reg(syscall::TLS_OFFSET_RDI).get(); + m_gprs.r8 = intrinsic.tls_reg(syscall::TLS_OFFSET_R8).get(); + m_gprs.r9 = intrinsic.tls_reg(syscall::TLS_OFFSET_R9).get(); + m_gprs.r10 = intrinsic.tls_reg(syscall::TLS_OFFSET_R10).get(); + m_gprs.r11 = intrinsic.tls_reg(syscall::TLS_OFFSET_R11).get(); + m_gprs.r12 = intrinsic.tls_reg(syscall::TLS_OFFSET_R12).get(); + m_gprs.r13 = intrinsic.tls_reg(syscall::TLS_OFFSET_R13).get(); + m_gprs.r14 = intrinsic.tls_reg(syscall::TLS_OFFSET_R14).get(); + m_gprs.r15 = intrinsic.tls_reg(syscall::TLS_OFFSET_R15).get(); + + tls.active_vpsid = syscall::BF_INVALID_ID.get(); + m_active_ppid = bsl::safe_uint16::failure(); + + return bsl::errc_success; + } + + /// + /// @brief Returns the ID of the PP that this vps_t is still active + /// on. If the vps_t is inactive, this function returns + /// bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @return Returns the ID of the PP that this vps_t is still active + /// on. If the vps_t is inactive, this function returns + /// bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_active(tls_t &tls) const noexcept -> bsl::safe_uint16 + { + bsl::discard(tls); + return m_active_ppid; + } + + /// + /// @brief Returns true if this vps_t is active on the current PP, + /// false otherwise + /// + /// + /// @param tls the current TLS block + /// @return Returns true if this vps_t is active on the current PP, + /// false otherwise + /// + [[nodiscard]] constexpr auto + is_active_on_current_pp(tls_t &tls) const noexcept -> bool + { + return tls.ppid == m_active_ppid; + } + + /// + /// @brief Migrates this vps_t from one PP to another. This should + /// only be called by the run ABI when the VP and VPS's assigned + /// ppids do not match. The VPS should always match the assigned + /// VP's ID. If it doesn't we need to migrate the VPS. + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param ppid the ID of the PP to migrate to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + migrate(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uint16 const &ppid) noexcept + -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(intrinsic); + bsl::discard(ppid); + + // if (bsl::unlikely_assert(!m_id)) { + // bsl::error() << "vps_t not initialized\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(!m_allocated)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " was never allocated" // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(!ppid)) { + // bsl::error() << "invalid ppid\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(syscall::BF_INVALID_ID == ppid)) { + // bsl::error() << "invalid ppid\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(!(ppid < tls.online_pps))) { + // bsl::error() << "invalid ppid\n" << bsl::here(); + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(tls.ppid != ppid)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " is being migrated to pp " // -- + // << bsl::hex(ppid) // -- + // << " by pp " // -- + // << bsl::hex(tls.ppid) // -- + // << " which is not allowed " // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(ppid == m_assigned_ppid)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " is already assigned to a pp " // -- + // << bsl::hex(m_assigned_ppid) // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // if (bsl::unlikely(syscall::BF_INVALID_ID != m_active_ppid)) { + // bsl::error() << "vps " // -- + // << bsl::hex(m_id) // -- + // << " is still active on pp " // -- + // << bsl::hex(m_active_ppid) // -- + // << bsl::endl // -- + // << bsl::here(); // -- + + // return bsl::errc_failure; + // } + + // m_guest_vmcb->vmcb_clean_bits = {}; + // m_assigned_ppid = ppid; + + return bsl::errc_success; + } + + /// + /// @brief Returns the ID of the VP this vp_t is assigned to + /// + /// + /// @return Returns the ID of the VP this vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_vp() const noexcept -> bsl::safe_uint16 + { + if (bsl::unlikely(syscall::BF_INVALID_ID == m_assigned_vpid)) { + return bsl::safe_uint16::failure(); + } + + return m_assigned_vpid; + } + + /// + /// @brief Returns the ID of the PP this vp_t is assigned to + /// + /// + /// @return Returns the ID of the PP this vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_pp() const noexcept -> bsl::safe_uint16 + { + if (bsl::unlikely(syscall::BF_INVALID_ID == m_assigned_ppid)) { + return bsl::safe_uint16::failure(); + } + + return m_assigned_ppid; } /// /// @brief Stores the provided state in the VPS. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam STATE_SAVE_CONCEPT the type of state save to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param state the state to set the VPS to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise - /// - template + /// and friends otherwise [[nodiscard]] constexpr auto - state_save_to_vps(TLS_CONCEPT &tls, STATE_SAVE_CONCEPT const *const state) &noexcept + state_save_to_vps( + tls_t &tls, intrinsic_t &intrinsic, loader::state_save_t const &state) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; } - if (bsl::unlikely(nullptr == state)) { - bsl::error() << "invalid state\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; } - if (bsl::unlikely(!this->ensure_this_vps_is_loaded(tls))) { + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + ret = this->ensure_this_vps_is_loaded(tls, intrinsic); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RAX, state->rax); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RBX, state->rbx); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RCX, state->rcx); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RDX, state->rdx); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RBP, state->rbp); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RSI, state->rsi); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RDI, state->rdi); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R8, state->r8); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R9, state->r9); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R10, state->r10); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R11, state->r11); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R12, state->r12); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R13, state->r13); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R14, state->r14); - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R15, state->r15); - - ret = m_intrinsic->vmwrite64(VMCS_GUEST_RSP, state->rsp); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RAX, state.rax); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBX, state.rbx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RCX, state.rcx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDX, state.rdx); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBP, state.rbp); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RSI, state.rsi); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDI, state.rdi); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R8, state.r8); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R9, state.r9); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R10, state.r10); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R11, state.r11); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R12, state.r12); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R13, state.r13); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R14, state.r14); + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R15, state.r15); + } + else { + m_gprs.rax = state.rax; + m_gprs.rbx = state.rbx; + m_gprs.rcx = state.rcx; + m_gprs.rdx = state.rdx; + m_gprs.rbp = state.rbp; + m_gprs.rsi = state.rsi; + m_gprs.rdi = state.rdi; + m_gprs.r8 = state.r8; + m_gprs.r9 = state.r9; + m_gprs.r10 = state.r10; + m_gprs.r11 = state.r11; + m_gprs.r12 = state.r12; + m_gprs.r13 = state.r13; + m_gprs.r14 = state.r14; + m_gprs.r15 = state.r15; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_RIP, state->rip); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_RSP, state.rsp); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_RFLAGS, state->rflags); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_RIP, state.rip); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - auto const gdtr_limit{bsl::to_u32(state->gdtr.limit)}; - ret = m_intrinsic->vmwrite32(VMCS_GUEST_GDTR_LIMIT, gdtr_limit); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_RFLAGS, state.rflags); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - auto const gdtr_base{bsl::to_umax(state->gdtr.base)}; - ret = m_intrinsic->vmwrite64(VMCS_GUEST_GDTR_BASE, gdtr_base); - if (bsl::unlikely(!ret)) { + auto const gdtr_limit{bsl::to_u32(state.gdtr.limit)}; + ret = intrinsic.vmwrite32(VMCS_GUEST_GDTR_LIMIT, gdtr_limit); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - auto const idtr_limit{bsl::to_u32(state->idtr.limit)}; - ret = m_intrinsic->vmwrite32(VMCS_GUEST_IDTR_LIMIT, idtr_limit); - if (bsl::unlikely(!ret)) { + auto const gdtr_base{bsl::to_umax(state.gdtr.base)}; + ret = intrinsic.vmwrite64(VMCS_GUEST_GDTR_BASE, gdtr_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - auto const idtr_base{bsl::to_umax(state->idtr.base)}; - ret = m_intrinsic->vmwrite64(VMCS_GUEST_IDTR_BASE, idtr_base); - if (bsl::unlikely(!ret)) { + auto const idtr_limit{bsl::to_u32(state.idtr.limit)}; + ret = intrinsic.vmwrite32(VMCS_GUEST_IDTR_LIMIT, idtr_limit); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->set_es_segment_descriptor(state))) { + auto const idtr_base{bsl::to_umax(state.idtr.base)}; + ret = intrinsic.vmwrite64(VMCS_GUEST_IDTR_BASE, idtr_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->set_cs_segment_descriptor(state))) { + ret = this->set_es_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->set_ss_segment_descriptor(state))) { + ret = this->set_cs_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->set_ds_segment_descriptor(state))) { + ret = this->set_ss_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->set_fs_segment_descriptor(state))) { + ret = this->set_ds_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->set_gs_segment_descriptor(state))) { + ret = this->set_fs_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->set_ldtr_segment_descriptor(state))) { + ret = this->set_gs_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->set_tr_segment_descriptor(state))) { + ret = this->set_ldtr_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_CR0, state->cr0); - if (bsl::unlikely(!ret)) { + ret = this->set_tr_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - m_vmcs_missing_registers.cr2 = state->cr2; - - ret = m_intrinsic->vmwrite64(VMCS_GUEST_CR3, state->cr3); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_CR0, state.cr0); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_CR4, state->cr4); - if (bsl::unlikely(!ret)) { + m_vmcs_missing_registers.cr2 = state.cr2; + + ret = intrinsic.vmwrite64(VMCS_GUEST_CR3, state.cr3); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - m_vmcs_missing_registers.dr6 = state->dr6; - - ret = m_intrinsic->vmwrite64(VMCS_GUEST_DR7, state->dr7); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_CR4, state.cr4); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_IA32_EFER, state->ia32_efer); - if (bsl::unlikely(!ret)) { + m_vmcs_missing_registers.dr6 = state.dr6; + + ret = intrinsic.vmwrite64(VMCS_GUEST_DR7, state.dr7); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - m_vmcs_missing_registers.guest_ia32_star = state->ia32_star; - m_vmcs_missing_registers.guest_ia32_lstar = state->ia32_lstar; - m_vmcs_missing_registers.guest_ia32_cstar = state->ia32_cstar; - m_vmcs_missing_registers.guest_ia32_fmask = state->ia32_fmask; - - ret = m_intrinsic->vmwrite64(VMCS_GUEST_FS_BASE, state->ia32_fs_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_IA32_EFER, state.ia32_efer); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_GS_BASE, state->ia32_gs_base); - if (bsl::unlikely(!ret)) { + m_vmcs_missing_registers.guest_ia32_star = state.ia32_star; + m_vmcs_missing_registers.guest_ia32_lstar = state.ia32_lstar; + m_vmcs_missing_registers.guest_ia32_cstar = state.ia32_cstar; + m_vmcs_missing_registers.guest_ia32_fmask = state.ia32_fmask; + + ret = intrinsic.vmwrite64(VMCS_GUEST_FS_BASE, state.ia32_fs_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - m_vmcs_missing_registers.guest_ia32_kernel_gs_base = state->ia32_kernel_gs_base; - - ret = m_intrinsic->vmwrite64(VMCS_GUEST_IA32_SYSENTER_CS, state->ia32_sysenter_cs); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_GS_BASE, state.ia32_gs_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_IA32_SYSENTER_ESP, state->ia32_sysenter_esp); - if (bsl::unlikely(!ret)) { + m_vmcs_missing_registers.guest_ia32_kernel_gs_base = state.ia32_kernel_gs_base; + + ret = intrinsic.vmwrite64(VMCS_GUEST_IA32_SYSENTER_CS, state.ia32_sysenter_cs); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_IA32_SYSENTER_EIP, state->ia32_sysenter_eip); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_IA32_SYSENTER_ESP, state.ia32_sysenter_esp); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_IA32_PAT, state->ia32_pat); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_IA32_SYSENTER_EIP, state.ia32_sysenter_eip); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_IA32_DEBUGCTL, state->ia32_debugctl); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_IA32_PAT, state.ia32_pat); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; + } + + ret = intrinsic.vmwrite64(VMCS_GUEST_IA32_DEBUGCTL, state.ia32_debugctl); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; } return bsl::errc_success; @@ -1795,220 +2430,263 @@ namespace mk /// @brief Stores the VPS state in the provided state save. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use - /// @tparam STATE_SAVE_CONCEPT the type of state save to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param state the state save to store the VPS state to /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise - /// - template + /// and friends otherwise [[nodiscard]] constexpr auto - vps_to_state_save(TLS_CONCEPT &tls, STATE_SAVE_CONCEPT *const state) &noexcept + vps_to_state_save(tls_t &tls, intrinsic_t &intrinsic, loader::state_save_t &state) noexcept -> bsl::errc_type { bsl::errc_type ret{}; - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; } - if (bsl::unlikely(nullptr == state)) { - bsl::error() << "invalid state\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; } - if (bsl::unlikely(!this->ensure_this_vps_is_loaded(tls))) { + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + ret = this->ensure_this_vps_is_loaded(tls, intrinsic); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - state->rax = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RAX).get(); - state->rbx = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RBX).get(); - state->rcx = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RCX).get(); - state->rdx = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RDX).get(); - state->rbp = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RBP).get(); - state->rsi = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RSI).get(); - state->rdi = m_intrinsic->tls_reg(syscall::TLS_OFFSET_RDI).get(); - state->r8 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R8).get(); - state->r9 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R9).get(); - state->r10 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R10).get(); - state->r11 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R11).get(); - state->r12 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R12).get(); - state->r13 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R13).get(); - state->r14 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R14).get(); - state->r15 = m_intrinsic->tls_reg(syscall::TLS_OFFSET_R15).get(); - - ret = m_intrinsic->vmread64(VMCS_GUEST_RSP, &state->rsp); - if (bsl::unlikely(!ret)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; + if (tls.active_vpsid == m_id) { + state.rax = intrinsic.tls_reg(syscall::TLS_OFFSET_RAX).get(); + state.rbx = intrinsic.tls_reg(syscall::TLS_OFFSET_RBX).get(); + state.rcx = intrinsic.tls_reg(syscall::TLS_OFFSET_RCX).get(); + state.rdx = intrinsic.tls_reg(syscall::TLS_OFFSET_RDX).get(); + state.rbp = intrinsic.tls_reg(syscall::TLS_OFFSET_RBP).get(); + state.rsi = intrinsic.tls_reg(syscall::TLS_OFFSET_RSI).get(); + state.rdi = intrinsic.tls_reg(syscall::TLS_OFFSET_RDI).get(); + state.r8 = intrinsic.tls_reg(syscall::TLS_OFFSET_R8).get(); + state.r9 = intrinsic.tls_reg(syscall::TLS_OFFSET_R9).get(); + state.r10 = intrinsic.tls_reg(syscall::TLS_OFFSET_R10).get(); + state.r11 = intrinsic.tls_reg(syscall::TLS_OFFSET_R11).get(); + state.r12 = intrinsic.tls_reg(syscall::TLS_OFFSET_R12).get(); + state.r13 = intrinsic.tls_reg(syscall::TLS_OFFSET_R13).get(); + state.r14 = intrinsic.tls_reg(syscall::TLS_OFFSET_R14).get(); + state.r15 = intrinsic.tls_reg(syscall::TLS_OFFSET_R15).get(); + } + else { + state.rax = m_gprs.rax; + state.rbx = m_gprs.rbx; + state.rcx = m_gprs.rcx; + state.rdx = m_gprs.rdx; + state.rbp = m_gprs.rbp; + state.rsi = m_gprs.rsi; + state.rdi = m_gprs.rdi; + state.r8 = m_gprs.r8; + state.r9 = m_gprs.r9; + state.r10 = m_gprs.r10; + state.r11 = m_gprs.r11; + state.r12 = m_gprs.r12; + state.r13 = m_gprs.r13; + state.r14 = m_gprs.r14; + state.r15 = m_gprs.r15; } - ret = m_intrinsic->vmread64(VMCS_GUEST_RIP, &state->rip); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_RSP, &state.rsp); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_RFLAGS, &state->rflags); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_RIP, &state.rip); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread16(VMCS_GUEST_GDTR_LIMIT, &state->gdtr.limit); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_RFLAGS, &state.rflags); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; + } + + ret = intrinsic.vmread16(VMCS_GUEST_GDTR_LIMIT, &state.gdtr.limit); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; } bsl::safe_uint64 gdtr_base{}; - ret = m_intrinsic->vmread64(VMCS_GUEST_GDTR_BASE, gdtr_base.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_GDTR_BASE, gdtr_base.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - state->gdtr.base = bsl::to_ptr(gdtr_base); + state.gdtr.base = bsl::to_ptr(gdtr_base); - ret = m_intrinsic->vmread16(VMCS_GUEST_IDTR_LIMIT, &state->idtr.limit); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread16(VMCS_GUEST_IDTR_LIMIT, &state.idtr.limit); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } bsl::safe_uint64 idtr_base{}; - ret = m_intrinsic->vmread64(VMCS_GUEST_IDTR_BASE, idtr_base.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_IDTR_BASE, idtr_base.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - state->idtr.base = bsl::to_ptr(idtr_base); + state.idtr.base = bsl::to_ptr(idtr_base); - if (bsl::unlikely(!this->get_es_segment_descriptor(state))) { + ret = this->get_es_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->get_cs_segment_descriptor(state))) { + ret = this->get_cs_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->get_ss_segment_descriptor(state))) { + ret = this->get_ss_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->get_ds_segment_descriptor(state))) { + ret = this->get_ds_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->get_fs_segment_descriptor(state))) { + ret = this->get_fs_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->get_gs_segment_descriptor(state))) { + ret = this->get_gs_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->get_ldtr_segment_descriptor(state))) { + ret = this->get_ldtr_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - if (bsl::unlikely(!this->get_tr_segment_descriptor(state))) { + ret = this->get_tr_segment_descriptor(intrinsic, state); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_CR0, &state->cr0); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_CR0, &state.cr0); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - state->cr2 = m_vmcs_missing_registers.cr2; + state.cr2 = m_vmcs_missing_registers.cr2; - ret = m_intrinsic->vmread64(VMCS_GUEST_CR3, &state->cr3); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_CR3, &state.cr3); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_CR4, &state->cr4); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_CR4, &state.cr4); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - state->dr6 = m_vmcs_missing_registers.dr6; + state.dr6 = m_vmcs_missing_registers.dr6; - ret = m_intrinsic->vmread64(VMCS_GUEST_DR7, &state->dr7); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_DR7, &state.dr7); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_IA32_EFER, &state->ia32_efer); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_IA32_EFER, &state.ia32_efer); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - state->ia32_star = m_vmcs_missing_registers.guest_ia32_star; - state->ia32_lstar = m_vmcs_missing_registers.guest_ia32_lstar; - state->ia32_cstar = m_vmcs_missing_registers.guest_ia32_cstar; - state->ia32_fmask = m_vmcs_missing_registers.guest_ia32_fmask; + state.ia32_star = m_vmcs_missing_registers.guest_ia32_star; + state.ia32_lstar = m_vmcs_missing_registers.guest_ia32_lstar; + state.ia32_cstar = m_vmcs_missing_registers.guest_ia32_cstar; + state.ia32_fmask = m_vmcs_missing_registers.guest_ia32_fmask; - ret = m_intrinsic->vmread64(VMCS_GUEST_FS_BASE, &state->ia32_fs_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_FS_BASE, &state.ia32_fs_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_GS_BASE, &state->ia32_gs_base); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_GS_BASE, &state.ia32_gs_base); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - state->ia32_kernel_gs_base = m_vmcs_missing_registers.guest_ia32_kernel_gs_base; + state.ia32_kernel_gs_base = m_vmcs_missing_registers.guest_ia32_kernel_gs_base; - ret = m_intrinsic->vmread64(VMCS_GUEST_IA32_SYSENTER_CS, &state->ia32_sysenter_cs); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_IA32_SYSENTER_CS, &state.ia32_sysenter_cs); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_IA32_SYSENTER_ESP, &state->ia32_sysenter_esp); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_IA32_SYSENTER_ESP, &state.ia32_sysenter_esp); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_IA32_SYSENTER_EIP, &state->ia32_sysenter_eip); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_IA32_SYSENTER_EIP, &state.ia32_sysenter_eip); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_IA32_PAT, &state->ia32_pat); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_IA32_PAT, &state.ia32_pat); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_IA32_DEBUGCTL, &state->ia32_debugctl); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_IA32_DEBUGCTL, &state.ia32_debugctl); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } return bsl::errc_success; @@ -2019,17 +2697,16 @@ namespace mk /// the field to read. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @tparam FIELD_TYPE the type (i.e., size) of field to read /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param index the index of the field to read from the VPS /// @return Returns the value of the requested field from the - /// VPS or bsl::safe_integral::zero(true) - /// on failure. + /// VPS or bsl::safe_integral::failure() /// - template + template [[nodiscard]] constexpr auto - read(TLS_CONCEPT &tls, bsl::safe_uintmax const &index) &noexcept + read(tls_t &tls, intrinsic_t &intrinsic, bsl::safe_uintmax const &index) noexcept -> bsl::safe_integral { /// TODO: @@ -2041,18 +2718,42 @@ namespace mk bsl::errc_type ret{}; bsl::safe_integral val{}; - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::safe_integral::zero(true); + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::safe_integral::failure(); } - if (bsl::unlikely(!this->ensure_this_vps_is_loaded(tls))) { + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_integral::failure(); + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_integral::failure(); + } + + ret = this->ensure_this_vps_is_loaded(tls, intrinsic); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::safe_integral::zero(true); + return bsl::safe_integral::failure(); } if constexpr (bsl::is_same::value) { - ret = m_intrinsic->vmread16(index, val.data()); + ret = intrinsic.vmread16(index, val.data()); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return val; @@ -2062,7 +2763,7 @@ namespace mk } if constexpr (bsl::is_same::value) { - ret = m_intrinsic->vmread32(index, val.data()); + ret = intrinsic.vmread32(index, val.data()); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return val; @@ -2072,7 +2773,7 @@ namespace mk } if constexpr (bsl::is_same::value) { - ret = m_intrinsic->vmread64(index, val.data()); + ret = intrinsic.vmread64(index, val.data()); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return val; @@ -2082,7 +2783,7 @@ namespace mk } bsl::error() << "unsupported field type\n" << bsl::here(); - return bsl::safe_integral::zero(true); + return bsl::safe_integral::failure(); } /// @@ -2090,20 +2791,20 @@ namespace mk /// the field and the value to write. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @tparam FIELD_TYPE the type (i.e., size) of field to write /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param index the index of the field to write to the VPS - /// @param value the value to write to the VPS + /// @param val the value to write to the VPS /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise /// - template + template [[nodiscard]] constexpr auto write( - TLS_CONCEPT &tls, + tls_t &tls, + intrinsic_t &intrinsic, bsl::safe_uintmax const &index, - bsl::safe_integral const &value) &noexcept -> bsl::errc_type + bsl::safe_integral const &val) noexcept -> bsl::errc_type { /// TODO: /// - Implement a field type checker to make sure the user is @@ -2113,47 +2814,67 @@ namespace mk bsl::errc_type ret{}; - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(!val)) { + bsl::error() << "invalid value\n" << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(!value)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(value) // -- - << bsl::endl // -- - << bsl::here(); // -- + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::errc_failure; + return bsl::errc_precondition; } - if (bsl::unlikely(!this->ensure_this_vps_is_loaded(tls))) { + ret = this->ensure_this_vps_is_loaded(tls, intrinsic); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - constexpr auto vmcs_pinbased_ctls_idx{bsl::to_umax(0x4000U)}; - constexpr auto vmcs_exit_ctls_idx{bsl::to_umax(0x400CU)}; - constexpr auto vmcs_entry_ctls_idx{bsl::to_umax(0x4012U)}; + constexpr auto vmcs_pinbased_ctls_idx{0x4000_umax}; + constexpr auto vmcs_exit_ctls_idx{0x400C_umax}; + constexpr auto vmcs_entry_ctls_idx{0x4012_umax}; - bsl::safe_integral sanitized{value}; + bsl::safe_integral sanitized{val}; if constexpr (bsl::is_same::value) { switch (index.get()) { case vmcs_pinbased_ctls_idx.get(): { - constexpr auto vmcs_pinbased_ctls_mask{bsl::to_u32(0x28U)}; + constexpr auto vmcs_pinbased_ctls_mask{0x28_u32}; sanitized |= vmcs_pinbased_ctls_mask; break; } case vmcs_exit_ctls_idx.get(): { - constexpr auto vmcs_exit_ctls_mask{bsl::to_u32(0x3C0204U)}; + constexpr auto vmcs_exit_ctls_mask{0x3C0204_u32}; sanitized |= vmcs_exit_ctls_mask; break; } case vmcs_entry_ctls_idx.get(): { - constexpr auto vmcs_entry_ctls_mask{bsl::to_u32(0xC204U)}; + constexpr auto vmcs_entry_ctls_mask{0xC204_u32}; sanitized |= vmcs_entry_ctls_mask; break; } @@ -2166,25 +2887,28 @@ namespace mk else { switch (index.get()) { case vmcs_pinbased_ctls_idx.get(): { - bsl::error() - << "invalid integer type for field: " << bsl::hex(index) << bsl::endl - << bsl::here(); + bsl::error() << "invalid integer type for field " // -- + << bsl::hex(index) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } case vmcs_exit_ctls_idx.get(): { - bsl::error() - << "invalid integer type for field: " << bsl::hex(index) << bsl::endl - << bsl::here(); + bsl::error() << "invalid integer type for field " // -- + << bsl::hex(index) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } case vmcs_entry_ctls_idx.get(): { - bsl::error() - << "invalid integer type for field: " << bsl::hex(index) << bsl::endl - << bsl::here(); + bsl::error() << "invalid integer type for field " // -- + << bsl::hex(index) // -- + << bsl::endl // -- + << bsl::here(); // -- return bsl::errc_failure; } @@ -2196,7 +2920,7 @@ namespace mk } if constexpr (bsl::is_same::value) { - ret = m_intrinsic->vmwrite16(index, sanitized); + ret = intrinsic.vmwrite16(index, sanitized); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; @@ -2206,7 +2930,7 @@ namespace mk } if constexpr (bsl::is_same::value) { - ret = m_intrinsic->vmwrite32(index, sanitized); + ret = intrinsic.vmwrite32(index, sanitized); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; @@ -2216,7 +2940,7 @@ namespace mk } if constexpr (bsl::is_same::value) { - ret = m_intrinsic->vmwrite64(index, sanitized); + ret = intrinsic.vmwrite64(index, sanitized); if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; @@ -2234,82 +2958,164 @@ namespace mk /// defining the field to read. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param reg a bf_reg_t defining the field to read from the VPS /// @return Returns the value of the requested field from the - /// VPS or bsl::safe_uintmax::zero(true) on failure. - /// - template + /// VPS or bsl::safe_uintmax::failure() on failure. [[nodiscard]] constexpr auto - read_reg(TLS_CONCEPT &tls, syscall::bf_reg_t const reg) &noexcept -> bsl::safe_uintmax + read_reg(tls_t &tls, intrinsic_t &intrinsic, syscall::bf_reg_t const reg) noexcept + -> bsl::safe_uintmax { - bsl::safe_uint64 index{}; + bsl::safe_uint64 index{bsl::safe_uint64::failure()}; - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::safe_uintmax::failure(); + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); } switch (reg) { case syscall::bf_reg_t::bf_reg_t_rax: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RAX); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RAX); + } + + return m_gprs.rax; } case syscall::bf_reg_t::bf_reg_t_rbx: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RBX); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RBX); + } + + return m_gprs.rbx; } case syscall::bf_reg_t::bf_reg_t_rcx: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RCX); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RCX); + } + + return m_gprs.rcx; } case syscall::bf_reg_t::bf_reg_t_rdx: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RDX); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RDX); + } + + return m_gprs.rdx; } case syscall::bf_reg_t::bf_reg_t_rbp: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RBP); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RBP); + } + + return m_gprs.rbp; } case syscall::bf_reg_t::bf_reg_t_rsi: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RSI); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RSI); + } + + return m_gprs.rsi; } case syscall::bf_reg_t::bf_reg_t_rdi: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_RDI); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_RDI); + } + + return m_gprs.rdi; } case syscall::bf_reg_t::bf_reg_t_r8: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R8); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R8); + } + + return m_gprs.r8; } case syscall::bf_reg_t::bf_reg_t_r9: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R9); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R9); + } + + return m_gprs.r9; } case syscall::bf_reg_t::bf_reg_t_r10: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R10); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R10); + } + + return m_gprs.r10; } case syscall::bf_reg_t::bf_reg_t_r11: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R11); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R11); + } + + return m_gprs.r11; } case syscall::bf_reg_t::bf_reg_t_r12: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R12); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R12); + } + + return m_gprs.r12; } case syscall::bf_reg_t::bf_reg_t_r13: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R13); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R13); + } + + return m_gprs.r13; } case syscall::bf_reg_t::bf_reg_t_r14: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R14); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R14); + } + + return m_gprs.r14; } case syscall::bf_reg_t::bf_reg_t_r15: { - return m_intrinsic->tls_reg(syscall::TLS_OFFSET_R15); + if (tls.active_vpsid == m_id) { + return intrinsic.tls_reg(syscall::TLS_OFFSET_R15); + } + + return m_gprs.r15; } case syscall::bf_reg_t::bf_reg_t_rip: { @@ -2597,11 +3403,11 @@ namespace mk default: { bsl::error() << "unknown by bf_reg_t\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); + break; } } - auto val{this->read(tls, index)}; + auto const val{this->read(tls, intrinsic, index)}; if (bsl::unlikely(!val)) { bsl::print() << bsl::here(); return val; @@ -2615,108 +3421,202 @@ namespace mk /// defining the field and a value to write. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @param reg a bf_reg_t defining the field to write to the VPS /// @param val the value to write to the VPS /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise /// - template [[nodiscard]] constexpr auto write_reg( - TLS_CONCEPT &tls, syscall::bf_reg_t const reg, bsl::safe_uintmax const &val) &noexcept - -> bsl::errc_type + tls_t &tls, + intrinsic_t &intrinsic, + syscall::bf_reg_t const reg, + bsl::safe_uintmax const &val) noexcept -> bsl::errc_type { - bsl::safe_uint64 index{}; + bsl::safe_uint64 index{bsl::safe_uint64::failure()}; - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; + } + + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely_assert(!val)) { + bsl::error() << "invalid value\n" << bsl::here(); return bsl::errc_failure; } - if (bsl::unlikely(!val)) { - bsl::error() << "invalid val: " // -- - << bsl::hex(val) // -- - << bsl::endl // -- - << bsl::here(); // -- + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- - return bsl::errc_failure; + return bsl::errc_precondition; } switch (reg) { case syscall::bf_reg_t::bf_reg_t_rax: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RAX, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RAX, val); + } + else { + m_gprs.rax = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rbx: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RBX, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBX, val); + } + else { + m_gprs.rbx = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rcx: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RCX, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RCX, val); + } + else { + m_gprs.rcx = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rdx: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RDX, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDX, val); + } + else { + m_gprs.rdx = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rbp: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RBP, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RBP, val); + } + else { + m_gprs.rbp = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rsi: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RSI, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RSI, val); + } + else { + m_gprs.rsi = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_rdi: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_RDI, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_RDI, val); + } + else { + m_gprs.rdi = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r8: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R8, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R8, val); + } + else { + m_gprs.r8 = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r9: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R9, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R9, val); + } + else { + m_gprs.r9 = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r10: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R10, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R10, val); + } + else { + m_gprs.r10 = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r11: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R11, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R11, val); + } + else { + m_gprs.r11 = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r12: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R12, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R12, val); + } + else { + m_gprs.r12 = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r13: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R13, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R13, val); + } + else { + m_gprs.r13 = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r14: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R14, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R14, val); + } + else { + m_gprs.r14 = val.get(); + } return bsl::errc_success; } case syscall::bf_reg_t::bf_reg_t_r15: { - m_intrinsic->set_tls_reg(syscall::TLS_OFFSET_R15, val); + if (tls.active_vpsid == m_id) { + intrinsic.set_tls_reg(syscall::TLS_OFFSET_R15, val); + } + else { + m_gprs.r15 = val.get(); + } return bsl::errc_success; } @@ -3012,11 +3912,11 @@ namespace mk default: { bsl::error() << "unknown by bf_reg_t\n" << bsl::here(); - return bsl::errc_failure; + break; } } - auto const ret{this->write(tls, index, val)}; + auto const ret{this->write(tls, intrinsic, index, val)}; if (bsl::unlikely(!ret)) { bsl::print() << bsl::here(); return ret; @@ -3031,33 +3931,88 @@ namespace mk /// will return the VMExit reason. /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @param log the VMExit log to use /// @return Returns the VMExit reason on success, or - /// bsl::safe_uintmax::zero(true) on failure. /// - template [[nodiscard]] constexpr auto - run(TLS_CONCEPT &tls) &noexcept -> bsl::safe_uintmax + run(tls_t &tls, intrinsic_t &intrinsic, vmexit_log_t &log) noexcept -> bsl::safe_uintmax { - constexpr bsl::safe_uintmax invalid_exit_reason{bsl::to_umax(0xFFFFFFFFFFFFFFFFU)}; + bsl::errc_type ret{}; + constexpr auto invalid_exit_reason{0xFFFFFFFF00000000_umax}; - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::safe_uintmax::failure(); } - if (bsl::unlikely(!this->ensure_this_vps_is_loaded(tls))) { + if (bsl::unlikely_assert(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + if (bsl::unlikely_assert(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot run by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::safe_uintmax::failure(); + } + + ret = this->ensure_this_vps_is_loaded(tls, intrinsic); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::safe_uintmax::zero(true); + return bsl::safe_uintmax::failure(); } - auto const exit_reason{details::intrinsic_vmrun(&m_vmcs_missing_registers)}; - if (invalid_exit_reason == exit_reason) { - this->dump(tls); + bsl::safe_uintmax const exit_reason{intrinsic_vmrun(&m_vmcs_missing_registers)}; + if (bsl::unlikely(exit_reason > invalid_exit_reason)) { + bsl::error() << "vmlaunch/vmresume failed with error code " // -- + << (exit_reason & (~invalid_exit_reason)) // -- + << bsl::endl // -- + << bsl::here(); // -- - bsl::error() << "vmlaunch/vmresume failed\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); + return bsl::safe_uintmax::failure(); + } + + if constexpr (!(BSL_DEBUG_LEVEL < bsl::VV)) { + log.add( + tls.ppid, + {tls.active_vmid, + tls.active_vpid, + tls.active_vpsid, + exit_reason, + intrinsic.vmread64_quiet(VMCS_EXIT_QUALIFICATION), + intrinsic.vmread64_quiet(VMCS_VMEXIT_INSTRUCTION_INFORMATION), + {}, + intrinsic.tls_reg(syscall::TLS_OFFSET_RAX), + intrinsic.tls_reg(syscall::TLS_OFFSET_RBX), + intrinsic.tls_reg(syscall::TLS_OFFSET_RCX), + intrinsic.tls_reg(syscall::TLS_OFFSET_RDX), + intrinsic.tls_reg(syscall::TLS_OFFSET_RBP), + intrinsic.tls_reg(syscall::TLS_OFFSET_RSI), + intrinsic.tls_reg(syscall::TLS_OFFSET_RDI), + intrinsic.tls_reg(syscall::TLS_OFFSET_R8), + intrinsic.tls_reg(syscall::TLS_OFFSET_R9), + intrinsic.tls_reg(syscall::TLS_OFFSET_R10), + intrinsic.tls_reg(syscall::TLS_OFFSET_R11), + intrinsic.tls_reg(syscall::TLS_OFFSET_R12), + intrinsic.tls_reg(syscall::TLS_OFFSET_R13), + intrinsic.tls_reg(syscall::TLS_OFFSET_R14), + intrinsic.tls_reg(syscall::TLS_OFFSET_R15), + intrinsic.vmread64_quiet(VMCS_GUEST_RSP), + intrinsic.vmread64_quiet(VMCS_GUEST_RIP)}); } /// TODO: @@ -3072,43 +4027,66 @@ namespace mk /// @brief Advance the IP of the VPS /// /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - template [[nodiscard]] constexpr auto - advance_ip(TLS_CONCEPT &tls) &noexcept -> bsl::errc_type + advance_ip(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { bsl::errc_type ret{}; bsl::safe_uint64 rip{}; bsl::safe_uint64 len{}; - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return bsl::errc_failure; + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; } - if (bsl::unlikely(!this->ensure_this_vps_is_loaded(tls))) { + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + ret = this->ensure_this_vps_is_loaded(tls, intrinsic); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_GUEST_RIP, rip.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_GUEST_RIP, rip.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmread64(VMCS_VMEXIT_INSTRUCTION_LENGTH, len.data()); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmread64(VMCS_VMEXIT_INSTRUCTION_LENGTH, len.data()); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); - return bsl::errc_failure; + return ret; } - ret = m_intrinsic->vmwrite64(VMCS_GUEST_RIP, rip + len); - if (bsl::unlikely(!ret)) { + ret = intrinsic.vmwrite64(VMCS_GUEST_RIP, rip + len); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); return ret; } @@ -3117,669 +4095,431 @@ namespace mk } /// - /// @brief Dumps the contents of a VMCS field to the console + /// @brief Clears the VPS's internal cache. Note that this is a + /// hardware specific function and doesn't change the actual + /// values stored in the VPS. /// /// - /// @tparam FIELD_TYPE the type (i.e., size) of field to read - /// @param name the name of the field - /// @param type the field's type - /// @param index the index of the field - /// - template - constexpr void - dump_vmcs_field( - bsl::string_view const &name, - bsl::string_view const &type, - bsl::safe_uintmax const &index) noexcept - { - constexpr bsl::safe_uintmax field_width{bsl::to_umax(44)}; - - bsl::errc_type ret{}; - bsl::safe_integral val{}; - - if constexpr (bsl::is_same::value) { - ret = m_intrinsic->vmread16_quiet(index, val.data()); - if (bsl::unlikely(!ret)) { - val = bsl::safe_integral::zero(true); - } - } - - if constexpr (bsl::is_same::value) { - ret = m_intrinsic->vmread32_quiet(index, val.data()); - if (bsl::unlikely(!ret)) { - val = bsl::safe_integral::zero(true); - } - } - - if constexpr (bsl::is_same::value) { - ret = m_intrinsic->vmread64_quiet(index, val.data()); - if (bsl::unlikely(!ret)) { - val = bsl::safe_integral::zero(true); - } - } - - bsl::print() << bsl::yellow << "| " << bsl::reset_color; - bsl::print() << name; - - for (bsl::safe_uintmax i{}; i < field_width - name.length(); ++i) { - bsl::print() << ' '; - } - - bsl::print() << bsl::yellow << " | " << bsl::reset_color; - bsl::print() << type; - bsl::print() << bsl::yellow << " | " << bsl::reset_color; - - if (val) { - if (val.is_zero()) { - bsl::print() << bsl::black << bsl::hex(val) << bsl::reset_color; - } - else { - bsl::print() << bsl::hex(val); - } - - if constexpr (bsl::is_same::value) { - bsl::print() << bsl::yellow << " |\n" << bsl::reset_color; - } - - if constexpr (bsl::is_same::value) { - bsl::print() << bsl::yellow << " |\n" << bsl::reset_color; - } - - if constexpr (bsl::is_same::value) { - bsl::print() << bsl::yellow << " |\n" << bsl::reset_color; - } - } - else { - bsl::print() << bsl::black << "unsupported " << bsl::reset_color; - bsl::print() << bsl::yellow << " |\n" << bsl::reset_color; - } - } - - /// - /// @brief Dumps the contents of a missing VMCS register to the - /// console. As a reminder, a missing register, is a register - /// that we need to keep track of manually and is missing from - /// the VMCS. - /// - /// - /// @param name the name of the register - /// @param type the register's type - /// @param value the value of the register - /// - constexpr void - dump_missing_register( - bsl::string_view const &name, - bsl::string_view const &type, - bsl::safe_uintmax const &value) noexcept - { - constexpr bsl::safe_uintmax field_width{bsl::to_umax(44)}; - - bsl::print() << bsl::yellow << "| " << bsl::reset_color; - bsl::print() << name; - - for (bsl::safe_uintmax i{}; i < field_width - name.length(); ++i) { - bsl::print() << ' '; - } - - bsl::print() << bsl::yellow << " | " << bsl::reset_color; - bsl::print() << type; - bsl::print() << bsl::yellow << " | " << bsl::reset_color; - - if (value.is_zero()) { - bsl::print() << bsl::black << bsl::hex(value) << bsl::reset_color; - } - else { - bsl::print() << bsl::hex(value); - } - - bsl::print() << bsl::yellow << " |\n" << bsl::reset_color; - } - - /// - /// @brief Dumps the contents of the VPS to the console - /// - /// - /// @tparam TLS_CONCEPT defines the type of TLS block to use /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise /// - template - constexpr void - dump(TLS_CONCEPT &tls) &noexcept + [[nodiscard]] constexpr auto + clear(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type { - /// TODO: - /// - Right now, we check for unsupported by reading a field - /// that might not exist, and if we get an error, we report - /// unsupported. This causes a write to the VMCS with an - /// error code, which is then logged forever, which could be - /// misleading if you happen to dump the same VPS more than - /// once. Instead, we really need some detection logic for - /// the fields that do not exist. - /// - Remove the quiet versions of the intrinsics are they - /// are not needed once you clean this up. - /// - Remove the extra read logic from the dump_vmcs_field code and - /// use read instead. - /// + bsl::errc_type ret{}; - constexpr bsl::string_view type_64bit_m{"64-bit M"}; - constexpr bsl::string_view type_16bit_c{"16-bit C"}; - constexpr bsl::string_view type_16bit_g{"16-bit G"}; - constexpr bsl::string_view type_16bit_h{"16-bit H"}; - constexpr bsl::string_view type_64bit_c{"64-bit C"}; - constexpr bsl::string_view type_64bit_r{"64-bit R"}; - constexpr bsl::string_view type_64bit_g{"64-bit G"}; - constexpr bsl::string_view type_64bit_h{"64-bit H"}; - constexpr bsl::string_view type_32bit_c{"32-bit C"}; - constexpr bsl::string_view type_32bit_r{"32-bit R"}; - constexpr bsl::string_view type_32bit_g{"32-bit G"}; - constexpr bsl::string_view type_32bit_h{"32-bit H"}; - - if constexpr (BSL_DEBUG_LEVEL == bsl::ZERO_UMAX) { - return; + if (bsl::unlikely_assert(!m_id)) { + bsl::error() << "vps_t not initialized\n" << bsl::here(); + return bsl::errc_precondition; } - if (bsl::unlikely(!m_allocated)) { - bsl::error() << "invalid vps\n" << bsl::here(); - return; + if (bsl::unlikely(m_allocated != allocated_status_t::allocated)) { + bsl::error() << "vps " // -- + << bsl::hex(m_id) // -- + << "'s status is not allocated and cannot be used" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; } - if (bsl::unlikely(!this->ensure_this_vps_is_loaded(tls))) { + if (bsl::unlikely(tls.ppid != m_assigned_ppid)) { + bsl::error() << "vp " // -- + << bsl::hex(m_id) // -- + << " is assigned to pp " // -- + << bsl::hex(m_assigned_ppid) // -- + << " and cannot be operated on by pp " // -- + << bsl::hex(tls.ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_precondition; + } + + ret = this->ensure_this_vps_is_loaded(tls, intrinsic); + if (bsl::unlikely_assert(!ret)) { bsl::print() << bsl::here(); + return ret; + } + + ret = intrinsic.vmclear(&m_vmcs_phys); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + ret = intrinsic.vmload(&m_vmcs_phys); + if (bsl::unlikely_assert(!ret)) { + bsl::print() << bsl::here(); + return ret; + } + + tls.loaded_vpsid = m_id.get(); + m_vmcs_missing_registers.launched = {}; + + return ret; + } + + /// + /// @brief Dumps the vm_t + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// + constexpr void + dump(tls_t &tls, intrinsic_t &intrinsic) const noexcept + { + bsl::discard(tls); + + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { return; } // clang-format off - bsl::print() << bsl::bold_magenta << "VPS" << bsl::reset_color; - bsl::print() << " [" << bsl::hex(m_id) << "] "; - bsl::print() << bsl::bold_magenta << "Dump: " << bsl::reset_color; - bsl::print() << bsl::yellow << bsl::endl; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; - bsl::print() << bsl::yellow << "| " << bsl::cyan; - bsl::print() << "Field "; - bsl::print() << bsl::yellow << "| " << bsl::cyan; - bsl::print() << "Type "; - bsl::print() << bsl::yellow << "| " << bsl::cyan; - bsl::print() << "Value "; - bsl::print() << bsl::yellow << "|" << bsl::reset_color << bsl::endl; - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + if (bsl::unlikely(!m_id)) { + bsl::print() << "[error]" << bsl::endl; + return; + } - this->dump_missing_register( - "rax", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_RAX)); - this->dump_missing_register( - "rbx", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_RBX)); - this->dump_missing_register( - "rcx", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_RCX)); - this->dump_missing_register( - "rdx", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_RDX)); - this->dump_missing_register( - "rbp", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_RBP)); - this->dump_missing_register( - "rsi", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_RSI)); - this->dump_missing_register( - "rdi", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_RDI)); - this->dump_missing_register( - "r8", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_R8)); - this->dump_missing_register( - "r9", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_R9)); - this->dump_missing_register( - "r10", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_R10)); - this->dump_missing_register( - "r11", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_R11)); - this->dump_missing_register( - "r12", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_R12)); - this->dump_missing_register( - "r13", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_R13)); - this->dump_missing_register( - "r14", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_R14)); - this->dump_missing_register( - "r15", type_64bit_m, m_intrinsic->tls_reg(syscall::TLS_OFFSET_R15)); + bsl::print() << bsl::mag << "vps ["; + bsl::print() << bsl::rst << bsl::hex(m_id); + bsl::print() << bsl::mag << "] dump: "; + bsl::print() << bsl::rst << bsl::endl; - this->dump_missing_register( - "cr2", type_64bit_m, m_vmcs_missing_registers.cr2); - this->dump_missing_register( - "dr6", type_64bit_m, m_vmcs_missing_registers.dr6); + /// Header + /// - this->dump_missing_register( - "guest_ia32_star", type_64bit_m, m_vmcs_missing_registers.guest_ia32_star); - this->dump_missing_register( - "guest_ia32_lstar", type_64bit_m, m_vmcs_missing_registers.guest_ia32_lstar); - this->dump_missing_register( - "guest_ia32_cstar", type_64bit_m, m_vmcs_missing_registers.guest_ia32_cstar); - this->dump_missing_register( - "guest_ia32_fmask", type_64bit_m, m_vmcs_missing_registers.guest_ia32_fmask); - this->dump_missing_register( - "guest_ia32_kernel_gs_base", type_64bit_m, m_vmcs_missing_registers.guest_ia32_kernel_gs_base); + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - this->dump_missing_register( - "host_ia32_star", type_64bit_m, m_vmcs_missing_registers.host_ia32_star); - this->dump_missing_register( - "host_ia32_lstar", type_64bit_m, m_vmcs_missing_registers.host_ia32_lstar); - this->dump_missing_register( - "host_ia32_cstar", type_64bit_m, m_vmcs_missing_registers.host_ia32_cstar); - this->dump_missing_register( - "host_ia32_fmask", type_64bit_m, m_vmcs_missing_registers.host_ia32_fmask); - this->dump_missing_register( - "host_ia32_kernel_gs_base", type_64bit_m, m_vmcs_missing_registers.host_ia32_kernel_gs_base); + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^40s", "description "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::cyn << bsl::fmt{"^19s", "value "}; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - this->dump_vmcs_field( - "vm_instruction_error", type_32bit_r, VMCS_VM_INSTRUCTION_ERROR); + /// Allocated + /// - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<40s", "allocated "}; + bsl::print() << bsl::ylw << "| "; + if (this->is_allocated()) { + bsl::print() << bsl::grn << bsl::fmt{"^19s", "yes "}; + } + else { + bsl::print() << bsl::red << bsl::fmt{"^19s", "no "}; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; - this->dump_vmcs_field( - "virtual_processor_identifier", type_16bit_c, VMCS_VIRTUAL_PROCESSOR_IDENTIFIER); - this->dump_vmcs_field( - "posted_interrupt_notification_vector", type_16bit_c, VMCS_POSTED_INTERRUPT_NOTIFICATION_VECTOR); - this->dump_vmcs_field( - "eptp_index", type_16bit_c, VMCS_EPTP_INDEX); + /// Assigned VP + /// - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<40s", "assigned vp "}; + bsl::print() << bsl::ylw << "| "; + if (m_assigned_vpid != syscall::BF_INVALID_ID) { + bsl::print() << bsl::grn << " " << bsl::hex(m_assigned_vpid) << " "; + } + else { + bsl::print() << bsl::red << " " << bsl::hex(m_assigned_vpid) << " "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; - this->dump_vmcs_field( - "guest_es_selector", type_16bit_g, VMCS_GUEST_ES_SELECTOR); - this->dump_vmcs_field( - "guest_cs_selector", type_16bit_g, VMCS_GUEST_CS_SELECTOR); - this->dump_vmcs_field( - "guest_ss_selector", type_16bit_g, VMCS_GUEST_SS_SELECTOR); - this->dump_vmcs_field( - "guest_ds_selector", type_16bit_g, VMCS_GUEST_DS_SELECTOR); - this->dump_vmcs_field( - "guest_fs_selector", type_16bit_g, VMCS_GUEST_FS_SELECTOR); - this->dump_vmcs_field( - "guest_gs_selector", type_16bit_g, VMCS_GUEST_GS_SELECTOR); - this->dump_vmcs_field( - "guest_ldtr_selector", type_16bit_g, VMCS_GUEST_LDTR_SELECTOR); - this->dump_vmcs_field( - "guest_tr_selector", type_16bit_g, VMCS_GUEST_TR_SELECTOR); - this->dump_vmcs_field( - "guest_interrupt_status", type_16bit_g, VMCS_GUEST_INTERRUPT_STATUS); - this->dump_vmcs_field( - "pml_index", type_16bit_g, VMCS_PML_INDEX); + /// Assigned PP + /// - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::fmt{"<40s", "assigned pp "}; + bsl::print() << bsl::ylw << "| "; + if (m_assigned_ppid != syscall::BF_INVALID_ID) { + bsl::print() << bsl::grn << " " << bsl::hex(m_assigned_ppid) << " "; + } + else { + bsl::print() << bsl::red << " " << bsl::hex(m_assigned_ppid) << " "; + } + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << bsl::endl; - this->dump_vmcs_field( - "host_es_selector", type_16bit_h, VMCS_HOST_ES_SELECTOR); - this->dump_vmcs_field( - "host_cs_selector", type_16bit_h, VMCS_HOST_CS_SELECTOR); - this->dump_vmcs_field( - "host_ss_selector", type_16bit_h, VMCS_HOST_SS_SELECTOR); - this->dump_vmcs_field( - "host_ds_selector", type_16bit_h, VMCS_HOST_DS_SELECTOR); - this->dump_vmcs_field( - "host_fs_selector", type_16bit_h, VMCS_HOST_FS_SELECTOR); - this->dump_vmcs_field( - "host_gs_selector", type_16bit_h, VMCS_HOST_GS_SELECTOR); - this->dump_vmcs_field( - "host_tr_selector", type_16bit_h, VMCS_HOST_TR_SELECTOR); + /// Guest Missing Fields + /// - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - this->dump_vmcs_field( - "address_of_io_bitmap_a", type_64bit_c, VMCS_ADDRESS_OF_IO_BITMAP_A); - this->dump_vmcs_field( - "address_of_io_bitmap_b", type_64bit_c, VMCS_ADDRESS_OF_IO_BITMAP_B); - this->dump_vmcs_field( - "address_of_msr_bitmaps", type_64bit_c, VMCS_ADDRESS_OF_MSR_BITMAPS); - this->dump_vmcs_field( - "vmexit_msr_store_address", type_64bit_c, VMCS_VMEXIT_MSR_STORE_ADDRESS); - this->dump_vmcs_field( - "vmexit_msr_load_address", type_64bit_c, VMCS_VMEXIT_MSR_LOAD_ADDRESS); - this->dump_vmcs_field( - "vmentry_msr_load_address", type_64bit_c, VMCS_VMENTRY_MSR_LOAD_ADDRESS); - this->dump_vmcs_field( - "executive_vmcs_pointer", type_64bit_c, VMCS_EXECUTIVE_VMCS_POINTER); - this->dump_vmcs_field( - "pml_address", type_64bit_c, VMCS_PML_ADDRESS); - this->dump_vmcs_field( - "tsc_offset", type_64bit_c, VMCS_TSC_OFFSET); - this->dump_vmcs_field( - "virtual_apic_address", type_64bit_c, VMCS_VIRTUAL_APIC_ADDRESS); - this->dump_vmcs_field( - "apic_access_address", type_64bit_c, VMCS_APIC_ACCESS_ADDRESS); - this->dump_vmcs_field( - "posted_interrupt_descriptor_address", type_64bit_c, VMCS_POSTED_INTERRUPT_DESCRIPTOR_ADDRESS); - this->dump_vmcs_field( - "vm_function_controls", type_64bit_c, VMCS_VM_FUNCTION_CONTROLS); - this->dump_vmcs_field( - "ept_pointer", type_64bit_c, VMCS_EPT_POINTER); - this->dump_vmcs_field( - "eoi_exit_bitmap0", type_64bit_c, VMCS_EOI_EXIT_BITMAP0); - this->dump_vmcs_field( - "eoi_exit_bitmap1", type_64bit_c, VMCS_EOI_EXIT_BITMAP1); - this->dump_vmcs_field( - "eoi_exit_bitmap2", type_64bit_c, VMCS_EOI_EXIT_BITMAP2); - this->dump_vmcs_field( - "eoi_exit_bitmap3", type_64bit_c, VMCS_EOI_EXIT_BITMAP3); - this->dump_vmcs_field( - "eptp_list_address", type_64bit_c, VMCS_EPTP_LIST_ADDRESS); - this->dump_vmcs_field( - "vmread_bitmap_address", type_64bit_c, VMCS_VMREAD_BITMAP_ADDRESS); - this->dump_vmcs_field( - "vmwrite_bitmap_address", type_64bit_c, VMCS_VMWRITE_BITMAP_ADDRESS); - this->dump_vmcs_field( - "virt_exception_information_address", type_64bit_c, VMCS_VIRT_EXCEPTION_INFORMATION_ADDRESS); - this->dump_vmcs_field( - "xss_exiting_bitmap", type_64bit_c, VMCS_XSS_EXITING_BITMAP); - this->dump_vmcs_field( - "encls_exiting_bitmap", type_64bit_c, VMCS_ENCLS_EXITING_BITMAP); - this->dump_vmcs_field( - "sub_page_permission_table_pointer", type_64bit_c, VMCS_SUB_PAGE_PERMISSION_TABLE_POINTER); - this->dump_vmcs_field( - "tls_multiplier", type_64bit_c, VMCS_TLS_MULTIPLIER); + if (!this->is_allocated()) { + return; + } - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + if (tls.active_vpsid == m_id) { + this->dump("rax ", intrinsic.tls_reg(syscall::TLS_OFFSET_RAX)); + this->dump("rbx ", intrinsic.tls_reg(syscall::TLS_OFFSET_RBX)); + this->dump("rcx ", intrinsic.tls_reg(syscall::TLS_OFFSET_RCX)); + this->dump("rdx ", intrinsic.tls_reg(syscall::TLS_OFFSET_RDX)); + this->dump("rbp ", intrinsic.tls_reg(syscall::TLS_OFFSET_RBP)); + this->dump("rsi ", intrinsic.tls_reg(syscall::TLS_OFFSET_RSI)); + this->dump("rdi ", intrinsic.tls_reg(syscall::TLS_OFFSET_RDI)); + this->dump("r8 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R8)); + this->dump("r9 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R9)); + this->dump("r10 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R10)); + this->dump("r11 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R11)); + this->dump("r12 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R12)); + this->dump("r13 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R13)); + this->dump("r14 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R14)); + this->dump("r15 ", intrinsic.tls_reg(syscall::TLS_OFFSET_R15)); + } + else { + this->dump("rax ", bsl::make_safe(m_gprs.rax)); + this->dump("rbx ", bsl::make_safe(m_gprs.rbx)); + this->dump("rcx ", bsl::make_safe(m_gprs.rcx)); + this->dump("rdx ", bsl::make_safe(m_gprs.rdx)); + this->dump("rbp ", bsl::make_safe(m_gprs.rbp)); + this->dump("rsi ", bsl::make_safe(m_gprs.rsi)); + this->dump("rdi ", bsl::make_safe(m_gprs.rdi)); + this->dump("r8 ", bsl::make_safe(m_gprs.r8)); + this->dump("r9 ", bsl::make_safe(m_gprs.r9)); + this->dump("r10 ", bsl::make_safe(m_gprs.r10)); + this->dump("r11 ", bsl::make_safe(m_gprs.r11)); + this->dump("r12 ", bsl::make_safe(m_gprs.r12)); + this->dump("r13 ", bsl::make_safe(m_gprs.r13)); + this->dump("r14 ", bsl::make_safe(m_gprs.r14)); + this->dump("r15 ", bsl::make_safe(m_gprs.r15)); + } - this->dump_vmcs_field( - "guest_physical_address", type_64bit_r, VMCS_GUEST_PHYSICAL_ADDRESS); + /// 16 Bit Control Fields + /// - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - this->dump_vmcs_field( - "vmcs_link_pointer", type_64bit_g, VMCS_VMCS_LINK_POINTER); - this->dump_vmcs_field( - "guest_ia32_debugctl", type_64bit_g, VMCS_GUEST_IA32_DEBUGCTL); - this->dump_vmcs_field( - "guest_ia32_pat", type_64bit_g, VMCS_GUEST_IA32_PAT); - this->dump_vmcs_field( - "guest_ia32_efer", type_64bit_g, VMCS_GUEST_IA32_EFER); - this->dump_vmcs_field( - "guest_ia32_perf_global_ctrl", type_64bit_g, VMCS_GUEST_IA32_PERF_GLOBAL_CTRL); - this->dump_vmcs_field( - "guest_pdpte0", type_64bit_g, VMCS_GUEST_PDPTE0); - this->dump_vmcs_field( - "guest_pdpte1", type_64bit_g, VMCS_GUEST_PDPTE1); - this->dump_vmcs_field( - "guest_pdpte2", type_64bit_g, VMCS_GUEST_PDPTE2); - this->dump_vmcs_field( - "guest_pdpte3", type_64bit_g, VMCS_GUEST_PDPTE3); - this->dump_vmcs_field( - "guest_ia32_bndcfgs", type_64bit_g, VMCS_GUEST_IA32_BNDCFGS); - this->dump_vmcs_field( - "guest_rtit_ctl", type_64bit_g, VMCS_GUEST_RTIT_CTL); + this->dump("virtual_processor_identifier ", intrinsic.vmread16_quiet(VMCS_VIRTUAL_PROCESSOR_IDENTIFIER)); + this->dump("posted_interrupt_notification_vector ", intrinsic.vmread16_quiet(VMCS_POSTED_INTERRUPT_NOTIFICATION_VECTOR)); + this->dump("eptp_index ", intrinsic.vmread16_quiet(VMCS_EPTP_INDEX)); - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + /// 16 Bit Guest Fields + /// - this->dump_vmcs_field( - "host_ia32_pat", type_64bit_h, VMCS_HOST_IA32_PAT); - this->dump_vmcs_field( - "host_ia32_efer", type_64bit_h, VMCS_HOST_IA32_EFER); - this->dump_vmcs_field( - "host_ia32_perf_global_ctrl", type_64bit_h, VMCS_HOST_IA32_PERF_GLOBAL_CTRL); + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + this->dump("es_selector ", intrinsic.vmread16_quiet(VMCS_GUEST_ES_SELECTOR)); + this->dump("cs_selector ", intrinsic.vmread16_quiet(VMCS_GUEST_CS_SELECTOR)); + this->dump("ss_selector ", intrinsic.vmread16_quiet(VMCS_GUEST_SS_SELECTOR)); + this->dump("ds_selector ", intrinsic.vmread16_quiet(VMCS_GUEST_DS_SELECTOR)); + this->dump("fs_selector ", intrinsic.vmread16_quiet(VMCS_GUEST_FS_SELECTOR)); + this->dump("gs_selector ", intrinsic.vmread16_quiet(VMCS_GUEST_GS_SELECTOR)); + this->dump("ldtr_selector ", intrinsic.vmread16_quiet(VMCS_GUEST_LDTR_SELECTOR)); + this->dump("tr_selector ", intrinsic.vmread16_quiet(VMCS_GUEST_TR_SELECTOR)); + this->dump("interrupt_status ", intrinsic.vmread16_quiet(VMCS_GUEST_INTERRUPT_STATUS)); + this->dump("pml_index ", intrinsic.vmread16_quiet(VMCS_PML_INDEX)); - this->dump_vmcs_field( - "pin_based_vm_execution_ctls", type_32bit_c, VMCS_PIN_BASED_VM_EXECUTION_CTLS); - this->dump_vmcs_field( - "primary_proc_based_vm_execution_ctls", type_32bit_c, VMCS_PRIMARY_PROC_BASED_VM_EXECUTION_CTLS); - this->dump_vmcs_field( - "exception_bitmap", type_32bit_c, VMCS_EXCEPTION_BITMAP); - this->dump_vmcs_field( - "page_fault_error_code_mask", type_32bit_c, VMCS_PAGE_FAULT_ERROR_CODE_MASK); - this->dump_vmcs_field( - "page_fault_error_code_match", type_32bit_c, VMCS_PAGE_FAULT_ERROR_CODE_MATCH); - this->dump_vmcs_field( - "cr3_target_count", type_32bit_c, VMCS_CR3_TARGET_COUNT); - this->dump_vmcs_field( - "vmexit_ctls", type_32bit_c, VMCS_VMEXIT_CTLS); - this->dump_vmcs_field( - "vmexit_msr_store_count", type_32bit_c, VMCS_VMEXIT_MSR_STORE_COUNT); - this->dump_vmcs_field( - "vmexit_msr_load_count", type_32bit_c, VMCS_VMEXIT_MSR_LOAD_COUNT); - this->dump_vmcs_field( - "vmentry_ctls", type_32bit_c, VMCS_VMENTRY_CTLS); - this->dump_vmcs_field( - "vmentry_msr_load_count", type_32bit_c, VMCS_VMENTRY_MSR_LOAD_COUNT); - this->dump_vmcs_field( - "vmentry_interrupt_information_field", type_32bit_c, VMCS_VMENTRY_INTERRUPT_INFORMATION_FIELD); - this->dump_vmcs_field( - "vmentry_exception_error_code", type_32bit_c, VMCS_VMENTRY_EXCEPTION_ERROR_CODE); - this->dump_vmcs_field( - "vmentry_instruction_length", type_32bit_c, VMCS_VMENTRY_INSTRUCTION_LENGTH); - this->dump_vmcs_field( - "tpr_threshold", type_32bit_c, VMCS_TPR_THRESHOLD); - this->dump_vmcs_field( - "secondary_proc_based_vm_execution_ctls", type_32bit_c, VMCS_SECONDARY_PROC_BASED_VM_EXECUTION_CTLS); - this->dump_vmcs_field( - "ple_gap", type_32bit_c, VMCS_PLE_GAP); - this->dump_vmcs_field( - "ple_window", type_32bit_c, VMCS_PLE_WINDOW); + /// 64 Bit Control Fields + /// - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - this->dump_vmcs_field( - "exit_reason", type_32bit_r, VMCS_EXIT_REASON); - this->dump_vmcs_field( - "vmexit_interruption_information", type_32bit_r, VMCS_VMEXIT_INTERRUPTION_INFORMATION); - this->dump_vmcs_field( - "vmexit_interruption_error_code", type_32bit_r, VMCS_VMEXIT_INTERRUPTION_ERROR_CODE); - this->dump_vmcs_field( - "idt_vectoring_information_field", type_32bit_r, VMCS_IDT_VECTORING_INFORMATION_FIELD); - this->dump_vmcs_field( - "idt_vectoring_error_code", type_32bit_r, VMCS_IDT_VECTORING_ERROR_CODE); - this->dump_vmcs_field( - "vmexit_instruction_length", type_32bit_r, VMCS_VMEXIT_INSTRUCTION_LENGTH); - this->dump_vmcs_field( - "vmexit_instruction_information", type_32bit_r, VMCS_VMEXIT_INSTRUCTION_INFORMATION); + this->dump("address_of_io_bitmap_a ", intrinsic.vmread64_quiet(VMCS_ADDRESS_OF_IO_BITMAP_A)); + this->dump("address_of_io_bitmap_b ", intrinsic.vmread64_quiet(VMCS_ADDRESS_OF_IO_BITMAP_B)); + this->dump("address_of_msr_bitmaps ", intrinsic.vmread64_quiet(VMCS_ADDRESS_OF_MSR_BITMAPS)); + this->dump("vmexit_msr_store_address ", intrinsic.vmread64_quiet(VMCS_VMEXIT_MSR_STORE_ADDRESS)); + this->dump("vmexit_msr_load_address ", intrinsic.vmread64_quiet(VMCS_VMEXIT_MSR_LOAD_ADDRESS)); + this->dump("vmentry_msr_load_address ", intrinsic.vmread64_quiet(VMCS_VMENTRY_MSR_LOAD_ADDRESS)); + this->dump("executive_vmcs_pointer ", intrinsic.vmread64_quiet(VMCS_EXECUTIVE_VMCS_POINTER)); + this->dump("pml_address ", intrinsic.vmread64_quiet(VMCS_PML_ADDRESS)); + this->dump("tsc_offset ", intrinsic.vmread64_quiet(VMCS_TSC_OFFSET)); + this->dump("virtual_apic_address ", intrinsic.vmread64_quiet(VMCS_VIRTUAL_APIC_ADDRESS)); + this->dump("apic_access_address ", intrinsic.vmread64_quiet(VMCS_APIC_ACCESS_ADDRESS)); + this->dump("posted_interrupt_descriptor_address ", intrinsic.vmread64_quiet(VMCS_POSTED_INTERRUPT_DESCRIPTOR_ADDRESS)); + this->dump("vm_function_controls ", intrinsic.vmread64_quiet(VMCS_VM_FUNCTION_CONTROLS)); + this->dump("ept_pointer ", intrinsic.vmread64_quiet(VMCS_EPT_POINTER)); + this->dump("eoi_exit_bitmap0 ", intrinsic.vmread64_quiet(VMCS_EOI_EXIT_BITMAP0)); + this->dump("eoi_exit_bitmap1 ", intrinsic.vmread64_quiet(VMCS_EOI_EXIT_BITMAP1)); + this->dump("eoi_exit_bitmap2 ", intrinsic.vmread64_quiet(VMCS_EOI_EXIT_BITMAP2)); + this->dump("eoi_exit_bitmap3 ", intrinsic.vmread64_quiet(VMCS_EOI_EXIT_BITMAP3)); + this->dump("eptp_list_address ", intrinsic.vmread64_quiet(VMCS_EPTP_LIST_ADDRESS)); + this->dump("vmread_bitmap_address ", intrinsic.vmread64_quiet(VMCS_VMREAD_BITMAP_ADDRESS)); + this->dump("vmwrite_bitmap_address ", intrinsic.vmread64_quiet(VMCS_VMWRITE_BITMAP_ADDRESS)); + this->dump("virt_exception_information_address ", intrinsic.vmread64_quiet(VMCS_VIRT_EXCEPTION_INFORMATION_ADDRESS)); + this->dump("xss_exiting_bitmap ", intrinsic.vmread64_quiet(VMCS_XSS_EXITING_BITMAP)); + this->dump("encls_exiting_bitmap ", intrinsic.vmread64_quiet(VMCS_ENCLS_EXITING_BITMAP)); + this->dump("sub_page_permission_table_pointer ", intrinsic.vmread64_quiet(VMCS_SUB_PAGE_PERMISSION_TABLE_POINTER)); + this->dump("tls_multiplier ", intrinsic.vmread64_quiet(VMCS_TLS_MULTIPLIER)); - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + /// 64 Bit Read-Only Fields + /// - this->dump_vmcs_field( - "guest_es_limit", type_32bit_g, VMCS_GUEST_ES_LIMIT); - this->dump_vmcs_field( - "guest_cs_limit", type_32bit_g, VMCS_GUEST_CS_LIMIT); - this->dump_vmcs_field( - "guest_ss_limit", type_32bit_g, VMCS_GUEST_SS_LIMIT); - this->dump_vmcs_field( - "guest_ds_limit", type_32bit_g, VMCS_GUEST_DS_LIMIT); - this->dump_vmcs_field( - "guest_fs_limit", type_32bit_g, VMCS_GUEST_FS_LIMIT); - this->dump_vmcs_field( - "guest_gs_limit", type_32bit_g, VMCS_GUEST_GS_LIMIT); - this->dump_vmcs_field( - "guest_ldtr_limit", type_32bit_g, VMCS_GUEST_LDTR_LIMIT); - this->dump_vmcs_field( - "guest_tr_limit", type_32bit_g, VMCS_GUEST_TR_LIMIT); - this->dump_vmcs_field( - "guest_gdtr_limit", type_32bit_g, VMCS_GUEST_GDTR_LIMIT); - this->dump_vmcs_field( - "guest_idtr_limit", type_32bit_g, VMCS_GUEST_IDTR_LIMIT); - this->dump_vmcs_field( - "guest_es_access_rights", type_32bit_g, VMCS_GUEST_ES_ACCESS_RIGHTS); - this->dump_vmcs_field( - "guest_cs_access_rights", type_32bit_g, VMCS_GUEST_CS_ACCESS_RIGHTS); - this->dump_vmcs_field( - "guest_ss_access_rights", type_32bit_g, VMCS_GUEST_SS_ACCESS_RIGHTS); - this->dump_vmcs_field( - "guest_ds_access_rights", type_32bit_g, VMCS_GUEST_DS_ACCESS_RIGHTS); - this->dump_vmcs_field( - "guest_fs_access_rights", type_32bit_g, VMCS_GUEST_FS_ACCESS_RIGHTS); - this->dump_vmcs_field( - "guest_gs_access_rights", type_32bit_g, VMCS_GUEST_GS_ACCESS_RIGHTS); - this->dump_vmcs_field( - "guest_ldtr_access_rights", type_32bit_g, VMCS_GUEST_LDTR_ACCESS_RIGHTS); - this->dump_vmcs_field( - "guest_tr_access_rights", type_32bit_g, VMCS_GUEST_TR_ACCESS_RIGHTS); - this->dump_vmcs_field( - "guest_interruptibility_state", type_32bit_g, VMCS_GUEST_INTERRUPTIBILITY_STATE); - this->dump_vmcs_field( - "guest_activity_state", type_32bit_g, VMCS_GUEST_ACTIVITY_STATE); - this->dump_vmcs_field( - "guest_smbase", type_32bit_g, VMCS_GUEST_SMBASE); - this->dump_vmcs_field( - "guest_ia32_sysenter_cs", type_32bit_g, VMCS_GUEST_IA32_SYSENTER_CS); - this->dump_vmcs_field( - "vmx_preemption_timer_value", type_32bit_g, VMCS_VMX_PREEMPTION_TIMER_VALUE); + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + this->dump("guest_physical_address ", intrinsic.vmread64_quiet(VMCS_GUEST_PHYSICAL_ADDRESS)); - this->dump_vmcs_field( - "host_ia32_sysenter_cs", type_32bit_h, VMCS_HOST_IA32_SYSENTER_CS); + /// 64 Bit Guest Fields + /// - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - this->dump_vmcs_field( - "cr0_guest_host_mask", type_64bit_c, VMCS_CR0_GUEST_HOST_MASK); - this->dump_vmcs_field( - "cr4_guest_host_mask", type_64bit_c, VMCS_CR4_GUEST_HOST_MASK); - this->dump_vmcs_field( - "cr0_read_shadow", type_64bit_c, VMCS_CR0_READ_SHADOW); - this->dump_vmcs_field( - "cr4_read_shadow", type_64bit_c, VMCS_CR4_READ_SHADOW); - this->dump_vmcs_field( - "cr3_target_value0", type_64bit_c, VMCS_CR3_TARGET_VALUE0); - this->dump_vmcs_field( - "cr3_target_value1", type_64bit_c, VMCS_CR3_TARGET_VALUE1); - this->dump_vmcs_field( - "cr3_target_value2", type_64bit_c, VMCS_CR3_TARGET_VALUE2); - this->dump_vmcs_field( - "cr3_target_value3", type_64bit_c, VMCS_CR3_TARGET_VALUE3); + this->dump("vmcs_link_pointer ", intrinsic.vmread64_quiet(VMCS_VMCS_LINK_POINTER)); + this->dump("ia32_debugctl ", intrinsic.vmread64_quiet(VMCS_GUEST_IA32_DEBUGCTL)); + this->dump("ia32_pat ", intrinsic.vmread64_quiet(VMCS_GUEST_IA32_PAT)); + this->dump("ia32_efer ", intrinsic.vmread64_quiet(VMCS_GUEST_IA32_EFER)); + this->dump("ia32_perf_global_ctrl ", intrinsic.vmread64_quiet(VMCS_GUEST_IA32_PERF_GLOBAL_CTRL)); + this->dump("guest_pdpte0 ", intrinsic.vmread64_quiet(VMCS_GUEST_PDPTE0)); + this->dump("guest_pdpte1 ", intrinsic.vmread64_quiet(VMCS_GUEST_PDPTE1)); + this->dump("guest_pdpte2 ", intrinsic.vmread64_quiet(VMCS_GUEST_PDPTE2)); + this->dump("guest_pdpte3 ", intrinsic.vmread64_quiet(VMCS_GUEST_PDPTE3)); + this->dump("ia32_bndcfgs ", intrinsic.vmread64_quiet(VMCS_GUEST_IA32_BNDCFGS)); + this->dump("guest_rtit_ctl ", intrinsic.vmread64_quiet(VMCS_GUEST_RTIT_CTL)); + this->dump("ia32_star ", bsl::make_safe(m_vmcs_missing_registers.guest_ia32_star)); + this->dump("ia32_lstar ", bsl::make_safe(m_vmcs_missing_registers.guest_ia32_lstar)); + this->dump("ia32_cstar ", bsl::make_safe(m_vmcs_missing_registers.guest_ia32_cstar)); + this->dump("ia32_fmask ", bsl::make_safe(m_vmcs_missing_registers.guest_ia32_fmask)); + this->dump("ia32_kernel_gs_base ", bsl::make_safe(m_vmcs_missing_registers.guest_ia32_kernel_gs_base)); - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + /// 32 Bit Control Fields + /// - this->dump_vmcs_field( - "exit_qualification", type_64bit_r, VMCS_EXIT_QUALIFICATION); - this->dump_vmcs_field( - "io_rcx", type_64bit_r, VMCS_IO_RCX); - this->dump_vmcs_field( - "io_rsi", type_64bit_r, VMCS_IO_RSI); - this->dump_vmcs_field( - "io_rdi", type_64bit_r, VMCS_IO_RDI); - this->dump_vmcs_field( - "io_rip", type_64bit_r, VMCS_IO_RIP); - this->dump_vmcs_field( - "guest_linear_address", type_64bit_r, VMCS_GUEST_LINEAR_ADDRESS); + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + this->dump("pin_based_vm_execution_ctls ", intrinsic.vmread32_quiet(VMCS_PIN_BASED_VM_EXECUTION_CTLS)); + this->dump("primary_proc_based_vm_execution_ctls ", intrinsic.vmread32_quiet(VMCS_PRIMARY_PROC_BASED_VM_EXECUTION_CTLS)); + this->dump("exception_bitmap ", intrinsic.vmread32_quiet(VMCS_EXCEPTION_BITMAP)); + this->dump("page_fault_error_code_mask ", intrinsic.vmread32_quiet(VMCS_PAGE_FAULT_ERROR_CODE_MASK)); + this->dump("page_fault_error_code_match ", intrinsic.vmread32_quiet(VMCS_PAGE_FAULT_ERROR_CODE_MATCH)); + this->dump("cr3_target_count ", intrinsic.vmread32_quiet(VMCS_CR3_TARGET_COUNT)); + this->dump("vmexit_ctls ", intrinsic.vmread32_quiet(VMCS_VMEXIT_CTLS)); + this->dump("vmexit_msr_store_count ", intrinsic.vmread32_quiet(VMCS_VMEXIT_MSR_STORE_COUNT)); + this->dump("vmexit_msr_load_count ", intrinsic.vmread32_quiet(VMCS_VMEXIT_MSR_LOAD_COUNT)); + this->dump("vmentry_ctls ", intrinsic.vmread32_quiet(VMCS_VMENTRY_CTLS)); + this->dump("vmentry_msr_load_count ", intrinsic.vmread32_quiet(VMCS_VMENTRY_MSR_LOAD_COUNT)); + this->dump("vmentry_interrupt_information_field ", intrinsic.vmread32_quiet(VMCS_VMENTRY_INTERRUPT_INFORMATION_FIELD)); + this->dump("vmentry_exception_error_code ", intrinsic.vmread32_quiet(VMCS_VMENTRY_EXCEPTION_ERROR_CODE)); + this->dump("vmentry_instruction_length ", intrinsic.vmread32_quiet(VMCS_VMENTRY_INSTRUCTION_LENGTH)); + this->dump("tpr_threshold ", intrinsic.vmread32_quiet(VMCS_TPR_THRESHOLD)); + this->dump("secondary_proc_based_vm_execution_ctls ", intrinsic.vmread32_quiet(VMCS_SECONDARY_PROC_BASED_VM_EXECUTION_CTLS)); + this->dump("ple_gap ", intrinsic.vmread32_quiet(VMCS_PLE_GAP)); + this->dump("ple_window ", intrinsic.vmread32_quiet(VMCS_PLE_WINDOW)); - this->dump_vmcs_field( - "guest_cr0", type_64bit_g, VMCS_GUEST_CR0); - this->dump_vmcs_field( - "guest_cr3", type_64bit_g, VMCS_GUEST_CR3); - this->dump_vmcs_field( - "guest_cr4", type_64bit_g, VMCS_GUEST_CR4); - this->dump_vmcs_field( - "guest_es_base", type_64bit_g, VMCS_GUEST_ES_BASE); - this->dump_vmcs_field( - "guest_cs_base", type_64bit_g, VMCS_GUEST_CS_BASE); - this->dump_vmcs_field( - "guest_ss_base", type_64bit_g, VMCS_GUEST_SS_BASE); - this->dump_vmcs_field( - "guest_ds_base", type_64bit_g, VMCS_GUEST_DS_BASE); - this->dump_vmcs_field( - "guest_fs_base", type_64bit_g, VMCS_GUEST_FS_BASE); - this->dump_vmcs_field( - "guest_gs_base", type_64bit_g, VMCS_GUEST_GS_BASE); - this->dump_vmcs_field( - "guest_ldtr_base", type_64bit_g, VMCS_GUEST_LDTR_BASE); - this->dump_vmcs_field( - "guest_tr_base", type_64bit_g, VMCS_GUEST_TR_BASE); - this->dump_vmcs_field( - "guest_gdtr_base", type_64bit_g, VMCS_GUEST_GDTR_BASE); - this->dump_vmcs_field( - "guest_idtr_base", type_64bit_g, VMCS_GUEST_IDTR_BASE); - this->dump_vmcs_field( - "guest_dr7", type_64bit_g, VMCS_GUEST_DR7); - this->dump_vmcs_field( - "guest_rsp", type_64bit_g, VMCS_GUEST_RSP); - this->dump_vmcs_field( - "guest_rip", type_64bit_g, VMCS_GUEST_RIP); - this->dump_vmcs_field( - "guest_rflags", type_64bit_g, VMCS_GUEST_RFLAGS); - this->dump_vmcs_field( - "guest_pending_debug_exceptions", type_64bit_g, VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS); - this->dump_vmcs_field( - "guest_ia32_sysenter_esp", type_64bit_g, VMCS_GUEST_IA32_SYSENTER_ESP); - this->dump_vmcs_field( - "guest_ia32_sysenter_eip", type_64bit_g, VMCS_GUEST_IA32_SYSENTER_EIP); + /// 32 Bit Read-Only Fields + /// - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; - this->dump_vmcs_field( - "host_cr0", type_64bit_h, VMCS_HOST_CR0); - this->dump_vmcs_field( - "host_cr3", type_64bit_h, VMCS_HOST_CR3); - this->dump_vmcs_field( - "host_cr4", type_64bit_h, VMCS_HOST_CR4); - this->dump_vmcs_field( - "host_fs_base", type_64bit_h, VMCS_HOST_FS_BASE); - this->dump_vmcs_field( - "host_gs_base", type_64bit_h, VMCS_HOST_GS_BASE); - this->dump_vmcs_field( - "host_tr_base", type_64bit_h, VMCS_HOST_TR_BASE); - this->dump_vmcs_field( - "host_gdtr_base", type_64bit_h, VMCS_HOST_GDTR_BASE); - this->dump_vmcs_field( - "host_idtr_base", type_64bit_h, VMCS_HOST_IDTR_BASE); - this->dump_vmcs_field( - "host_ia32_sysenter_esp", type_64bit_h, VMCS_HOST_IA32_SYSENTER_ESP); - this->dump_vmcs_field( - "host_ia32_sysenter_eip", type_64bit_h, VMCS_HOST_IA32_SYSENTER_EIP); - this->dump_vmcs_field( - "host_rsp", type_64bit_h, VMCS_HOST_RSP); - this->dump_vmcs_field( - "host_rip", type_64bit_h, VMCS_HOST_RIP); + this->dump("exit_reason ", intrinsic.vmread32_quiet(VMCS_EXIT_REASON)); + this->dump("vmexit_interruption_information ", intrinsic.vmread32_quiet(VMCS_VMEXIT_INTERRUPTION_INFORMATION)); + this->dump("vmexit_interruption_error_code ", intrinsic.vmread32_quiet(VMCS_VMEXIT_INTERRUPTION_ERROR_CODE)); + this->dump("idt_vectoring_information_field ", intrinsic.vmread32_quiet(VMCS_IDT_VECTORING_INFORMATION_FIELD)); + this->dump("idt_vectoring_error_code ", intrinsic.vmread32_quiet(VMCS_IDT_VECTORING_ERROR_CODE)); + this->dump("vmexit_instruction_length ", intrinsic.vmread32_quiet(VMCS_VMEXIT_INSTRUCTION_LENGTH)); + this->dump("vmexit_instruction_information ", intrinsic.vmread32_quiet(VMCS_VMEXIT_INSTRUCTION_INFORMATION)); - bsl::print() << bsl::yellow; - bsl::print() << "+---------------------------------------"; - bsl::print() << "---------------------------------------+"; - bsl::print() << bsl::reset_color << bsl::endl; + /// 32 Bit Guest Fields + /// + + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + this->dump("es_limit ", intrinsic.vmread32_quiet(VMCS_GUEST_ES_LIMIT)); + this->dump("cs_limit ", intrinsic.vmread32_quiet(VMCS_GUEST_CS_LIMIT)); + this->dump("ss_limit ", intrinsic.vmread32_quiet(VMCS_GUEST_SS_LIMIT)); + this->dump("ds_limit ", intrinsic.vmread32_quiet(VMCS_GUEST_DS_LIMIT)); + this->dump("fs_limit ", intrinsic.vmread32_quiet(VMCS_GUEST_FS_LIMIT)); + this->dump("gs_limit ", intrinsic.vmread32_quiet(VMCS_GUEST_GS_LIMIT)); + this->dump("ldtr_limit ", intrinsic.vmread32_quiet(VMCS_GUEST_LDTR_LIMIT)); + this->dump("tr_limit ", intrinsic.vmread32_quiet(VMCS_GUEST_TR_LIMIT)); + this->dump("gdtr_limit ", intrinsic.vmread32_quiet(VMCS_GUEST_GDTR_LIMIT)); + this->dump("idtr_limit ", intrinsic.vmread32_quiet(VMCS_GUEST_IDTR_LIMIT)); + this->dump("es_access_rights ", intrinsic.vmread32_quiet(VMCS_GUEST_ES_ACCESS_RIGHTS)); + this->dump("cs_access_rights ", intrinsic.vmread32_quiet(VMCS_GUEST_CS_ACCESS_RIGHTS)); + this->dump("ss_access_rights ", intrinsic.vmread32_quiet(VMCS_GUEST_SS_ACCESS_RIGHTS)); + this->dump("ds_access_rights ", intrinsic.vmread32_quiet(VMCS_GUEST_DS_ACCESS_RIGHTS)); + this->dump("fs_access_rights ", intrinsic.vmread32_quiet(VMCS_GUEST_FS_ACCESS_RIGHTS)); + this->dump("gs_access_rights ", intrinsic.vmread32_quiet(VMCS_GUEST_GS_ACCESS_RIGHTS)); + this->dump("ldtr_access_rights ", intrinsic.vmread32_quiet(VMCS_GUEST_LDTR_ACCESS_RIGHTS)); + this->dump("tr_access_rights ", intrinsic.vmread32_quiet(VMCS_GUEST_TR_ACCESS_RIGHTS)); + this->dump("guest_interruptibility_state ", intrinsic.vmread32_quiet(VMCS_GUEST_INTERRUPTIBILITY_STATE)); + this->dump("guest_activity_state ", intrinsic.vmread32_quiet(VMCS_GUEST_ACTIVITY_STATE)); + this->dump("guest_smbase ", intrinsic.vmread32_quiet(VMCS_GUEST_SMBASE)); + this->dump("ia32_sysenter_cs ", intrinsic.vmread32_quiet(VMCS_GUEST_IA32_SYSENTER_CS)); + this->dump("vmx_preemption_timer_value ", intrinsic.vmread32_quiet(VMCS_VMX_PREEMPTION_TIMER_VALUE)); + + /// Natural-Width Control Fields + /// + + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + this->dump("cr0_guest_host_mask ", intrinsic.vmread64_quiet(VMCS_CR0_GUEST_HOST_MASK)); + this->dump("cr4_guest_host_mask ", intrinsic.vmread64_quiet(VMCS_CR4_GUEST_HOST_MASK)); + this->dump("cr0_read_shadow ", intrinsic.vmread64_quiet(VMCS_CR0_READ_SHADOW)); + this->dump("cr4_read_shadow ", intrinsic.vmread64_quiet(VMCS_CR4_READ_SHADOW)); + this->dump("cr3_target_value0 ", intrinsic.vmread64_quiet(VMCS_CR3_TARGET_VALUE0)); + this->dump("cr3_target_value1 ", intrinsic.vmread64_quiet(VMCS_CR3_TARGET_VALUE1)); + this->dump("cr3_target_value2 ", intrinsic.vmread64_quiet(VMCS_CR3_TARGET_VALUE2)); + this->dump("cr3_target_value3 ", intrinsic.vmread64_quiet(VMCS_CR3_TARGET_VALUE3)); + + /// Natural-Width Read-Only Fields + /// + + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + this->dump("exit_qualification ", intrinsic.vmread64_quiet(VMCS_EXIT_QUALIFICATION)); + this->dump("io_rcx ", intrinsic.vmread64_quiet(VMCS_IO_RCX)); + this->dump("io_rsi ", intrinsic.vmread64_quiet(VMCS_IO_RSI)); + this->dump("io_rdi ", intrinsic.vmread64_quiet(VMCS_IO_RDI)); + this->dump("io_rip ", intrinsic.vmread64_quiet(VMCS_IO_RIP)); + this->dump("guest_linear_address ", intrinsic.vmread64_quiet(VMCS_GUEST_LINEAR_ADDRESS)); + + /// Natural-Width Guest Fields + /// + + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + this->dump("cr0 ", intrinsic.vmread64_quiet(VMCS_GUEST_CR0)); + this->dump("cr2 ", bsl::make_safe(m_vmcs_missing_registers.cr2)); + this->dump("cr3 ", intrinsic.vmread64_quiet(VMCS_GUEST_CR3)); + this->dump("cr4 ", intrinsic.vmread64_quiet(VMCS_GUEST_CR4)); + this->dump("es_base ", intrinsic.vmread64_quiet(VMCS_GUEST_ES_BASE)); + this->dump("cs_base ", intrinsic.vmread64_quiet(VMCS_GUEST_CS_BASE)); + this->dump("ss_base ", intrinsic.vmread64_quiet(VMCS_GUEST_SS_BASE)); + this->dump("ds_base ", intrinsic.vmread64_quiet(VMCS_GUEST_DS_BASE)); + this->dump("fs_base ", intrinsic.vmread64_quiet(VMCS_GUEST_FS_BASE)); + this->dump("gs_base ", intrinsic.vmread64_quiet(VMCS_GUEST_GS_BASE)); + this->dump("ldtr_base ", intrinsic.vmread64_quiet(VMCS_GUEST_LDTR_BASE)); + this->dump("tr_base ", intrinsic.vmread64_quiet(VMCS_GUEST_TR_BASE)); + this->dump("gdtr_base ", intrinsic.vmread64_quiet(VMCS_GUEST_GDTR_BASE)); + this->dump("idtr_base ", intrinsic.vmread64_quiet(VMCS_GUEST_IDTR_BASE)); + this->dump("dr6 ", bsl::make_safe(m_vmcs_missing_registers.dr6)); + this->dump("dr7 ", intrinsic.vmread64_quiet(VMCS_GUEST_DR7)); + this->dump("rsp ", intrinsic.vmread64_quiet(VMCS_GUEST_RSP)); + this->dump("rip ", intrinsic.vmread64_quiet(VMCS_GUEST_RIP)); + this->dump("rflags ", intrinsic.vmread64_quiet(VMCS_GUEST_RFLAGS)); + this->dump("guest_pending_debug_exceptions ", intrinsic.vmread64_quiet(VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS)); + this->dump("ia32_sysenter_esp ", intrinsic.vmread64_quiet(VMCS_GUEST_IA32_SYSENTER_ESP)); + this->dump("ia32_sysenter_eip ", intrinsic.vmread64_quiet(VMCS_GUEST_IA32_SYSENTER_EIP)); + + /// Footer + /// + + bsl::print() << bsl::ylw << "+--------------------------------------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + // clang-format on } }; } diff --git a/kernel/src/x64/mk_main_entry.S b/kernel/src/x64/mk_main_entry.S index 41e1c415..dcab61b6 100644 --- a/kernel/src/x64/mk_main_entry.S +++ b/kernel/src/x64/mk_main_entry.S @@ -24,6 +24,61 @@ * SOFTWARE. */ + /** @brief defines the offset of mk_args_t.ppid */ + #define ARGS_OFFSET_PPID 0x0 + /** @brief defines the offset of mk_args_t.online_pps */ + #define ARGS_OFFSET_ONLINE_PPS 0x002 + /** @brief defines the offset of mk_args_t.mk_state */ + #define ARGS_OFFSET_MK_STATE 0x008 + /** @brief defines the offset of mk_args_t.root_vp_state */ + #define ARGS_OFFSET_ROOT_VP_STATE 0x010 + /** @brief defines the offset of mk_args_t.debug_ring */ + #define ARGS_OFFSET_DEBUG_RING 0x018 + + /** @brief defines the size of the TLS block */ + #define TLS_SIZE 0x300 + /** @brief defines the offset of tls_t.current_fast_fail_ip */ + #define TLS_OFFSET_CURRENT_FAST_FAIL_IP 0x180 + /** @brief defines the offset of tls_t.current_fast_fail_sp */ + #define TLS_OFFSET_CURRENT_FAST_FAIL_SP 0x188 + /** @brief defines the offset of tls_t.mk_main_fast_fail_ip */ + #define TLS_OFFSET_MK_MAIN_FAST_FAIL_IP 0x190 + /** @brief defines the offset of tls_t.mk_main_fast_fail_sp */ + #define TLS_OFFSET_MK_MAIN_FAST_FAIL_SP 0x198 + /** @brief defines the offset of tls_t.call_ext_fast_fail_ip */ + #define TLS_OFFSET_CALL_EXT_FAST_FAIL_IP 0x1A0 + /** @brief defines the offset of tls_t.dispatch_syscall_fast_fail_ip */ + #define TLS_OFFSET_DISPATCH_SYSCALL_FAST_FAIL_IP 0x1B0 + /** @brief defines the offset of tls_t.self */ + #define TLS_OFFSET_SELF 0x200 + /** @brief defines the offset of tls_t.ppid */ + #define TLS_OFFSET_PPID 0x208 + /** @brief defines the offset of tls_t.online_pps */ + #define TLS_OFFSET_ONLINE_PPS 0x20A + /** @brief defines the offset of tls_t.loaded_vpsid */ + #define TLS_OFFSET_LOADED_VPSID 0x20C + /** @brief defines the offset of tls_t.mk_state */ + #define TLS_OFFSET_MK_STATE 0x228 + /** @brief defines the offset of tls_t.root_vp_state */ + #define TLS_OFFSET_ROOT_VP_STATE 0x230 + /** @brief defines the offset of tls_t.active_<>id */ + #define TLS_OFFSET_ACTIVE_IDS 0x238 + /** @brief defines the offset of tls_t.nmi_lock */ + #define TLS_OFFSET_NMI_LOCK 0x258 + /** @brief defines the offset of tls_t.nmi_pending */ + #define TLS_OFFSET_NMI_PENDING 0x260 + + /** @brief defines the offset of state_save_t.nmi */ + #define SS_OFFSET_NMI 0x318 + + /** @brief defines MSR_IA32_LSTAR */ + #define MSR_IA32_LSTAR 0xC0000082 + /** @brief defines MSR_IA32_GS_BASE */ + #define MSR_IA32_GS_BASE 0xC0000101 + + /** @brief defines invalid ids for all of the active ids */ + #define INVALID_IDS 0xFFFFFFFFFFFFFFFF + .code64 .intel_syntax noprefix @@ -31,55 +86,141 @@ .type mk_main_entry, @function mk_main_entry: + /** + * NOTE: + * - The first thing we need to do is save off RDI for the fast fail + * handler. If it is called, it will need the args that this function + * was provided, so we leave this on the stack for it. Since the state + * save has the correct stack pointer, we can leave it in this state + * as a safe return that uses the Root VP state will use the correct + * stack pointer, while a failure will use the current stack pointer + * with this return address on it. + */ + push rdi /** - * TODO: - * - Comment this code + * NOTE: + * - The next thing to do is get the TLS block for this PP. Each PP has + * it's own TLS block (both in the microkernel, and in each extension) + * which means that our definition of a thread is similar to that of + * Intel's and AMD's, meaning each logical core is a thread. + * - The loader will tell us in the args that it provided what the PPID + * is. Remember that this entry point will be called for each PP, so it + * is called more than once. Once we have the PPID, we can calculate + * which TLS block to grab based on the size of each TLS block. */ - mov r10, [rdi] - mov rdx, 0x000000000000FFFF - and r10, rdx + xor rbx, rbx + mov bx, [rdi + ARGS_OFFSET_PPID] - mov rax, r10 - mov rdx, 0x300 + mov rax, rbx + mov rdx, TLS_SIZE mul rdx lea rsi, [rip + g_tls_blocks] add rsi, rax - mov ecx, 0xC0000101 + /** + * NOTE: + * - Next we program GS with the location of the TLS block so that we + * can index into the TLS block using GS. + */ + + mov ecx, MSR_IA32_GS_BASE mov rax, rsi mov rdx, rsi shr rdx, 32 wrmsr - push rsi - push rdi + /** + * NOTE: + * - From here we need to set the "self" pointer in the TLS block as + * well as the PPID to the TLS block so that we always know what the + * PPID is no matter where we are. + */ - mov rax, r10 - mov rdx, 0xFFFFFFFFFFFF0000 - or rax, rdx + mov gs:[TLS_OFFSET_SELF], rsi + mov gs:[TLS_OFFSET_PPID], bx - mov gs:[0x200], rsi - mov gs:[0x208], rax + /** + * NOTE: + * - To start, there are no active extensions, VMs, VPs or VPSs. + */ + + mov rax, INVALID_IDS + mov gs:[TLS_OFFSET_ACTIVE_IDS], rax + + /** + * NOTE: + * - Next we set some of the fast fail entry points in the TLS block. + * These will be used when an error or exception occurs so that + * we can gracefully handle issues. + */ lea rax, [rip + mk_main_fast_fail_entry] - mov gs:[0x190], rax + mov gs:[TLS_OFFSET_MK_MAIN_FAST_FAIL_IP], rax lea rax, [rip + call_ext_fast_fail_entry] - mov gs:[0x1A0], rax + mov gs:[TLS_OFFSET_CALL_EXT_FAST_FAIL_IP], rax lea rax, [rip + dispatch_syscall_fast_fail_entry] - mov gs:[0x1B0], rax + mov gs:[TLS_OFFSET_DISPATCH_SYSCALL_FAST_FAIL_IP], rax - mov rax, [rdi + 0x008] - mov gs:[0x228], rax - mov rax, [rdi + 0x010] - mov gs:[0x230], rax + /** + * NOTE: + * - Next we need to set the number of online PPs on the system. + * The microkernel will need to know this so that it can properly set + * up it's internal resources. + */ + mov ax, [rdi + ARGS_OFFSET_ONLINE_PPS] + mov gs:[TLS_OFFSET_ONLINE_PPS], ax + + /** + * NOTE: + * - Next we need to invalidate the loaded VPSID. This is only used on + * Intel CPUs and is used to determine which VMCS is currently loaded. + * We cannot use the active VPSID here because an extension can read + * and write to any VPS it wants, even if it is not active. + */ + + mov rax, INVALID_IDS + mov gs:[TLS_OFFSET_LOADED_VPSID], ax + + /** + * NOTE: + * - Next we store the location of the MK and Root VP state save areas + * that the loader created for us. For the most part, we only really + * need the Root VP state as we will use this to return back to the + * Root VP once we start the hypervisor on this PP, but just in case, + * we also provide the MK state as well. In general, the microkernel + * is really unware of the state that the loader gives it. + */ + + mov rax, [rdi + ARGS_OFFSET_MK_STATE] + mov gs:[TLS_OFFSET_MK_STATE], rax + mov rax, [rdi + ARGS_OFFSET_ROOT_VP_STATE] + mov gs:[TLS_OFFSET_ROOT_VP_STATE], rax + + /** + * NOTE: + * - Next we store the pointer to the debug ring that the loader has + * set up for us. This is needed so that we have somewhere to put + * debug information. + */ + + mov rdx, [rdi + ARGS_OFFSET_DEBUG_RING] lea rax, [rip + g_debug_ring] - mov rdx, [rdi + 0x018] mov [rax], rdx + /** + * NOTE: + * - Before we can continue, we need to save off the arguments for + * the mk_main_trampoline function. These will be poped right before + * calling this function. + */ + + push rsi + push rdi + /** * NOTE: * - Set up the IDT with the actual ESRs. Before we can do this, we need @@ -92,7 +233,7 @@ mk_main_entry: */ mov rax, 0x1 - mov gs:[0x258], rax + mov gs:[TLS_OFFSET_NMI_LOCK], rax mov rdi, 0 lea rsi, [rip + dispatch_esr_entry_0] @@ -166,30 +307,66 @@ mk_main_entry: lea rsi, [rip + dispatch_esr_entry_19] call set_esr - mov ecx, 0xC0000082 + /** + * NOTE: + * - Next, we need to store the syscall handler location. This will be + * used by extensions to make syscalls. + */ + + mov ecx, MSR_IA32_LSTAR lea rax, [rip + dispatch_syscall_entry] mov rdx, rax shr rdx, 32 wrmsr + /** + * NOTE: + * - Next we transfer the NMI pending bit. If this is set, we need to hand + * it to the extension so that it can handle the NMI appropriately as + * the microkernel has no way of handling NMIs, so basically any NMI + * that might fire at any point during the loading process has to be + * recorded and transfered all the way to the extension so that it can + * handle it properly. + */ + pop rdi - mov rdx, [rdi + 0x010] - mov rax, [rdx + 0x318] - mov gs:[0x260], rax + mov rdx, [rdi + ARGS_OFFSET_ROOT_VP_STATE] + mov rax, [rdx + SS_OFFSET_NMI] + mov gs:[TLS_OFFSET_NMI_PENDING], rax xor rax, rax - mov [rdx + 0x318], rax + mov [rdx + SS_OFFSET_NMI], rax pop rsi - mov gs:[0x198], rsp - mov rax, gs:[0x190] - mov gs:[0x180], rax - mov rax, gs:[0x198] - mov gs:[0x188], rax + /** + * NOTE: + * - This next block of assembly is seen throughout the assembly code. + * Basically, it stores the information needed for fast failing. Each + * time we enter a new context like calling into an extension, handling + * a syscall, etc, we need to swap around the fast fail handler and RSP + * so that we know where to return to in the event of an error. + */ + + mov gs:[TLS_OFFSET_MK_MAIN_FAST_FAIL_SP], rsp + mov gs:[TLS_OFFSET_CURRENT_FAST_FAIL_SP], rsp + mov rax, gs:[TLS_OFFSET_MK_MAIN_FAST_FAIL_IP] + mov gs:[TLS_OFFSET_CURRENT_FAST_FAIL_IP], rax + + /** + * NOTE: + * - Finally, call the main trampoline. + */ + + call mk_main + + /** + * NOTE: + * - If we get here, it is because an error occurred and we need to + * fast fail. + */ - call mk_main_trampoline jmp return_to_current_fast_fail .size mk_main_entry, .-mk_main_entry @@ -202,10 +379,64 @@ mk_main_entry: .type mk_main_fast_fail_entry, @function mk_main_fast_fail_entry: + /** + * NOTE: + * - In the beginning of mk_main_entry, we saved the original arguments + * to the stack which we will use here. + */ + pop rdi - mov rdi, [rdi + 0x010] + /** + * NOTE: + * - Promote back to the root OS on failure. + */ + + mov rdi, [rdi + ARGS_OFFSET_ROOT_VP_STATE] mov rsi, 1 jmp promote .size mk_main_fast_fail_entry, .-mk_main_fast_fail_entry + + /**************************************************************************/ + /* Runtime Helpers */ + /**************************************************************************/ + + .globl memcpy + .type memcpy, @function +memcpy: + + mov rax, rdi + mov rcx, rdx + rep movsb + + ret + int 3 + + .size memcpy, .-memcpy + + + + .globl memset + .type memset, @function +memset: + + mov r10, rdi + mov rax, rsi + mov rcx, rdx + rep stosb + mov rax, r10 + + ret + int 3 + + .size memset, .-memset + + + + .rodata + .intel_syntax noprefix + + .globl __stack_chk_guard +__stack_chk_guard: + .quad 0xDEADBEEFDEADBEEF diff --git a/kernel/src/x64/return_to_current_fast_fail.S b/kernel/src/x64/return_to_current_fast_fail.S index d13d5ca4..5cf66283 100644 --- a/kernel/src/x64/return_to_current_fast_fail.S +++ b/kernel/src/x64/return_to_current_fast_fail.S @@ -24,6 +24,11 @@ * SOFTWARE. */ + /** @brief defines the offset of tls_t.current_fast_fail_ip */ + #define TLS_OFFSET_CURRENT_FAST_FAIL_IP 0x180 + /** @brief defines the offset of tls_t.current_fast_fail_sp */ + #define TLS_OFFSET_CURRENT_FAST_FAIL_SP 0x188 + .code64 .intel_syntax noprefix @@ -31,12 +36,11 @@ .type return_to_current_fast_fail, @function return_to_current_fast_fail: - mov rax, gs:[0x188] + mov rax, gs:[TLS_OFFSET_CURRENT_FAST_FAIL_SP] + cmp rax, 0 je use_current_stack - mov rsp, rax - use_current_stack: call set_up_target @@ -44,7 +48,7 @@ capture_spec: pause jmp capture_spec set_up_target: - mov rax, gs:[0x180] + mov rax, gs:[TLS_OFFSET_CURRENT_FAST_FAIL_IP] mov [rsp], rax ret int 3 diff --git a/kernel/src/x64/root_page_table_t.hpp b/kernel/src/x64/root_page_table_t.hpp index ed9c099d..e6fbde8d 100644 --- a/kernel/src/x64/root_page_table_t.hpp +++ b/kernel/src/x64/root_page_table_t.hpp @@ -25,6 +25,15 @@ #ifndef ROOT_PAGE_TABLE_T_HPP #define ROOT_PAGE_TABLE_T_HPP +#include "../lock_guard_t.hpp" +#include "../spinlock_t.hpp" + +#include +#include +#include +#include +#include +#include #include #include #include @@ -33,6 +42,7 @@ #include #include #include +#include #include #include @@ -42,37 +52,24 @@ #include #include #include +#include namespace mk { /// @class mk::root_page_table_t /// /// - /// @brief TODO + /// @brief Implements the root pages tables used by the microkernel + /// for mapping extension memory. /// - /// - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use - /// @tparam PAGE_SIZE defines the size of a page - /// @tparam PAGE_SHIFT defines number of bits in a page - /// - template< - typename INTRINSIC_CONCEPT, - typename PAGE_POOL_CONCEPT, - bsl::uintmax PAGE_SIZE, - bsl::uintmax PAGE_SHIFT> class root_page_table_t final { - /// @brief stores true if initialized() has been executed - bool m_initialized{}; - /// @brief stores a reference to the intrinsics to use - INTRINSIC_CONCEPT *m_intrinsic{}; - /// @brief stores a reference to the page pool to use - PAGE_POOL_CONCEPT *m_page_pool{}; /// @brief stores a pointer to the pml4t pml4t_t *m_pml4t{}; - /// @brief stores the CR3 value used to activate this RPT - bsl::safe_uintmax m_pml4t_phys; + /// @brief stores the physical address of the pml4t + bsl::safe_uintmax m_pml4t_phys{bsl::safe_uintmax::failure()}; + /// @brief safe guards operations on the RPT. + mutable spinlock_t m_lock{}; /// /// @brief Returns the index of the last entry present in a page @@ -85,12 +82,14 @@ namespace mk /// table. /// template - [[nodiscard]] constexpr auto - get_last_index(TABLE_CONCEPT const *const table) const noexcept -> bsl::safe_uintmax + [[nodiscard]] static constexpr auto + get_last_index(TABLE_CONCEPT const *const table) noexcept -> bsl::safe_uintmax { + constexpr auto disabled{0_umax}; + bsl::safe_uintmax last_index{}; for (auto const elem : table->entries) { - if (bsl::ZERO_UMAX == elem.data->p) { + if (disabled == elem.data->p) { continue; } @@ -101,151 +100,177 @@ namespace mk } /// - /// @brief Given an outputter, index and the index of the last + /// @brief Given index and the index of the last /// present entry in the page table being dumped, this function /// will output a decoration and the index. /// /// - /// @tparam T the type of outputter provided - /// @param o the instance of the outputter used to output the value. /// @param index the current index of the entry being dumped /// @param last_index the index of the last present entry in the page /// table being dumped. /// - template - constexpr void + static constexpr void output_decoration_and_index( - bsl::out const o, - bsl::safe_uintmax const &index, - bsl::safe_uintmax const &last_index) const noexcept + bsl::safe_uintmax const &index, bsl::safe_uintmax const &last_index) noexcept { - o << bsl::reset_color; + bsl::print() << bsl::rst; if (index != last_index) { - o << "├── "; + bsl::print() << "├── "; } else { - o << "└── "; + bsl::print() << "└── "; } - o << "[" << bsl::yellow << bsl::fmt("#05x", index) << bsl::reset_color << "] "; + bsl::print() << "[" << bsl::ylw << bsl::fmt{"#05x", index} << bsl::rst << "] "; } /// - /// @brief Given an outputter, and whether or not the page table + /// @brief Given whether or not the page table /// entry is the last entry in the table, this function will - /// either output whitespace, or a | and shitespace. + /// either output whtspace, or a | and shitespace. /// /// - /// @tparam T the type of outputter provided - /// @param o the instance of the outputter used to output the value. /// @param is_last_index true if the entry being outputted is the /// last index in the table. /// - template - constexpr void - output_spacing(bsl::out const o, bool const is_last_index) const noexcept + static constexpr void + output_spacing(bool const is_last_index) noexcept { - o << bsl::reset_color; + bsl::print() << bsl::rst; if (!is_last_index) { - o << "│ "; + bsl::print() << "│ "; } else { - o << " "; + bsl::print() << " "; } } /// - /// @brief Given and outputter and a page table entry, this + /// @brief Given a page table entry, this /// function outputs the flags associated with the entry /// /// - /// @tparam T the type of outputter provided /// @tparam ENTRY_CONCEPT the type of page table entry to output - /// @param o the instance of the outputter used to output the value. /// @param entry the page table entry to output /// - template - constexpr void - output_entry_and_flags(bsl::out const o, ENTRY_CONCEPT const *const entry) const noexcept + template + static constexpr void + output_entry_and_flags(ENTRY_CONCEPT const *const entry) noexcept { + constexpr auto disabled{0_umax}; bool add_comma{}; - o << bsl::hex(*static_cast(static_cast(entry))); - o << bsl::reset_color << " ("; + bsl::print() << bsl::hex( + *static_cast(static_cast(entry))); + bsl::print() << bsl::rst << " ("; - if (bsl::ZERO_UMAX != entry->rw) { - o << bsl::green << "W" << bsl::reset_color; + if (disabled != entry->rw) { + bsl::print() << bsl::grn << 'W'; add_comma = true; } else { bsl::touch(); } - if (bsl::ZERO_UMAX != entry->us) { + if (disabled != entry->us) { if (add_comma) { - o << ", "; + bsl::print() << bsl::rst << ", "; } else { bsl::touch(); } - o << bsl::green << "U" << bsl::reset_color; + bsl::print() << bsl::grn << 'U'; add_comma = true; } else { bsl::touch(); } - if (bsl::ZERO_UMAX != entry->nx) { + if (disabled != entry->nx) { if (add_comma) { - o << ", "; + bsl::print() << bsl::rst << ", "; } else { bsl::touch(); } - o << bsl::green << "NX" << bsl::reset_color; + bsl::print() << bsl::grn << "NX"; add_comma = true; } else { bsl::touch(); } - if constexpr (bsl::is_same::value) { - if (bsl::ZERO_UMAX != entry->alias) { + if constexpr (bsl::is_same::value) { + if (disabled != entry->alias) { if (add_comma) { - o << ", "; + bsl::print() << bsl::rst << ", "; } else { bsl::touch(); } - o << bsl::green << "alias" << bsl::reset_color; + bsl::print() << bsl::grn << "alias"; + add_comma = true; } else { bsl::touch(); } } - if constexpr (bsl::is_same::value) { - if (bsl::ZERO_UMAX != entry->auto_release) { - if (add_comma) { - o << ", "; - } - else { - bsl::touch(); - } - - o << bsl::green << "auto_release" << bsl::reset_color; + if constexpr (bsl::is_same::value) { + if (add_comma) { + bsl::print() << bsl::rst << ", "; } else { bsl::touch(); } + + switch (entry->auto_release) { + case MAP_PAGE_AUTO_RELEASE_ALLOC_PAGE.get(): { + bsl::print() << bsl::grn << "auto_release_alloc_page"; + break; + } + + case MAP_PAGE_AUTO_RELEASE_ALLOC_HUGE.get(): { + bsl::print() << bsl::grn << "auto_release_alloc_huge"; + break; + } + + case MAP_PAGE_AUTO_RELEASE_ALLOC_HEAP.get(): { + bsl::print() << bsl::grn << "auto_release_alloc_heap"; + break; + } + + case MAP_PAGE_AUTO_RELEASE_STACK.get(): { + bsl::print() << bsl::grn << "auto_release_stack"; + break; + } + + case MAP_PAGE_AUTO_RELEASE_TLS.get(): { + bsl::print() << bsl::grn << "auto_release_tls"; + break; + } + + case MAP_PAGE_AUTO_RELEASE_ELF.get(): { + bsl::print() << bsl::grn << "auto_release_elf"; + break; + } + + default: { + bsl::print() << bsl::grn << "manual"; + break; + } + } + + add_comma = true; } - o << ")" << bsl::endl; + bsl::print() << bsl::rst << ')'; + bsl::print() << bsl::rst << bsl::endl; } /// @@ -256,51 +281,48 @@ namespace mk /// @param virt the virtual address to get the PML4T offset from. /// @return the PML4T offset from the virtual address /// - [[nodiscard]] constexpr auto - pml4to(bsl::safe_uintmax const &virt) const noexcept -> bsl::safe_uintmax + [[nodiscard]] static constexpr auto + pml4to(bsl::safe_uintmax const &virt) noexcept -> bsl::safe_uintmax { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(39)}; - return (virt >> shift) & mask; + constexpr auto mask{0x1FF_umax}; + constexpr auto shft{39_umax}; + return (virt >> shft) & mask; } /// /// @brief Dumps the provided pml4t_t /// /// - /// @tparam T the type of outputter provided - /// @param o the instance of the outputter used to output the value. + /// @param page_pool the page_pool_t to use /// @param pml4t the pml4t_t to dump /// - template constexpr void - dump_pml4t(bsl::out const o, pml4t_t const *const pml4t) const noexcept + dump_pml4t(page_pool_t &page_pool, pml4t_t const *const pml4t) const noexcept { - bsl::safe_uintmax const last_index{this->get_last_index(pml4t)}; + constexpr auto disabled{0_umax}; + bsl::safe_uintmax const last_index{get_last_index(pml4t)}; - o << bsl::blue // -- - << bsl::hex(m_page_pool->virt_to_phys(pml4t)) // -- - << ": " // -- - << bsl::endl; // -- + bsl::print() << bsl::blu << bsl::hex(m_pml4t_phys); + bsl::print() << bsl::rst << bsl::endl; for (auto const elem : pml4t->entries) { - if (bsl::ZERO_UMAX == elem.data->p) { + if (disabled == elem.data->p) { continue; } - this->output_decoration_and_index(o, elem.index, last_index); + output_decoration_and_index(elem.index, last_index); - if (bsl::ZERO_UMAX != elem.data->us) { - o << bsl::blue; + if (disabled != elem.data->us) { + bsl::print() << bsl::blu; + output_entry_and_flags(elem.data); } else { - o << bsl::black; + bsl::print() << bsl::blk; + output_entry_and_flags(elem.data); } - this->output_entry_and_flags(o, elem.data); - - if (bsl::ZERO_UMAX != elem.data->us) { - this->dump_pdpt(o, this->get_pdpt(elem.data), elem.index == last_index); + if (disabled != elem.data->us) { + dump_pdpt(page_pool, get_pdpt(page_pool, elem.data), elem.index == last_index); } else { bsl::touch(); @@ -312,37 +334,33 @@ namespace mk /// @brief Adds a pdpt_t to the provided pml4te_t. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param pml4te the pml4te_t to add a pdpt_t too - /// @param us if true, this function will map the table with - /// userspace privileges. /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - [[nodiscard]] constexpr auto - add_pdpt(loader::pml4te_t *const pml4te, bool const us) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + add_pdpt(tls_t &tls, page_pool_t &page_pool, pml4te_t *const pml4te) noexcept + -> bsl::errc_type { - auto const *const table{m_page_pool->template allocate()}; + auto const *const table{page_pool.allocate(tls, ALLOCATE_TAG_PDPTS)}; if (bsl::unlikely(nullptr == table)) { bsl::print() << bsl::here(); return bsl::errc_failure; } - auto const table_phys{m_page_pool->virt_to_phys(table)}; - if (bsl::unlikely(!table_phys)) { + auto const table_phys{page_pool.virt_to_phys(table)}; + if (bsl::unlikely_assert(!table_phys)) { bsl::print() << bsl::here(); return bsl::errc_failure; } - pml4te->phys = (table_phys >> PAGE_SHIFT).get(); - pml4te->p = bsl::ONE_UMAX.get(); - pml4te->rw = bsl::ONE_UMAX.get(); - - if (us) { - pml4te->us = bsl::ONE_UMAX.get(); - } - else { - pml4te->us = bsl::ZERO_UMAX.get(); - } + constexpr auto enable{1_umax}; + pml4te->phys = (table_phys >> HYPERVISOR_PAGE_SHIFT).get(); + pml4te->p = enable.get(); + pml4te->rw = enable.get(); + pml4te->us = enable.get(); return bsl::errc_success; } @@ -351,21 +369,24 @@ namespace mk /// @brief Adds a pdpt_t to the provided pml4te_t. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param pml4te the pml4te_t to add a pdpt_t too /// - constexpr void - remove_pdpt(loader::pml4te_t *const pml4te) noexcept + static constexpr void + remove_pdpt(tls_t &tls, page_pool_t &page_pool, pml4te_t *const pml4te) noexcept { - for (auto const elem : get_pdpt(pml4te)->entries) { - if (elem.data->p != bsl::ZERO_UMAX) { - this->remove_pdt(elem.data); + constexpr auto disabled{0_umax}; + for (auto const elem : get_pdpt(page_pool, pml4te)->entries) { + if (disabled != elem.data->p) { + remove_pdt(tls, page_pool, elem.data); } else { bsl::touch(); } } - m_page_pool->deallocate(get_pdpt(pml4te)); + page_pool.deallocate(tls, get_pdpt(page_pool, pml4te), ALLOCATE_TAG_PDPTS); } /// @@ -373,16 +394,17 @@ namespace mk /// pml4te_t. /// /// + /// @param page_pool the page_pool_t to use /// @param pml4te the pml4te_t to get the pdpt_t from /// @return A pointer to the requested pdpt_t /// - [[nodiscard]] constexpr auto - get_pdpt(loader::pml4te_t *const pml4te) noexcept -> pdpt_t * + [[nodiscard]] static constexpr auto + get_pdpt(page_pool_t &page_pool, pml4te_t *const pml4te) noexcept -> pdpt_t * { bsl::safe_uintmax entry_phys{pml4te->phys}; - entry_phys <<= PAGE_SHIFT; + entry_phys <<= HYPERVISOR_PAGE_SHIFT; - return m_page_pool->template phys_to_virt(entry_phys); + return page_pool.template phys_to_virt(entry_phys); } /// @@ -390,16 +412,17 @@ namespace mk /// pml4te_t. /// /// + /// @param page_pool the page_pool_t to use /// @param pml4te the pml4te_t to get the pdpt_t from /// @return A pointer to the requested pdpt_t /// - [[nodiscard]] constexpr auto - get_pdpt(loader::pml4te_t const *const pml4te) const noexcept -> pdpt_t const * + [[nodiscard]] static constexpr auto + get_pdpt(page_pool_t &page_pool, pml4te_t const *const pml4te) noexcept -> pdpt_t const * { bsl::safe_uintmax entry_phys{pml4te->phys}; - entry_phys <<= PAGE_SHIFT; + entry_phys <<= HYPERVISOR_PAGE_SHIFT; - return m_page_pool->template phys_to_virt(entry_phys); + return page_pool.template phys_to_virt(entry_phys); } /// @@ -410,44 +433,46 @@ namespace mk /// @param virt the virtual address to get the PDPT offset from. /// @return the PDPT offset from the virtual address /// - [[nodiscard]] constexpr auto - pdpto(bsl::safe_uintmax const &virt) const noexcept -> bsl::safe_uintmax + [[nodiscard]] static constexpr auto + pdpto(bsl::safe_uintmax const &virt) noexcept -> bsl::safe_uintmax { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(30)}; - return (virt >> shift) & mask; + constexpr auto mask{0x1FF_umax}; + constexpr auto shft{30_umax}; + return (virt >> shft) & mask; } /// /// @brief Dumps the provided pdpt_t /// /// - /// @tparam T the type of outputter provided - /// @param o the instance of the outputter used to output the value. + /// @param page_pool the page_pool_t to use /// @param pdpt the pdpt_t to dump /// @param is_pml4te_last_index true if the parent pml4te was the /// last pml4te in the table /// - template - constexpr void + static constexpr void dump_pdpt( - bsl::out const o, pdpt_t const *const pdpt, bool is_pml4te_last_index) const noexcept + page_pool_t &page_pool, pdpt_t const *const pdpt, bool is_pml4te_last_index) noexcept { - bsl::safe_uintmax const last_index{this->get_last_index(pdpt)}; + constexpr auto disabled{0_umax}; + auto const last_index{get_last_index(pdpt)}; for (auto const elem : pdpt->entries) { - if (bsl::ZERO_UMAX == elem.data->p) { + if (disabled == elem.data->p) { continue; } - this->output_spacing(o, is_pml4te_last_index); - this->output_decoration_and_index(o, elem.index, last_index); + output_spacing(is_pml4te_last_index); + output_decoration_and_index(elem.index, last_index); - o << bsl::blue; - this->output_entry_and_flags(o, elem.data); + bsl::print() << bsl::blu; + output_entry_and_flags(elem.data); - this->dump_pdt( - o, this->get_pdt(elem.data), is_pml4te_last_index, elem.index == last_index); + dump_pdt( + page_pool, + get_pdt(page_pool, elem.data), + is_pml4te_last_index, + elem.index == last_index); } } @@ -455,37 +480,32 @@ namespace mk /// @brief Adds a pdt_t to the provided pdpte_t. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param pdpte the pdpte_t to add a pdt_t too - /// @param us if true, this function will map the table with - /// userspace privileges. /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - [[nodiscard]] constexpr auto - add_pdt(loader::pdpte_t *const pdpte, bool const us) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + add_pdt(tls_t &tls, page_pool_t &page_pool, pdpte_t *const pdpte) noexcept -> bsl::errc_type { - auto const *const table{m_page_pool->template allocate()}; + auto const *const table{page_pool.allocate(tls, ALLOCATE_TAG_PDTS)}; if (bsl::unlikely(nullptr == table)) { bsl::print() << bsl::here(); return bsl::errc_failure; } - auto const table_phys{m_page_pool->virt_to_phys(table)}; - if (bsl::unlikely(!table_phys)) { + auto const table_phys{page_pool.virt_to_phys(table)}; + if (bsl::unlikely_assert(!table_phys)) { bsl::print() << bsl::here(); return bsl::errc_failure; } - pdpte->phys = (table_phys >> PAGE_SHIFT).get(); - pdpte->p = bsl::ONE_UMAX.get(); - pdpte->rw = bsl::ONE_UMAX.get(); - - if (us) { - pdpte->us = bsl::ONE_UMAX.get(); - } - else { - pdpte->us = bsl::ZERO_UMAX.get(); - } + constexpr auto enable{1_umax}; + pdpte->phys = (table_phys >> HYPERVISOR_PAGE_SHIFT).get(); + pdpte->p = enable.get(); + pdpte->rw = enable.get(); + pdpte->us = enable.get(); return bsl::errc_success; } @@ -494,21 +514,24 @@ namespace mk /// @brief Adds a pdt_t to the provided pdpte_t. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param pdpte the pdpte_t to add a pdt_t too /// - constexpr void - remove_pdt(loader::pdpte_t *const pdpte) noexcept + static constexpr void + remove_pdt(tls_t &tls, page_pool_t &page_pool, pdpte_t *const pdpte) noexcept { - for (auto const elem : get_pdt(pdpte)->entries) { - if (elem.data->p != bsl::ZERO_UMAX) { - this->remove_pt(elem.data); + constexpr auto disabled{0_umax}; + for (auto const elem : get_pdt(page_pool, pdpte)->entries) { + if (disabled != elem.data->p) { + remove_pt(tls, page_pool, elem.data); } else { bsl::touch(); } } - m_page_pool->deallocate(get_pdt(pdpte)); + page_pool.deallocate(tls, get_pdt(page_pool, pdpte), ALLOCATE_TAG_PDTS); } /// @@ -517,15 +540,16 @@ namespace mk /// /// /// @param pdpte the pdpte_t to get the pdt_t from + /// @param page_pool the page_pool_t to use /// @return A pointer to the requested pdt_t /// - [[nodiscard]] constexpr auto - get_pdt(loader::pdpte_t *const pdpte) noexcept -> pdt_t * + [[nodiscard]] static constexpr auto + get_pdt(page_pool_t &page_pool, pdpte_t *const pdpte) noexcept -> pdt_t * { bsl::safe_uintmax entry_phys{pdpte->phys}; - entry_phys <<= PAGE_SHIFT; + entry_phys <<= HYPERVISOR_PAGE_SHIFT; - return m_page_pool->template phys_to_virt(entry_phys); + return page_pool.template phys_to_virt(entry_phys); } /// @@ -534,15 +558,16 @@ namespace mk /// /// /// @param pdpte the pdpte_t to get the pdt_t from + /// @param page_pool the page_pool_t to use /// @return A pointer to the requested pdt_t /// - [[nodiscard]] constexpr auto - get_pdt(loader::pdpte_t const *const pdpte) const noexcept -> pdt_t const * + [[nodiscard]] static constexpr auto + get_pdt(page_pool_t &page_pool, pdpte_t const *const pdpte) noexcept -> pdt_t const * { bsl::safe_uintmax entry_phys{pdpte->phys}; - entry_phys <<= PAGE_SHIFT; + entry_phys <<= HYPERVISOR_PAGE_SHIFT; - return m_page_pool->template phys_to_virt(entry_phys); + return page_pool.template phys_to_virt(entry_phys); } /// @@ -553,51 +578,49 @@ namespace mk /// @param virt the virtual address to get the PDT offset from. /// @return the PDT offset from the virtual address /// - [[nodiscard]] constexpr auto - pdto(bsl::safe_uintmax const &virt) const noexcept -> bsl::safe_uintmax + [[nodiscard]] static constexpr auto + pdto(bsl::safe_uintmax const &virt) noexcept -> bsl::safe_uintmax { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(21)}; - return (virt >> shift) & mask; + constexpr auto mask{0x1FF_umax}; + constexpr auto shft{21_umax}; + return (virt >> shft) & mask; } /// /// @brief Dumps the provided pdt_t /// /// - /// @tparam T the type of outputter provided - /// @param o the instance of the outputter used to output the value. + /// @param page_pool the page_pool_t to use /// @param pdt the pdt_t to dump /// @param is_pml4te_last_index true if the parent pml4te was the /// last pml4te in the table /// @param is_pdpte_last_index true if the parent pdpte was the /// last pdpte in the table /// - template - constexpr void + static constexpr void dump_pdt( - bsl::out const o, + page_pool_t &page_pool, pdt_t const *const pdt, bool is_pml4te_last_index, - bool is_pdpte_last_index) const noexcept + bool is_pdpte_last_index) noexcept { - bsl::safe_uintmax const last_index{this->get_last_index(pdt)}; + bsl::safe_uintmax const last_index{get_last_index(pdt)}; + constexpr auto disabled{0_umax}; for (auto const elem : pdt->entries) { - if (bsl::ZERO_UMAX == elem.data->p) { + if (disabled == elem.data->p) { continue; } - this->output_spacing(o, is_pml4te_last_index); - this->output_spacing(o, is_pdpte_last_index); - this->output_decoration_and_index(o, elem.index, last_index); + output_spacing(is_pml4te_last_index); + output_spacing(is_pdpte_last_index); + output_decoration_and_index(elem.index, last_index); - o << bsl::blue; - this->output_entry_and_flags(o, elem.data); + bsl::print() << bsl::blu; + output_entry_and_flags(elem.data); - this->dump_pt( - o, - this->get_pt(elem.data), + dump_pt( + get_pt(page_pool, elem.data), is_pml4te_last_index, is_pdpte_last_index, elem.index == last_index); @@ -608,37 +631,32 @@ namespace mk /// @brief Adds a pt_t to the provided pdte_t. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param pdte the pdte_t to add a pt_t too - /// @param us if true, this function will map the table with - /// userspace privileges. /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// - [[nodiscard]] constexpr auto - add_pt(loader::pdte_t *const pdte, bool const us) noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + add_pt(tls_t &tls, page_pool_t &page_pool, pdte_t *const pdte) noexcept -> bsl::errc_type { - auto const *const table{m_page_pool->template allocate()}; + auto const *const table{page_pool.allocate(tls, ALLOCATE_TAG_PTS)}; if (bsl::unlikely(nullptr == table)) { bsl::print() << bsl::here(); return bsl::errc_failure; } - auto const table_phys{m_page_pool->virt_to_phys(table)}; - if (bsl::unlikely(!table_phys)) { + auto const table_phys{page_pool.virt_to_phys(table)}; + if (bsl::unlikely_assert(!table_phys)) { bsl::print() << bsl::here(); return bsl::errc_failure; } - pdte->phys = (table_phys >> PAGE_SHIFT).get(); - pdte->p = bsl::ONE_UMAX.get(); - pdte->rw = bsl::ONE_UMAX.get(); - - if (us) { - pdte->us = bsl::ONE_UMAX.get(); - } - else { - pdte->us = bsl::ZERO_UMAX.get(); - } + constexpr auto enable{1_umax}; + pdte->phys = (table_phys >> HYPERVISOR_PAGE_SHIFT).get(); + pdte->p = enable.get(); + pdte->rw = enable.get(); + pdte->us = enable.get(); return bsl::errc_success; } @@ -647,12 +665,77 @@ namespace mk /// @brief Adds a pt_t to the provided pdte_t. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param pdte the pdte_t to add a pt_t too /// - constexpr void - remove_pt(loader::pdte_t *const pdte) noexcept + static constexpr void + remove_pt(tls_t &tls, page_pool_t &page_pool, pdte_t *const pdte) noexcept { - m_page_pool->deallocate(get_pt(pdte)); + constexpr auto disabled{0_umax}; + for (auto const elem : get_pt(page_pool, pdte)->entries) { + if (disabled == elem.data->p) { + continue; + } + + switch (elem.data->auto_release) { + case MAP_PAGE_NO_AUTO_RELEASE.get(): { + break; + } + + case MAP_PAGE_AUTO_RELEASE_ALLOC_PAGE.get(): { + page_pool.deallocate( + tls, + pte_from_page_pool_to_virt(page_pool, elem.data), + ALLOCATE_TAG_BF_MEM_OP_ALLOC_PAGE); + + break; + } + + case MAP_PAGE_AUTO_RELEASE_ALLOC_HEAP.get(): { + page_pool.deallocate( + tls, + pte_from_page_pool_to_virt(page_pool, elem.data), + ALLOCATE_TAG_BF_MEM_OP_ALLOC_HEAP); + + break; + } + + case MAP_PAGE_AUTO_RELEASE_STACK.get(): { + page_pool.deallocate( + tls, + pte_from_page_pool_to_virt(page_pool, elem.data), + ALLOCATE_TAG_EXT_STACK); + + break; + } + + case MAP_PAGE_AUTO_RELEASE_TLS.get(): { + page_pool.deallocate( + tls, + pte_from_page_pool_to_virt(page_pool, elem.data), + ALLOCATE_TAG_EXT_TLS); + + break; + } + + case MAP_PAGE_AUTO_RELEASE_ELF.get(): { + page_pool.deallocate( + tls, + pte_from_page_pool_to_virt(page_pool, elem.data), + ALLOCATE_TAG_EXT_ELF); + + break; + } + + default: { + bsl::error() << "uknown tag\n" << bsl::here(); + break; + } + } + } + + page_pool.deallocate(tls, get_pt(page_pool, pdte), ALLOCATE_TAG_PTS); } /// @@ -660,16 +743,17 @@ namespace mk /// pdte_t. /// /// + /// @param page_pool the page_pool_t to use /// @param pdte the pdte_t to get the pt_t from /// @return A pointer to the requested pt_t /// - [[nodiscard]] constexpr auto - get_pt(loader::pdte_t *const pdte) noexcept -> pt_t * + [[nodiscard]] static constexpr auto + get_pt(page_pool_t &page_pool, pdte_t *const pdte) noexcept -> pt_t * { bsl::safe_uintmax entry_phys{pdte->phys}; - entry_phys <<= PAGE_SHIFT; + entry_phys <<= HYPERVISOR_PAGE_SHIFT; - return m_page_pool->template phys_to_virt(entry_phys); + return page_pool.template phys_to_virt(entry_phys); } /// @@ -677,16 +761,17 @@ namespace mk /// pdte_t. /// /// + /// @param page_pool the page_pool_t to use /// @param pdte the pdte_t to get the pt_t from /// @return A pointer to the requested pt_t /// - [[nodiscard]] constexpr auto - get_pt(loader::pdte_t const *const pdte) const noexcept -> pt_t const * + [[nodiscard]] static constexpr auto + get_pt(page_pool_t &page_pool, pdte_t const *const pdte) noexcept -> pt_t const * { bsl::safe_uintmax entry_phys{pdte->phys}; - entry_phys <<= PAGE_SHIFT; + entry_phys <<= HYPERVISOR_PAGE_SHIFT; - return m_page_pool->template phys_to_virt(entry_phys); + return page_pool.template phys_to_virt(entry_phys); } /// @@ -697,20 +782,18 @@ namespace mk /// @param virt the virtual address to get the PT offset from. /// @return the PT offset from the virtual address /// - [[nodiscard]] constexpr auto - pto(bsl::safe_uintmax const &virt) const noexcept -> bsl::safe_uintmax + [[nodiscard]] static constexpr auto + pto(bsl::safe_uintmax const &virt) noexcept -> bsl::safe_uintmax { - constexpr bsl::safe_uintmax mask{bsl::to_umax(0x1FF)}; - constexpr bsl::safe_uintmax shift{bsl::to_umax(12)}; - return (virt >> shift) & mask; + constexpr auto mask{0x1FF_umax}; + constexpr auto shft{12_umax}; + return (virt >> shft) & mask; } /// /// @brief Dumps the provided pt_t /// /// - /// @tparam T the type of outputter provided - /// @param o the instance of the outputter used to output the value. /// @param pt the pt_t to dump /// @param is_pml4te_last_index true if the parent pml4te was the /// last pml4te in the table @@ -719,32 +802,69 @@ namespace mk /// @param is_pdte_last_index true if the parent pdte was the /// last pdte in the table /// - template - constexpr void + static constexpr void dump_pt( - bsl::out const o, pt_t const *const pt, bool is_pml4te_last_index, bool is_pdpte_last_index, - bool is_pdte_last_index) const noexcept + bool is_pdte_last_index) noexcept { - bsl::safe_uintmax const last_index{this->get_last_index(pt)}; + bsl::safe_uintmax const last_index{get_last_index(pt)}; + constexpr auto disabled{0_umax}; for (auto const elem : pt->entries) { - if (bsl::ZERO_UMAX == elem.data->p) { + if (disabled == elem.data->p) { continue; } - this->output_spacing(o, is_pml4te_last_index); - this->output_spacing(o, is_pdpte_last_index); - this->output_spacing(o, is_pdte_last_index); - this->output_decoration_and_index(o, elem.index, last_index); + output_spacing(is_pml4te_last_index); + output_spacing(is_pdpte_last_index); + output_spacing(is_pdte_last_index); + output_decoration_and_index(elem.index, last_index); - o << bsl::white; - this->output_entry_and_flags(o, elem.data); + bsl::print() << bsl::rst; + output_entry_and_flags(elem.data); } } + /// + /// @brief Returns the virtual address associated with a specific + /// pte that was allocated using the page pool. + /// + /// + /// @param page_pool the page_pool_t to use + /// @param pte the pte_t to convert + /// @return Returns the virtual address associated with a specific + /// pte that was allocated using the page pool. + /// + [[nodiscard]] static constexpr auto + pte_from_page_pool_to_virt(page_pool_t &page_pool, pte_t *const pte) noexcept -> page_t * + { + bsl::safe_uintmax entry_phys{pte->phys}; + entry_phys <<= HYPERVISOR_PAGE_SHIFT; + + return page_pool.phys_to_virt(entry_phys); + } + + /// + /// @brief Returns the virtual address associated with a specific + /// pte that was allocated using the huge pool. + /// + /// + /// @param huge_pool the huge_pool_t to use + /// @param pte the pte_t to convert + /// @return Returns the virtual address associated with a specific + /// pte that was allocated using the huge pool. + /// + [[nodiscard]] static constexpr auto + pte_from_huge_pool_to_virt(huge_pool_t &huge_pool, pte_t *const pte) noexcept -> page_t * + { + bsl::safe_uintmax entry_phys{pte->phys}; + entry_phys <<= HYPERVISOR_PAGE_SHIFT; + + return huge_pool.phys_to_virt(entry_phys); + } + /// /// @brief Returns the page aligned version of the addr /// @@ -752,10 +872,11 @@ namespace mk /// @param addr the address to query /// @return Returns the page aligned version of the addr /// - [[nodiscard]] constexpr auto - page_aligned(bsl::safe_uintmax const &addr) const noexcept -> bsl::safe_uintmax + [[nodiscard]] static constexpr auto + page_aligned(bsl::safe_uintmax const &addr) noexcept -> bsl::safe_uintmax { - return (addr & ~(PAGE_SIZE - bsl::ONE_UMAX)); + constexpr auto one{1_umax}; + return (addr & ~(HYPERVISOR_PAGE_SIZE - one)); } /// @@ -765,10 +886,270 @@ namespace mk /// @param addr the address to query /// @return Returns true if the provided address is page aligned /// - [[nodiscard]] constexpr auto - is_page_aligned(bsl::safe_uintmax const &addr) const noexcept -> bool + [[nodiscard]] static constexpr auto + is_page_aligned(bsl::safe_uintmax const &addr) noexcept -> bool { - return (addr & (PAGE_SIZE - bsl::ONE_UMAX)) == bsl::ZERO_UMAX; + constexpr auto one{1_umax}; + constexpr auto aligned{0_umax}; + return (addr & (HYPERVISOR_PAGE_SIZE - one)) == aligned; + } + + /// + /// @brief Allocates a page from the provided page pool and maps it + /// into the root page table being managed by this class The page + /// is marked as "auto release", meaning when this root page table + /// is released, the pages allocated by this function will + /// automatically be deallocated and put back into the provided + /// page pool. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param page_virt the virtual address to map the allocated + /// page to + /// @param page_flags defines how memory should be mapped + /// @param auto_release defines what auto release tag to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate_page( + tls_t &tls, + page_pool_t &page_pool, + bsl::safe_uintmax const &page_virt, + bsl::safe_uintmax const &page_flags, + bsl::safe_int32 const &auto_release) noexcept -> void * + { + bsl::errc_type ret{}; + + page_t *page{}; + switch (auto_release.get()) { + case MAP_PAGE_AUTO_RELEASE_STACK.get(): { + /// fixme, this should not be bsl::uint8 + page = page_pool.allocate(tls, ALLOCATE_TAG_EXT_STACK); + break; + } + + case MAP_PAGE_AUTO_RELEASE_TLS.get(): { + /// fixme, this should not be bsl::uint8 + page = page_pool.allocate(tls, ALLOCATE_TAG_EXT_TLS); + break; + } + + case MAP_PAGE_AUTO_RELEASE_ELF.get(): { + /// fixme, this should not be bsl::uint8 + page = page_pool.allocate(tls, ALLOCATE_TAG_EXT_ELF); + break; + } + + default: { + bsl::error() << "unknown tag\n" << bsl::here(); + break; + } + } + + if (bsl::unlikely(nullptr == page)) { + bsl::print() << bsl::here(); + return nullptr; + } + + auto const page_phys{page_pool.virt_to_phys(page)}; + if (bsl::unlikely_assert(!page_phys)) { + bsl::error() << "physical address is invalid " // -- + << bsl::hex(page_phys) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return nullptr; + } + + ret = this->map_page(tls, page_pool, page_virt, page_phys, page_flags, auto_release); + if (bsl::unlikely(!ret)) { + bsl::print() << bsl::here(); + return nullptr; + } + + return page; + } + + /// + /// @brief Releases the memory allocated for tables + /// + /// + /// @param page_pool the page_pool_t to use + /// @param tls the current TLS block + /// + constexpr void + release_tables(tls_t &tls, page_pool_t &page_pool) noexcept + { + constexpr auto disabled{0_umax}; + for (auto const elem : m_pml4t->entries) { + if (disabled == elem.data->p) { + continue; + } + + if (disabled != elem.data->alias) { + continue; + } + + this->remove_pdpt(tls, page_pool, elem.data); + } + + page_pool.deallocate(tls, m_pml4t, ALLOCATE_TAG_PML4TS); + m_pml4t = {}; + m_pml4t_phys = bsl::safe_uintmax::failure(); + } + + public: + /// + /// @brief Initializes this root_page_table_t + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize(tls_t &tls, page_pool_t &page_pool) noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(m_pml4t_phys)) { + bsl::error() << "root_page_table_t already initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + bsl::finally release_on_error{[this, &tls, &page_pool]() noexcept -> void { + this->release(tls, page_pool); + }}; + + m_pml4t = page_pool.template allocate(tls, ALLOCATE_TAG_PML4TS); + if (bsl::unlikely(nullptr == m_pml4t)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + m_pml4t_phys = page_pool.virt_to_phys(m_pml4t); + if (bsl::unlikely_assert(!m_pml4t_phys)) { + bsl::print() << bsl::here(); + return bsl::errc_failure; + } + + release_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Releases all of the resources used by the RPT. + /// + /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// + constexpr void + release(tls_t &tls, page_pool_t &page_pool) noexcept + { + lock_guard_t lock{tls, m_lock}; + this->release_tables(tls, page_pool); + } + + /// + /// @brief Returns true if this RPT is initialized. + /// + /// + /// @return Returns true if this RPT is initialized. + /// + [[nodiscard]] constexpr auto + is_initialized() const noexcept -> bool + { + return !!m_pml4t_phys; + } + + /// + /// @brief Sets the current root page table to this root page table. + /// + /// + /// @param intrinsic the intrinsic_t to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + activate(intrinsic_t &intrinsic) const noexcept -> bsl::errc_type + { + if (bsl::unlikely_assert(!m_pml4t_phys)) { + bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + intrinsic.set_cr3(m_pml4t_phys); + return bsl::errc_success; + } + + /// + /// @brief Given a root page table, the pml4te_t enties are aliased + /// into this page table, allowing software using this root page + /// table to access the memory mapped into the provided root page + /// table. The additions are aliases only, meaning when this root + /// page table loses scope, aliased entries added by this function + /// are not returned back to the page pool. + /// + /// + /// @param tls the current TLS block + /// @param rpt the root page table to add aliases to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + add_tables(tls_t &tls, void const *const rpt) noexcept -> bsl::errc_type + { + lock_guard_t lock{tls, m_lock}; + + if (bsl::unlikely_assert(!m_pml4t_phys)) { + bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + auto const *const pml4t{static_cast(rpt)}; + if (bsl::unlikely_assert(nullptr == pml4t)) { + bsl::error() << "invalid rpt\n" << bsl::here(); + return bsl::errc_failure; + } + + constexpr auto enable{1_umax}; + constexpr auto disabled{0_umax}; + + for (auto const elem : pml4t->entries) { + if (disabled != elem.data->p) { + auto *const pml4e_dst{m_pml4t->entries.at_if(elem.index)}; + + *pml4e_dst = *elem.data; + pml4e_dst->alias = enable.get(); + } + else { + bsl::touch(); + } + } + + return bsl::errc_success; + } + + /// + /// @brief Given a root page table, the pml4te_t enties are aliased + /// into this page table, allowing software using this root page + /// table to access the memory mapped into the provided root page + /// table. The additions are aliases only, meaning when this root + /// page table loses scope, aliased entries added by this function + /// are not returned back to the page pool. + /// + /// + /// @param tls the current TLS block + /// @param rpt the root page table to add aliases to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + add_tables(tls_t &tls, root_page_table_t const &rpt) noexcept -> bsl::errc_type + { + return this->add_tables(tls, rpt.m_pml4t); } /// @@ -776,30 +1157,106 @@ namespace mk /// by this class. /// /// + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param page_virt the virtual address to map the physical address - /// too - /// @param page_phys the physical address to map - /// @param executable if true, the page is mapped as read/execute, - /// otherwise the page is mapped as read/write - /// @param us if true, map_page will map the page with userspace - /// privileges. - /// @param auto_release if true, the page is mapped as auto_release - /// meaning the page will be deallocated when the root page table - /// loses scope. + /// too. + /// @param page_phys the physical address to map. + /// @param page_flags defines how memory should be mapped + /// @param auto_release defines what auto release tag to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto map_page( + tls_t &tls, + page_pool_t &page_pool, bsl::safe_uintmax const &page_virt, bsl::safe_uintmax const &page_phys, - bool const executable, - bool const us, - bool const auto_release) noexcept -> bsl::errc_type + bsl::safe_uintmax const &page_flags, + bsl::safe_int32 const &auto_release) noexcept -> bsl::errc_type { + constexpr auto disabled{0_umax}; + lock_guard_t lock{tls, m_lock}; + + if (bsl::unlikely_assert(!m_pml4t_phys)) { + bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(page_virt.is_zero())) { + bsl::error() << "virtual address is invalid " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(!this->is_page_aligned(page_virt))) { + bsl::error() << "virtual address is not page aligned " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(page_phys.is_zero())) { + bsl::error() << "physical address is invalid " // -- + << bsl::hex(page_phys) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(!this->is_page_aligned(page_phys))) { + bsl::error() << "physical address is not page aligned " // -- + << bsl::hex(page_phys) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(!page_flags)) { + bsl::error() << "invalid flags " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if (bsl::unlikely_assert(!auto_release)) { + bsl::error() << "invalid auto release " // -- + << auto_release // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + if ((page_flags & MAP_PAGE_WRITE).is_pos()) { + if ((page_flags & MAP_PAGE_EXECUTE).is_pos()) { + bsl::error() << "invalid page_flags " // -- + << bsl::hex(page_flags) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; + } + + bsl::touch(); + } + else { + bsl::touch(); + } + auto *const pml4te{m_pml4t->entries.at_if(this->pml4to(page_virt))}; - if (pml4te->p == bsl::ZERO_UMAX) { - if (bsl::unlikely(!this->add_pdpt(pml4te, us))) { + if (disabled == pml4te->p) { + if (bsl::unlikely(!this->add_pdpt(tls, page_pool, pml4te))) { bsl::print() << bsl::here(); return bsl::errc_failure; } @@ -807,38 +1264,33 @@ namespace mk bsl::touch(); } else { - if (us) { - if (pml4te->us == bsl::ZERO_UMAX) { - bsl::error() << "attempt to map the userspace address " // -- - << bsl::hex(page_virt) // -- - << " in an address range owned by the kernel failed" // -- - << bsl::endl // -- - << bsl::here(); // -- - return bsl::errc_failure; - } + /// NOTE: + /// - The loader doesn't map in the memory associated with + /// the microkernel's page tables. This means this code + /// cannot walk any pages mapped to the microkernel, it + /// can only alias these pages. For this reason, mapping + /// must always take place on userspace specific memory + /// and the address spaces must be distinct. + /// - bsl::touch(); + if (disabled == pml4te->us) { + bsl::error() << "attempt to map the userspace address " // -- + << bsl::hex(page_virt) // -- + << " in an address range owned by the kernel failed" // -- + << bsl::endl // -- + << bsl::here(); // -- + + return bsl::errc_failure; } - else { - if (pml4te->us == bsl::ONE_UMAX) { - bsl::error() << "attempt to map the kernel address " // -- - << bsl::hex(page_virt) // -- - << " in an address range owned by userspace failed" // -- - << bsl::endl // -- - << bsl::here(); // -- - return bsl::errc_failure; - } - - bsl::touch(); - } + bsl::touch(); } - auto *const pdpt{this->get_pdpt(pml4te)}; + auto *const pdpt{get_pdpt(page_pool, pml4te)}; auto *const pdpte{pdpt->entries.at_if(this->pdpto(page_virt))}; - if (pdpte->p == bsl::ZERO_UMAX) { - if (bsl::unlikely(!this->add_pdt(pdpte, us))) { + if (disabled == pdpte->p) { + if (bsl::unlikely(!this->add_pdt(tls, page_pool, pdpte))) { bsl::print() << bsl::here(); return bsl::errc_failure; } @@ -849,10 +1301,10 @@ namespace mk bsl::touch(); } - auto *const pdt{this->get_pdt(pdpte)}; + auto *const pdt{get_pdt(page_pool, pdpte)}; auto *const pdte{pdt->entries.at_if(this->pdto(page_virt))}; - if (pdte->p == bsl::ZERO_UMAX) { - if (bsl::unlikely(!this->add_pt(pdte, us))) { + if (disabled == pdte->p) { + if (bsl::unlikely(!this->add_pt(tls, page_pool, pdte))) { bsl::print() << bsl::here(); return bsl::errc_failure; } @@ -863,875 +1315,225 @@ namespace mk bsl::touch(); } - auto *const pt{this->get_pt(pdte)}; + auto *const pt{get_pt(page_pool, pdte)}; auto *const pte{pt->entries.at_if(this->pto(page_virt))}; - if (bsl::unlikely(pte->p != bsl::ZERO_UMAX)) { + if (bsl::unlikely(disabled != pte->p)) { bsl::error() << "virtual address " // -- << bsl::hex(page_virt) // -- << " already mapped" // -- << bsl::endl // -- << bsl::here(); // -- - return bsl::errc_failure; + return bsl::errc_already_exists; } - pte->phys = (page_phys >> PAGE_SHIFT).get(); - pte->p = bsl::ONE_UMAX.get(); + constexpr auto enable{1_umax}; + constexpr auto disable{0_umax}; - if (executable) { - pte->rw = bsl::ZERO_UMAX.get(); - pte->nx = bsl::ZERO_UMAX.get(); + pte->phys = (page_phys >> HYPERVISOR_PAGE_SHIFT).get(); + pte->p = enable.get(); + pte->us = enable.get(); + pte->auto_release = auto_release.get(); + + if (!(page_flags & MAP_PAGE_WRITE).is_zero()) { + pte->rw = enable.get(); } else { - pte->rw = bsl::ONE_UMAX.get(); - pte->nx = bsl::ONE_UMAX.get(); + pte->rw = disable.get(); } - if (us) { - pte->us = bsl::ONE_UMAX.get(); + if (!(page_flags & MAP_PAGE_EXECUTE).is_zero()) { + pte->nx = disable.get(); } else { - pte->us = bsl::ZERO_UMAX.get(); - } - - if (auto_release) { - pte->auto_release = bsl::ONE_UMAX.get(); - } - else { - pte->auto_release = bsl::ZERO_UMAX.get(); + pte->nx = enable.get(); } return bsl::errc_success; } - /// - /// @brief Unmaps a previously mapped page. - /// - /// - /// @param page_virt the virtual address to unmap - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise - /// - [[nodiscard]] constexpr auto - unmap_page(bsl::safe_uintmax const &page_virt) noexcept -> bsl::errc_type - { - auto *const pml4te{m_pml4t->entries.at_if(this->pml4to(page_virt))}; - if (bsl::unlikely(pml4te->p == bsl::ZERO_UMAX)) { - bsl::error() << "virtual address " // -- - << bsl::hex(page_virt) // -- - << " not mapped" // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - auto *const pdpt{this->get_pdpt(pml4te)}; - auto *const pdpte{pdpt->entries.at_if(this->pdpto(page_virt))}; - if (bsl::unlikely(pdpte->p == bsl::ZERO_UMAX)) { - bsl::error() << "virtual address " // -- - << bsl::hex(page_virt) // -- - << " not mapped" // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - auto *const pdt{this->get_pdt(pdpte)}; - auto *const pdte{pdt->entries.at_if(this->pdto(page_virt))}; - if (bsl::unlikely(pdte->p == bsl::ZERO_UMAX)) { - bsl::error() << "virtual address " // -- - << bsl::hex(page_virt) // -- - << " not mapped" // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - auto *const pt{this->get_pt(pdte)}; - auto *const pte{pt->entries.at_if(this->pto(page_virt))}; - if (bsl::unlikely(pte->p == bsl::ZERO_UMAX)) { - bsl::error() << "virtual address " // -- - << bsl::hex(page_virt) // -- - << " not mapped" // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - *pte = {}; - - bool remove_pt{true}; - for (auto const elem : pt->entries) { - if (elem.data->p != bsl::ZERO_UMAX) { - remove_pt = false; - break; - } - } - - if (remove_pt) { - m_page_pool->deallocate(pt); - *pdte = {}; - } - - bool remove_pdt{true}; - for (auto const elem : pdt->entries) { - if (elem.data->p != bsl::ZERO_UMAX) { - remove_pdt = false; - break; - } - } - - if (remove_pdt) { - m_page_pool->deallocate(pdt); - *pdpte = {}; - } - - bool remove_pdpt{true}; - for (auto const elem : pdpt->entries) { - if (elem.data->p != bsl::ZERO_UMAX) { - remove_pdpt = false; - break; - } - } - - if (remove_pdpt) { - m_page_pool->deallocate(pdpt); - *pml4te = {}; - } - - m_intrinsic->invlpg(page_virt); - return bsl::errc_success; - } - - public: - /// @brief an alias for INTRINSIC_CONCEPT - using intrinsic_type = INTRINSIC_CONCEPT; - /// @brief an alias for PAGE_POOL_CONCEPT - using page_pool_type = PAGE_POOL_CONCEPT; - - /// - /// @brief Creates a root_page_table_t - /// - constexpr root_page_table_t() noexcept = default; - - /// - /// @brief Initializes this root_page_table_t - /// - /// - /// @param intrinsic the intrinsics to use - /// @param page_pool the page pool to use - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise - /// - [[nodiscard]] constexpr auto - initialize(INTRINSIC_CONCEPT *const intrinsic, PAGE_POOL_CONCEPT *const page_pool) &noexcept - -> bsl::errc_type - { - if (bsl::unlikely(m_initialized)) { - bsl::error() << "root_page_table_t already initialized\n" << bsl::here(); - return bsl::errc_failure; - } - - bsl::finally release_on_error{[this]() noexcept -> void { - this->release(); - }}; - - m_intrinsic = intrinsic; - if (bsl::unlikely(nullptr == intrinsic)) { - bsl::error() << "invalid intrinsic\n" << bsl::here(); - return bsl::errc_failure; - } - - m_page_pool = page_pool; - if (bsl::unlikely(nullptr == page_pool)) { - bsl::error() << "invalid page_pool\n" << bsl::here(); - return bsl::errc_failure; - } - - m_pml4t = m_page_pool->template allocate(); - if (bsl::unlikely(nullptr == m_pml4t)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - m_pml4t_phys = m_page_pool->virt_to_phys(m_pml4t); - if (bsl::unlikely(!m_pml4t_phys)) { - bsl::print() << bsl::here(); - return bsl::errc_failure; - } - - release_on_error.ignore(); - m_initialized = true; - - return bsl::errc_success; - } - - /// - /// @brief Releases the memory allocated in this root page table - /// - constexpr void - release() &noexcept - { - if (nullptr != m_page_pool) { - if (nullptr != m_pml4t) { - for (auto const elem : m_pml4t->entries) { - if (elem.data->p == bsl::ZERO_UMAX) { - continue; - } - - if (elem.data->alias != bsl::ZERO_UMAX) { - continue; - } - - this->remove_pdpt(elem.data); - } - } - else { - bsl::touch(); - } - - m_page_pool->deallocate(m_pml4t); - } - else { - bsl::touch(); - } - - m_pml4t = {}; - m_page_pool = {}; - m_intrinsic = {}; - m_initialized = false; - } - - /// - /// @brief Destructor - /// - constexpr ~root_page_table_t() noexcept = default; - - /// - /// @brief copy constructor - /// - /// - /// @param o the object being copied - /// - constexpr root_page_table_t(root_page_table_t const &o) noexcept = delete; - - /// - /// @brief move constructor - /// - /// - /// @param o the object being moved - /// - constexpr root_page_table_t(root_page_table_t &&o) noexcept = default; - - /// - /// @brief copy assignment - /// - /// - /// @param o the object being copied - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(root_page_table_t const &o) &noexcept - -> root_page_table_t & = delete; - - /// - /// @brief move assignment - /// - /// - /// @param o the object being moved - /// @return a reference to *this - /// - [[maybe_unused]] constexpr auto operator=(root_page_table_t &&o) &noexcept - -> root_page_table_t & = default; - - /// - /// @brief Sets the current root page table to this root page table. - /// - constexpr void - activate() const noexcept - { - m_intrinsic->set_cr3(m_pml4t_phys); - } - - /// - /// @brief Returns true if the current root page table is this root - /// page table. - /// - /// - /// @return Returns true if the current root page table is this root - /// page table. - /// - [[nodiscard]] constexpr auto - is_active() const noexcept -> bool - { - return (m_intrinsic->cr3() == m_pml4t_phys); - } - - /// - /// @brief Given a root page table, the pml4te_t enties are aliased - /// into this page table, allowing software using this root page - /// table to access the memory mapped into the provided root page - /// table. The additions are aliases only, meaning when this root - /// page table loses scope, aliased entries added by this function - /// are not returned back to the page pool. - /// - /// - /// @param rpt the root page table to add aliases to - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise - /// - [[nodiscard]] constexpr auto - add_tables(void const *const rpt) &noexcept -> bsl::errc_type - { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); - return bsl::errc_failure; - } - - auto const *const pml4t{static_cast(rpt)}; - if (bsl::unlikely(nullptr == pml4t)) { - bsl::error() << "invalid rpt\n" << bsl::here(); - return bsl::errc_failure; - } - - for (auto const elem : pml4t->entries) { - if (elem.data->p != bsl::ZERO_UMAX) { - auto *const pml4e_dst{m_pml4t->entries.at_if(elem.index)}; - if (bsl::unlikely(pml4e_dst->p != bsl::ZERO_UMAX)) { - bsl::error() << "unable to merge page tables\n" << bsl::here(); - return bsl::errc_failure; - } - - *pml4e_dst = *elem.data; - pml4e_dst->alias = bsl::ONE_UMAX.get(); - } - else { - bsl::touch(); - } - } - - return bsl::errc_success; - } - - /// - /// @brief Given a root page table, the pml4te_t enties are aliased - /// into this page table, allowing software using this root page - /// table to access the memory mapped into the provided root page - /// table. The additions are aliases only, meaning when this root - /// page table loses scope, aliased entries added by this function - /// are not returned back to the page pool. - /// - /// - /// @param rpt the root page table to add aliases to - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise - /// - [[nodiscard]] constexpr auto - add_tables(root_page_table_t const &rpt) &noexcept -> bsl::errc_type - { - return this->add_tables(rpt.m_pml4t); - } - /// /// @brief Maps a page into the root page table being managed - /// by this class using read/write permissions. + /// by this class. This version allows for unaligned virtual and + /// physical addresses and will perform the alignment for you. + /// Note that you should only use this function if you actually + /// need unaligned support to ensure alignment mistakes are not + /// accidentally introduced. /// /// - /// @tparam T defines the type of virtual address being mapped + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use /// @param page_virt the virtual address to map the physical address - /// too + /// too. + /// @param page_phys the physical address to map. If the physical + /// address is set to 0, map_page will use the page pool to + /// determine the physical address. + /// @param page_flags defines how memory should be mapped + /// @param auto_release defines what auto release tag to use /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise - /// - template - [[nodiscard]] constexpr auto - map_page_rw(T const page_virt) &noexcept -> bsl::errc_type - { - static_assert(bsl::is_pointer::value); - static_assert(bsl::is_standard_layout::value); - - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); - return bsl::errc_failure; - } - - if (bsl::unlikely(!page_virt)) { - bsl::error() << "virtual address is invalid: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - if (bsl::unlikely(!this->is_page_aligned(page_virt))) { - bsl::error() << "virtual address is not page aligned: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - auto const page_phys{m_page_pool->virt_to_phys(page_virt)}; - if (bsl::unlikely(!page_phys)) { - bsl::error() << "physical address is invalid: " // -- - << bsl::hex(page_phys) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - return this->map_page(bsl::to_umax(page_virt), page_phys, false, true, false); - } - - /// - /// @brief Maps a page into the root page table being managed - /// by this class using read/write permissions. - /// - /// - /// @param page_virt the virtual address to map the physical address too - /// @param page_phys the physical address to map - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise + /// and friends otherwise /// [[nodiscard]] constexpr auto - map_page_rw( - bsl::safe_uintmax const &page_virt, bsl::safe_uintmax const &page_phys) &noexcept - -> bsl::errc_type + map_page_unaligned( + tls_t &tls, + page_pool_t &page_pool, + bsl::safe_uintmax const &page_virt, + bsl::safe_uintmax const &page_phys, + bsl::safe_uintmax const &page_flags, + bsl::safe_int32 const &auto_release) noexcept -> bsl::errc_type { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); - return bsl::errc_failure; - } - - if (bsl::unlikely(!page_virt)) { - bsl::error() << "virtual address is invalid: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - if (bsl::unlikely(!this->is_page_aligned(page_virt))) { - bsl::error() << "virtual address is not page aligned: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - if (bsl::unlikely(!page_phys)) { - bsl::error() << "physical address is invalid: " // -- - << bsl::hex(page_phys) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - if (bsl::unlikely(!this->is_page_aligned(page_phys))) { - bsl::error() << "physical address is not page aligned: " // -- - << bsl::hex(page_phys) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - return this->map_page(page_virt, page_phys, false, true, false); - } - - /// - /// @brief Maps a page into the root page table being managed - /// by this class using read/execute permissions. - /// - /// - /// @tparam T defines the type of virtual address being mapped - /// @param page_virt the virtual address to map the physical address too - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise - /// - template - [[nodiscard]] constexpr auto - map_page_rx(T const page_virt) &noexcept -> bsl::errc_type - { - static_assert(bsl::is_pointer::value); - static_assert(bsl::is_standard_layout::value); - - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); - return bsl::errc_failure; - } - - if (bsl::unlikely(!page_virt)) { - bsl::error() << "virtual address is invalid: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - if (bsl::unlikely(!this->is_page_aligned(page_virt))) { - bsl::error() << "virtual address is not page aligned: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - auto const page_phys{m_page_pool->virt_to_phys(page_virt)}; - if (bsl::unlikely(!page_phys)) { - bsl::error() << "physical address is invalid: " // -- - << bsl::hex(page_phys) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - return this->map_page(bsl::to_umax(page_virt), page_phys, true, true, false); - } - - /// - /// @brief Maps a page into the root page table being managed - /// by this class using read/execute permissions. - /// - /// - /// @param page_virt the virtual address to map the physical address too - /// @param page_phys the physical address to map - /// @return Returns bsl::errc_success on success, bsl::errc_failure - /// otherwise - /// - [[nodiscard]] constexpr auto - map_page_rx( - bsl::safe_uintmax const &page_virt, bsl::safe_uintmax const &page_phys) &noexcept - -> bsl::errc_type - { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); - return bsl::errc_failure; - } - - if (bsl::unlikely(!page_virt)) { - bsl::error() << "virtual address is invalid: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - if (bsl::unlikely(!this->is_page_aligned(page_virt))) { - bsl::error() << "virtual address is not page aligned: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - if (bsl::unlikely(!page_phys)) { - bsl::error() << "physical address is invalid: " // -- - << bsl::hex(page_phys) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - if (bsl::unlikely(!this->is_page_aligned(page_phys))) { - bsl::error() << "physical address is not page aligned: " // -- - << bsl::hex(page_phys) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::errc_failure; - } - - return this->map_page(page_virt, page_phys, true, true, false); + return this->map_page( + tls, + page_pool, + this->page_aligned(page_virt), + this->page_aligned(page_phys), + page_flags, + auto_release); } /// /// @brief Allocates a page from the provided page pool and maps it - /// into the root page table being managed by this class using - /// read/write permissions. The page is marked as "auto release", - /// meaning when this root page table is released, the pages - /// allocated by this function will automatically be deallocated - /// and put back into the provided page pool. + /// into the root page table being managed by this class The page + /// is marked as "auto release", meaning when this root page table + /// is released, the pages allocated by this function will + /// automatically be deallocated and put back into the provided + /// page pool. Note that this version maps the memory in as + /// read/write. /// /// - /// @param page_virt the virtual address to map the page too - /// @return Returns a pointer to the allocated page, or a nullptr - /// on failure. + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param page_virt the virtual address to map the allocated + /// page to + /// @param auto_release defines what auto release tag to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise /// [[nodiscard]] constexpr auto - allocate_rw(bsl::safe_uintmax const &page_virt) &noexcept -> void * + allocate_page_rw( + tls_t &tls, + page_pool_t &page_pool, + bsl::safe_uintmax const &page_virt, + bsl::safe_int32 const &auto_release) noexcept -> void * { - if (bsl::unlikely(!m_initialized)) { + if (bsl::unlikely_assert(!m_pml4t_phys)) { bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); return nullptr; } - if (bsl::unlikely(!page_virt)) { - bsl::error() << "virtual address is invalid: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- + if (bsl::unlikely_assert(page_virt.is_zero())) { + bsl::error() << "virtual address is invalid " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- return nullptr; } - if (bsl::unlikely(!this->is_page_aligned(page_virt))) { - bsl::error() << "virtual address is not page aligned: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- + if (bsl::unlikely_assert(!this->is_page_aligned(page_virt))) { + bsl::error() << "virtual address is not page aligned " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- return nullptr; } - auto *const page{m_page_pool->template allocate()}; - if (bsl::unlikely(nullptr == page)) { - bsl::print() << bsl::here(); - return nullptr; - } - - auto const page_phys{m_page_pool->virt_to_phys(page)}; - if (bsl::unlikely(!page_phys)) { - bsl::error() << "physical address is invalid: " // -- - << bsl::hex(page_phys) // -- - << bsl::endl // -- - << bsl::here(); // -- + if (bsl::unlikely_assert(!auto_release)) { + bsl::error() << "invalid auto release " // -- + << auto_release // -- + << bsl::endl // -- + << bsl::here(); // -- return nullptr; } - if (bsl::unlikely(!this->map_page(page_virt, page_phys, false, true, true))) { - bsl::print() << bsl::here(); - return nullptr; - } - - return page; + return this->allocate_page( + tls, page_pool, page_virt, MAP_PAGE_READ | MAP_PAGE_WRITE, auto_release); } /// /// @brief Allocates a page from the provided page pool and maps it - /// into the root page table being managed by this class using - /// read/execute permissions. The page is marked as "auto release", - /// meaning when this root page table is released, the pages - /// allocated by this function will automatically be deallocated - /// and put back into the provided page pool. + /// into the root page table being managed by this class The page + /// is marked as "auto release", meaning when this root page table + /// is released, the pages allocated by this function will + /// automatically be deallocated and put back into the provided + /// page pool. Note that this version maps the memory in as + /// read/execute. /// /// - /// @param page_virt the virtual address to map the page too - /// @return Returns a pointer to the allocated page, or a nullptr - /// on failure. + /// @param tls the current TLS block + /// @param page_pool the page_pool_t to use + /// @param page_virt the virtual address to map the allocated + /// page to + /// @param auto_release defines what auto release tag to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise /// [[nodiscard]] constexpr auto - allocate_rx(bsl::safe_uintmax const &page_virt) &noexcept -> void * + allocate_page_rx( + tls_t &tls, + page_pool_t &page_pool, + bsl::safe_uintmax const &page_virt, + bsl::safe_int32 const &auto_release) noexcept -> void * { - if (bsl::unlikely(!m_initialized)) { + if (bsl::unlikely_assert(!m_pml4t_phys)) { bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); return nullptr; } - if (bsl::unlikely(!page_virt)) { - bsl::error() << "virtual address is invalid: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- + if (bsl::unlikely_assert(page_virt.is_zero())) { + bsl::error() << "virtual address is invalid " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- return nullptr; } - if (bsl::unlikely(!this->is_page_aligned(page_virt))) { - bsl::error() << "virtual address is not page aligned: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- + if (bsl::unlikely_assert(!this->is_page_aligned(page_virt))) { + bsl::error() << "virtual address is not page aligned " // -- + << bsl::hex(page_virt) // -- + << bsl::endl // -- + << bsl::here(); // -- return nullptr; } - auto *const page{m_page_pool->template allocate()}; - if (bsl::unlikely(nullptr == page)) { - bsl::print() << bsl::here(); - return nullptr; - } - - auto const page_phys{m_page_pool->virt_to_phys(page)}; - if (bsl::unlikely(!page_phys)) { - bsl::error() << "physical address is invalid: " // -- - << bsl::hex(page_phys) // -- - << bsl::endl // -- - << bsl::here(); // -- + if (bsl::unlikely_assert(!auto_release)) { + bsl::error() << "invalid auto release " // -- + << auto_release // -- + << bsl::endl // -- + << bsl::here(); // -- return nullptr; } - if (bsl::unlikely(!this->map_page(page_virt, page_phys, true, true, true))) { - bsl::print() << bsl::here(); - return nullptr; - } - - return page; - } - - /// - /// @brief Converts the provided virtual address to a physical - /// address by walking the page table. If the resulting conversion - /// is a microkernel address, or the virtual address is not mapped, - /// this function will return an error. - /// - /// - /// @param page_virt the virtual address to convert - /// @return Returns the resulting physical address. - /// - [[nodiscard]] constexpr auto - virt_to_phys(bsl::safe_uintmax const &page_virt) &noexcept -> bsl::safe_uintmax - { - if (bsl::unlikely(!m_initialized)) { - bsl::error() << "root_page_table_t not initialized\n" << bsl::here(); - return bsl::safe_uintmax::zero(true); - } - - if (bsl::unlikely(!page_virt)) { - bsl::error() << "virtual address is invalid: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::safe_uintmax::zero(true); - } - - if (bsl::unlikely(!this->is_page_aligned(page_virt))) { - bsl::error() << "virtual address is not page aligned: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::safe_uintmax::zero(true); - } - - auto *const pml4te{m_pml4t->entries.at_if(this->pml4to(page_virt))}; - if (pml4te->p == bsl::ZERO_UMAX) { - bsl::error() << "virtual address " // -- - << bsl::hex(page_virt) // -- - << " was never mapped" // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::safe_uintmax::zero(true); - } - - if (pml4te->us == bsl::ZERO_UMAX) { - bsl::error() << "unable to convert the kernel virtual address: " // -- - << bsl::hex(page_virt) // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::safe_uintmax::zero(true); - } - - auto *const pdpte{this->get_pdpt(pml4te)->entries.at_if(this->pdpto(page_virt))}; - if (pdpte->p == bsl::ZERO_UMAX) { - bsl::error() << "virtual address " // -- - << bsl::hex(page_virt) // -- - << " was never mapped" // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::safe_uintmax::zero(true); - } - - auto *const pdte{this->get_pdt(pdpte)->entries.at_if(this->pdto(page_virt))}; - if (pdte->p == bsl::ZERO_UMAX) { - bsl::error() << "virtual address " // -- - << bsl::hex(page_virt) // -- - << " was never mapped" // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::safe_uintmax::zero(true); - } - - auto *const pte{this->get_pt(pdte)->entries.at_if(this->pto(page_virt))}; - if (bsl::unlikely(pte->p != bsl::ZERO_UMAX)) { - bsl::error() << "virtual address " // -- - << bsl::hex(page_virt) // -- - << " was never mapped" // -- - << bsl::endl // -- - << bsl::here(); // -- - - return bsl::safe_uintmax::zero(true); - } - - return bsl::safe_uintmax{pte->phys} << PAGE_SHIFT; + return this->allocate_page( + tls, page_pool, page_virt, MAP_PAGE_READ | MAP_PAGE_EXECUTE, auto_release); } /// /// @brief Dumps the provided pml4_t /// /// - /// @tparam T the type of outputter provided - /// @param o the instance of the outputter used to output the value. + /// @param page_pool the page_pool_t to use /// - template constexpr void - dump(bsl::out const o) const noexcept + dump(page_pool_t &page_pool) const noexcept { - if (bsl::unlikely(!m_initialized)) { - o << "[error]" << bsl::endl; + if constexpr (BSL_DEBUG_LEVEL == bsl::CRITICAL_ONLY) { return; } - this->dump_pml4t(o, m_pml4t); + if (bsl::unlikely_assert(!m_pml4t_phys)) { + bsl::print() << "[error]" << bsl::endl; + return; + } + + dump_pml4t(page_pool, m_pml4t); } }; - - /// - /// @brief Outputs the provided mk::root_page_table_t to the provided - /// output type. - /// @related mk::root_page_table_t - /// - /// - /// @tparam T the type of outputter provided - /// @tparam INTRINSIC_CONCEPT defines the type of intrinsics to use - /// @tparam PAGE_POOL_CONCEPT defines the type of page pool to use - /// @tparam PAGE_SIZE defines the size of a page - /// @tparam PAGE_SHIFT defines number of bits in a page - /// @param o the instance of the outputter used to output the value. - /// @param rpt the root_page_table_t to output - /// @return return o - /// - template< - typename T, - typename INTRINSIC_CONCEPT, - typename PAGE_POOL_CONCEPT, - bsl::uintmax PAGE_SIZE, - bsl::uintmax PAGE_SHIFT> - [[maybe_unused]] constexpr auto - operator<<( - bsl::out const o, - mk::root_page_table_t const - &rpt) noexcept -> bsl::out - { - if constexpr (!o) { - return o; - } - - rpt.dump(o); - return o; - } } #endif diff --git a/kernel/src/x64/serial_write.hpp b/kernel/src/x64/serial_write.hpp deleted file mode 100644 index 2b3f8287..00000000 --- a/kernel/src/x64/serial_write.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/// @copyright -/// Copyright (C) 2020 Assured Information Security, Inc. -/// -/// @copyright -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// @copyright -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// @copyright -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -/// SOFTWARE. - -#ifndef SERIAL_WRITE_HPP -#define SERIAL_WRITE_HPP - -#include -#include -#include -#include -#include -#include - -namespace mk -{ - namespace details - { - /// @brief defines the line status register - constexpr bsl::safe_uint16 LSR{bsl::to_u16(5)}; - - /// @brief defines the transmit FIFO empty bit in the LSR - constexpr bsl::safe_uint8 LSR_TRANSMIT_FIFO_EMPTY{bsl::to_u8(1) << bsl::to_u8(5)}; - - /// - /// @brief Reads a byte from the requested serial port register. - /// - /// - /// @param reg the serial port register to read from - /// @return the data read from the requested serial port register - /// - [[nodiscard]] extern "C" auto serial_in(bsl::uint16 reg) noexcept -> bsl::uint8; - - /// - /// @brief Writes a byte to the requested serial port register. - /// - /// - /// @param reg the serial port register to write to - /// @param c the byte to write to the requested serial port register - /// - extern "C" void serial_out(bsl::uint16 reg, bsl::char_type const c) noexcept; - } - - /// - /// @brief Outputs a character to the serial port. - /// - /// - /// @param c the character to output - /// - constexpr void - serial_write(bsl::char_type const c) noexcept - { - if (bsl::is_constant_evaluated()) { - return; - } - - while (true) { - bsl::safe_uint8 const status{ - details::serial_in((details::LSR + bsl::to_u16(HYPERVISOR_SERIAL_PORT)).get())}; - - if ((status & details::LSR_TRANSMIT_FIFO_EMPTY).is_pos()) { - break; - } - - bsl::touch(); - } - - details::serial_out(bsl::to_u16(HYPERVISOR_SERIAL_PORT).get(), c); - } - - /// - /// @brief Outputs a string to the serial port. - /// - /// - /// @param str the string to output - /// - constexpr void - serial_write(bsl::cstr_type const str) noexcept - { - if (bsl::is_constant_evaluated()) { - return; - } - - for (bsl::safe_uintmax i{}; str[i.get()] != '\0'; ++i) { - serial_write(str[i.get()]); - } - } -} - -#endif diff --git a/kernel/src/x64/serial_write_c.S b/kernel/src/x64/serial_write_c.S new file mode 100644 index 00000000..3a8c9505 --- /dev/null +++ b/kernel/src/x64/serial_write_c.S @@ -0,0 +1,54 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl serial_write_c + .type serial_write_c, @function +serial_write_c: + push rax + push rdx + +wait_for_ffio_empty: + mov rdx, HYPERVISOR_SERIAL_PORT + add rdx, 5 + in al, dx + + and al, 0x20 + cmp al, 0x0 + jz wait_for_ffio_empty + + mov rdx, HYPERVISOR_SERIAL_PORT + mov rax, rdi + out dx, al + + pop rdx + pop rax + ret + int 3 + + .size serial_write_c, .-serial_write_c diff --git a/kernel/src/x64/serial_write_hex.S b/kernel/src/x64/serial_write_hex.S new file mode 100644 index 00000000..9b0e538e --- /dev/null +++ b/kernel/src/x64/serial_write_hex.S @@ -0,0 +1,145 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl serial_write_hex + .type serial_write_hex, @function +serial_write_hex: + push rdx + + mov rdx, rdi + + mov rdi, 0x30 + call serial_write_c + + mov rdi, 0x78 + call serial_write_c + + mov rdi, rdx + shr rdi, 60 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 56 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 52 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 48 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 44 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 40 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 36 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 32 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 28 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 24 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 20 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 16 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 12 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 8 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 4 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + and rdi, 0xFF + call serial_write_hex_digit + + pop rdx + ret + int 3 + +serial_write_hex_digit: + + cmp rdi, 9 + jg serial_write_hex_digit_a_to_f + + add rdi, 0x30 + call serial_write_c + + ret + int 3 + +serial_write_hex_digit_a_to_f: + + add rdi, 0x37 + call serial_write_c + + ret + int 3 + + .size serial_write_hex, .-serial_write_hex diff --git a/kernel/src/x64/vmexit_log_t.hpp b/kernel/src/x64/vmexit_log_t.hpp new file mode 100644 index 00000000..8d579e2e --- /dev/null +++ b/kernel/src/x64/vmexit_log_t.hpp @@ -0,0 +1,220 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VMEXIT_LOG_T_HPP +#define VMEXIT_LOG_T_HPP + +#include + +#include +#include +#include +#include +#include + +namespace mk +{ + /// @class mk::vmexit_log_t + /// + /// + /// @brief Stores a log of all VMExits that occur. Each PP has one log + /// that is shared between all of the VPSs so that you get a consistent + /// view of what actually happened during execution, which is more + /// important when implementing guest support as VPSs can swap between + /// execution on the same PP as the hypervisor is moving between VMs. + /// + class vmexit_log_t final + { + /// @brief stores the VMExit log + bsl::array m_vmexit_logs{}; + + /// + /// @brief Dumps the contents of the VMExit log for the requested PP + /// + /// + /// @param str the name of the field + /// @param val the value of the field + /// + static constexpr void + dump_field(bsl::string_view const &str, bsl::safe_uintmax const &val) noexcept + { + if (val.is_zero()) { + bsl::print() << bsl::ylw << str << bsl::blk << bsl::hex(val); + } + else { + bsl::print() << bsl::ylw << str << bsl::rst << bsl::hex(val); + } + } + + public: + /// + /// @brief Adds a record in the VMExit log + /// + /// + /// @param ppid the id of the PP whose log should be added to + /// @param rec the record to add to the log + /// + constexpr void + add(bsl::safe_uint16 const &ppid, vmexit_log_record_t const &rec) noexcept + { + if constexpr (BSL_DEBUG_LEVEL < bsl::VV) { + return; + } + + auto *const pp_log{m_vmexit_logs.at_if(bsl::to_umax(ppid))}; + if (bsl::unlikely(nullptr == pp_log)) { + return; + } + + *pp_log->log.at_if(pp_log->crsr) = rec; + + ++pp_log->crsr; + if (pp_log->crsr < pp_log->log.size()) { + bsl::touch(); + } + else { + pp_log->crsr = {}; + } + } + + /// + /// @brief Dumps the contents of the VMExit log for the requested PP + /// + /// + /// @param ppid the ID of the PP whose log should be dumped + /// + constexpr void + dump(bsl::safe_uint16 const &ppid) noexcept + { + if constexpr (BSL_DEBUG_LEVEL < bsl::VV) { + return; + } + + auto *const pp_log{m_vmexit_logs.at_if(bsl::to_umax(ppid))}; + if (bsl::unlikely(nullptr == pp_log)) { + bsl::error() << "invalid ppid " // -- + << bsl::hex(ppid) // -- + << bsl::endl // -- + << bsl::here(); // -- + + return; + } + + bsl::print() << bsl::mag << "vmexit log for pp ["; + bsl::print() << bsl::rst << bsl::hex(ppid); + bsl::print() << bsl::mag << "]: "; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+---------------------------------"; + bsl::print() << bsl::ylw << "----------------------------------"; + bsl::print() << bsl::ylw << "----------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + + for (bsl::safe_uintmax i{}; i < pp_log->log.size(); ++i) { + auto const *const rec{pp_log->log.at_if(pp_log->crsr)}; + + if (rec->rip.is_pos()) { + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::blu << "VM:"; + bsl::print() << bsl::cyn << bsl::fmt{"04x", rec->vmid}; + bsl::print() << bsl::rst << ", "; + bsl::print() << bsl::blu << "VP:"; + bsl::print() << bsl::cyn << bsl::fmt{"04x", rec->vpid}; + bsl::print() << bsl::rst << ", "; + bsl::print() << bsl::blu << "VPS:"; + bsl::print() << bsl::cyn << bsl::fmt{"04x", rec->vpsid}; + bsl::print() << bsl::rst << ", "; + bsl::print() << bsl::blu << "REASON:"; + bsl::print() << bsl::cyn << bsl::fmt{">2d", rec->exit_reason}; + bsl::print() << bsl::rst << " "; + bsl::print() << bsl::ylw << " |"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << " -"; + this->dump_field(" rip: ", rec->rip); + this->dump_field(" ei1: ", rec->ei1); + this->dump_field(" ei2: ", rec->ei2); + this->dump_field(" ei3: ", rec->ei3); + bsl::print() << bsl::ylw << " |"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << " -"; + this->dump_field(" rax: ", rec->rax); + this->dump_field(" rbx: ", rec->rbx); + this->dump_field(" rcx: ", rec->rcx); + this->dump_field(" rdx: ", rec->rdx); + bsl::print() << bsl::ylw << " |"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << " -"; + this->dump_field(" rbp: ", rec->rbp); + this->dump_field(" rsi: ", rec->rsi); + this->dump_field(" rdi: ", rec->rdi); + this->dump_field(" r08: ", rec->r8); + bsl::print() << bsl::ylw << " |"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << " -"; + this->dump_field(" r09: ", rec->r9); + this->dump_field(" r10: ", rec->r10); + this->dump_field(" r11: ", rec->r11); + this->dump_field(" r12: ", rec->r12); + bsl::print() << bsl::ylw << " |"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "| "; + bsl::print() << bsl::rst << " -"; + this->dump_field(" r13: ", rec->r13); + this->dump_field(" r14: ", rec->r14); + this->dump_field(" r15: ", rec->r15); + this->dump_field(" rsp: ", rec->rsp); + bsl::print() << bsl::ylw << " |"; + bsl::print() << bsl::rst << bsl::endl; + + bsl::print() << bsl::ylw << "+---------------------------------"; + bsl::print() << bsl::ylw << "----------------------------------"; + bsl::print() << bsl::ylw << "----------------------------------+"; + bsl::print() << bsl::rst << bsl::endl; + } + else { + bsl::touch(); + } + + ++pp_log->crsr; + if (pp_log->crsr < pp_log->log.size()) { + bsl::touch(); + } + else { + pp_log->crsr = {}; + } + } + } + }; +} + +#endif diff --git a/kernel/src/x64/vmexit_loop_entry.S b/kernel/src/x64/vmexit_loop_entry.S index d223bb7c..141c18ee 100644 --- a/kernel/src/x64/vmexit_loop_entry.S +++ b/kernel/src/x64/vmexit_loop_entry.S @@ -51,7 +51,7 @@ vmexit_loop_entry: push rax - mov rax, gs:[0x270] + mov rax, gs:[0x268] cmp rax, 0x0 jne skip_first_launch_logic @@ -76,14 +76,14 @@ install_fast_fail_and_continue_loop: * NOTE: * - If we get here, it is because the VMExit was successful, in which * case, we need to state that the next exit will not be our first, - * and then insteall our fast fail entry point which is what will + * and then install our fast fail entry point which is what will * execute in the event of an error instead of the current fast fail * entry point, which depends on what was executing at the time of the * error occuring. */ mov rax, 0x1 - mov gs:[0x270], rax + mov gs:[0x268], rax lea rax, [rip + fast_fail_entry] mov gs:[0x180], rax diff --git a/kernel/src/x64/yield.S b/kernel/src/x64/yield.S new file mode 100644 index 00000000..2b178846 --- /dev/null +++ b/kernel/src/x64/yield.S @@ -0,0 +1,37 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl yield + .type yield, @function +yield: + + pause + ret + + .size yield, .-yield diff --git a/kernel/test/.clang-tidy b/kernel/test/.clang-tidy new file mode 100644 index 00000000..1c2bf236 --- /dev/null +++ b/kernel/test/.clang-tidy @@ -0,0 +1,59 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +Checks: + ' + -*, + bsl-*, + -bsl-template-generic-param, + -bsl-literals-user-defined, + -bsl-lambda-implicit-capture, + -bsl-unused-return-value, + bugprone-*, + -bugprone-branch-clone, + cert-*, + -cert-dcl21-cpp, + -cert-oop54-cpp, + clang-analyzer-*, + -clang-analyzer-core.CallAndMessage, + -clang-analyzer-core.NullDereference, + -clang-analyzer-core.NonNullParamChecker, + cppcoreguidelines-*, + -cppcoreguidelines-avoid-non-const-global-variables, + hicpp-*, + -hicpp-function-size, + misc-*, + -misc-misplaced-const, + -misc-non-private-member-variables-in-classes, + modernize-*, + -modernize-use-default-member-init, + performance-*, + readability-*, + -readability-redundant-member-init, + -readability-avoid-const-params-in-decls, + -readability-static-accessed-through-instance, + -readability-function-size + ' +WarningsAsErrors: '*' +HeaderFilterRegex: '.*' +AnalyzeTemporaryDtors: false +FormatStyle: none +UseColor: true diff --git a/kernel/test/CMakeLists.txt b/kernel/test/CMakeLists.txt new file mode 100644 index 00000000..1d7eda2b --- /dev/null +++ b/kernel/test/CMakeLists.txt @@ -0,0 +1,201 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +include(${bsl_SOURCE_DIR}/cmake/function/bf_add_test.cmake) + +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + +list(APPEND INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include + ${CMAKE_CURRENT_LIST_DIR}/../mocks +) + +list(APPEND SYSTEM_INCLUDES + ${CMAKE_SOURCE_DIR}/syscall/include/cpp + ${CMAKE_SOURCE_DIR}/syscall/mocks/cpp + ${CMAKE_SOURCE_DIR}/loader/include/interface/cpp +) + +list(APPEND COMMON_INCLUDES + ${INCLUDES} +) + +list(APPEND COMMON_SYSTEM_INCLUDES + ${SYSTEM_INCLUDES} +) + +list(APPEND X64_INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include/x64 + ${CMAKE_CURRENT_LIST_DIR}/../mocks/x64 + ${INCLUDES} +) + +list(APPEND X64_SYSTEM_INCLUDES + ${CMAKE_SOURCE_DIR}/syscall/include/cpp/x64 + ${CMAKE_SOURCE_DIR}/syscall/mocks/cpp/x64 + ${CMAKE_SOURCE_DIR}/loader/include/interface/cpp/x64 + ${SYSTEM_INCLUDES} +) + +list(APPEND AMD_INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/amd + ${CMAKE_CURRENT_LIST_DIR}/../mocks/x64/amd + ${X64_INCLUDES} +) + +list(APPEND AMD_SYSTEM_INCLUDES + ${CMAKE_SOURCE_DIR}/syscall/include/cpp/x64/amd + ${CMAKE_SOURCE_DIR}/syscall/mocks/cpp/x64/amd + ${CMAKE_SOURCE_DIR}/loader/include/interface/cpp/x64/amd + ${X64_SYSTEM_INCLUDES} +) + +list(APPEND INTEL_INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intel + ${CMAKE_CURRENT_LIST_DIR}/../mocks/x64/intel + ${X64_INCLUDES} +) + +list(APPEND INTEL_SYSTEM_INCLUDES + ${CMAKE_SOURCE_DIR}/syscall/include/cpp/x64/intel + ${CMAKE_SOURCE_DIR}/syscall/mocks/cpp/x64/intel + ${CMAKE_SOURCE_DIR}/loader/include/interface/cpp/x64/intel + ${X64_SYSTEM_INCLUDES} +) + +list(APPEND AARCH64_INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64 + ${CMAKE_CURRENT_LIST_DIR}/../mocks/arm/aarch64 + ${INCLUDES} +) + +list(APPEND AARCH64_SYSTEM_INCLUDES + ${CMAKE_SOURCE_DIR}/syscall/include/cpp/arm/aarch64 + ${CMAKE_SOURCE_DIR}/syscall/mocks/cpp/arm/aarch64 + ${CMAKE_SOURCE_DIR}/loader/include/interface/cpp/arm/aarch64 + ${SYSTEM_INCLUDES} +) + +# ------------------------------------------------------------------------------ +# Definitions +# ------------------------------------------------------------------------------ + +list(APPEND DEFINES + HYPERVISOR_DEBUG_RING_SIZE=0x7FF0 + HYPERVISOR_PAGE_SIZE=0x1000_umax + HYPERVISOR_MAX_VMS=2_umax + HYPERVISOR_MAX_VPS=2_umax + HYPERVISOR_MAX_VPSS=2_umax + HYPERVISOR_MK_PAGE_POOL_ADDR=0x1000_umax + HYPERVISOR_MK_HUGE_POOL_ADDR=0x1000_umax +) + +list(APPEND COMMON_DEFINES + ${DEFINES} +) + +list(APPEND X64_DEFINES + ${DEFINES} +) + +list(APPEND AMD_DEFINES + ${X64_DEFINES} +) + +list(APPEND INTEL_DEFINES + ${X64_DEFINES} +) + +list(APPEND AARCH64_DEFINES + ${DEFINES} +) + +# ------------------------------------------------------------------------------ +# Tests +# ------------------------------------------------------------------------------ + +# add_subdirectory(bfelf/elf64_ehdr_t) +# add_subdirectory(bfelf/elf64_phdr_t) +# add_subdirectory(cstdio) +# add_subdirectory(details/print_thread_id) +# add_subdirectory(details/putc_stderr) +# add_subdirectory(details/putc_stdout) +# add_subdirectory(details/puts_stderr) +# add_subdirectory(details/puts_stdout) +# add_subdirectory(debug_ring_write) +# add_subdirectory(dispatch_esr_page_fault) +# add_subdirectory(dispatch_syscall) +# add_subdirectory(dispatch_syscall_callback_op) +# add_subdirectory(dispatch_syscall_callback_op_failure) +# add_subdirectory(dispatch_syscall_control_op) +# add_subdirectory(dispatch_syscall_control_op_failure) +# add_subdirectory(dispatch_syscall_debug_op) +# add_subdirectory(dispatch_syscall_debug_op_failure) +# add_subdirectory(dispatch_syscall_handle_op) +# add_subdirectory(dispatch_syscall_handle_op_failure) +# add_subdirectory(dispatch_syscall_mem_op) +# add_subdirectory(dispatch_syscall_mem_op_failure) +# add_subdirectory(dispatch_syscall_vm_op) +# add_subdirectory(dispatch_syscall_vm_op_failure) +# add_subdirectory(dispatch_syscall_vp_op) +# add_subdirectory(dispatch_syscall_vp_op_failure) +# add_subdirectory(dispatch_syscall_vps_op) +# add_subdirectory(dispatch_syscall_vps_op_failure) +# add_subdirectory(ext_pool_t) +# add_subdirectory(ext_t) +# add_subdirectory(fast_fail) +add_subdirectory(huge_pool_t) +# add_subdirectory(lock_guard_t) +# add_subdirectory(mk_main) +# add_subdirectory(msg_halt) +# add_subdirectory(msg_stack_chk_fail) +add_subdirectory(page_pool_t) +# add_subdirectory(serial_write) +# add_subdirectory(spinlock_t) +# add_subdirectory(vm_pool_t) +# add_subdirectory(vm_t) +# add_subdirectory(vmexit_loop) +# add_subdirectory(vp_pool_t) +# add_subdirectory(vp_t) +# add_subdirectory(vps_pool_t) + +# add_subdirectory(x64/dispatch_esr) +# add_subdirectory(x64/root_page_table_t) +# add_subdirectory(x64/vmexit_log_t) + +# add_subdirectory(x64/amd/dispatch_esr_nmi) +# add_subdirectory(x64/amd/dispatch_syscall_intrinsic_op) +# add_subdirectory(x64/amd/intrinsic_t) +# add_subdirectory(x64/amd/vps_t) + +# add_subdirectory(x64/intel/dispatch_esr_nmi) +# add_subdirectory(x64/intel/dispatch_syscall_intrinsic_op) +# add_subdirectory(x64/intel/intrinsic_t) +# add_subdirectory(x64/intel/vps_t) + +# add_subdirectory(arm/aarch64/dispatch_esr) +# add_subdirectory(arm/aarch64/dispatch_syscall_intrinsic_op) +# add_subdirectory(arm/aarch64/intrinsic_t) +# add_subdirectory(arm/aarch64/root_page_table_t) +# add_subdirectory(arm/aarch64/vmexit_log_t) +# add_subdirectory(arm/aarch64/vps_t) diff --git a/kernel/test/arm/aarch64/dispatch_esr/CMakeLists.txt b/kernel/test/arm/aarch64/dispatch_esr/CMakeLists.txt new file mode 100644 index 00000000..95c1094e --- /dev/null +++ b/kernel/test/arm/aarch64/dispatch_esr/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) +bf_add_test(behavior INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) diff --git a/kernel/test/arm/aarch64/dispatch_esr/behavior.cpp b/kernel/test/arm/aarch64/dispatch_esr/behavior.cpp new file mode 100644 index 00000000..71a63b0f --- /dev/null +++ b/kernel/test/arm/aarch64/dispatch_esr/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/arm/aarch64/dispatch_esr.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/arm/aarch64/dispatch_esr/requirements.cpp b/kernel/test/arm/aarch64/dispatch_esr/requirements.cpp new file mode 100644 index 00000000..8aecd76b --- /dev/null +++ b/kernel/test/arm/aarch64/dispatch_esr/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/arm/aarch64/dispatch_esr.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/arm/aarch64/dispatch_syscall_intrinsic_op/CMakeLists.txt b/kernel/test/arm/aarch64/dispatch_syscall_intrinsic_op/CMakeLists.txt new file mode 100644 index 00000000..95c1094e --- /dev/null +++ b/kernel/test/arm/aarch64/dispatch_syscall_intrinsic_op/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) +bf_add_test(behavior INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) diff --git a/kernel/test/arm/aarch64/dispatch_syscall_intrinsic_op/behavior.cpp b/kernel/test/arm/aarch64/dispatch_syscall_intrinsic_op/behavior.cpp new file mode 100644 index 00000000..644eebb5 --- /dev/null +++ b/kernel/test/arm/aarch64/dispatch_syscall_intrinsic_op/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/arm/aarch64/dispatch_syscall_intrinsic_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/arm/aarch64/dispatch_syscall_intrinsic_op/requirements.cpp b/kernel/test/arm/aarch64/dispatch_syscall_intrinsic_op/requirements.cpp new file mode 100644 index 00000000..f50a7809 --- /dev/null +++ b/kernel/test/arm/aarch64/dispatch_syscall_intrinsic_op/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/arm/aarch64/dispatch_syscall_intrinsic_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/arm/aarch64/intrinsic_t/CMakeLists.txt b/kernel/test/arm/aarch64/intrinsic_t/CMakeLists.txt new file mode 100644 index 00000000..95c1094e --- /dev/null +++ b/kernel/test/arm/aarch64/intrinsic_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) +bf_add_test(behavior INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) diff --git a/kernel/test/arm/aarch64/intrinsic_t/behavior.cpp b/kernel/test/arm/aarch64/intrinsic_t/behavior.cpp new file mode 100644 index 00000000..a62924bb --- /dev/null +++ b/kernel/test/arm/aarch64/intrinsic_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/arm/aarch64/intrinsic_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/arm/aarch64/intrinsic_t/requirements.cpp b/kernel/test/arm/aarch64/intrinsic_t/requirements.cpp new file mode 100644 index 00000000..0b4dcdbb --- /dev/null +++ b/kernel/test/arm/aarch64/intrinsic_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/arm/aarch64/intrinsic_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/arm/aarch64/root_page_table_t/CMakeLists.txt b/kernel/test/arm/aarch64/root_page_table_t/CMakeLists.txt new file mode 100644 index 00000000..95c1094e --- /dev/null +++ b/kernel/test/arm/aarch64/root_page_table_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) +bf_add_test(behavior INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) diff --git a/kernel/test/arm/aarch64/root_page_table_t/behavior.cpp b/kernel/test/arm/aarch64/root_page_table_t/behavior.cpp new file mode 100644 index 00000000..748a5521 --- /dev/null +++ b/kernel/test/arm/aarch64/root_page_table_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/arm/aarch64/root_page_table_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/arm/aarch64/root_page_table_t/requirements.cpp b/kernel/test/arm/aarch64/root_page_table_t/requirements.cpp new file mode 100644 index 00000000..a5fa0417 --- /dev/null +++ b/kernel/test/arm/aarch64/root_page_table_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/arm/aarch64/root_page_table_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/arm/aarch64/vmexit_log_t/CMakeLists.txt b/kernel/test/arm/aarch64/vmexit_log_t/CMakeLists.txt new file mode 100644 index 00000000..95c1094e --- /dev/null +++ b/kernel/test/arm/aarch64/vmexit_log_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) +bf_add_test(behavior INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) diff --git a/kernel/test/arm/aarch64/vmexit_log_t/behavior.cpp b/kernel/test/arm/aarch64/vmexit_log_t/behavior.cpp new file mode 100644 index 00000000..5d1df1d5 --- /dev/null +++ b/kernel/test/arm/aarch64/vmexit_log_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/arm/aarch64/vmexit_log_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/arm/aarch64/vmexit_log_t/requirements.cpp b/kernel/test/arm/aarch64/vmexit_log_t/requirements.cpp new file mode 100644 index 00000000..bd8364da --- /dev/null +++ b/kernel/test/arm/aarch64/vmexit_log_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/arm/aarch64/vmexit_log_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/arm/aarch64/vps_t/CMakeLists.txt b/kernel/test/arm/aarch64/vps_t/CMakeLists.txt new file mode 100644 index 00000000..95c1094e --- /dev/null +++ b/kernel/test/arm/aarch64/vps_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) +bf_add_test(behavior INCLUDES ${AARCH64_INCLUDES} SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} DEFINES ${AARCH64_DEFINES}) diff --git a/kernel/test/arm/aarch64/vps_t/behavior.cpp b/kernel/test/arm/aarch64/vps_t/behavior.cpp new file mode 100644 index 00000000..a62924bb --- /dev/null +++ b/kernel/test/arm/aarch64/vps_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/arm/aarch64/intrinsic_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/arm/aarch64/vps_t/requirements.cpp b/kernel/test/arm/aarch64/vps_t/requirements.cpp new file mode 100644 index 00000000..0b4dcdbb --- /dev/null +++ b/kernel/test/arm/aarch64/vps_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/arm/aarch64/intrinsic_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/cmake/function/hypervisor_add_header_depends.cmake b/kernel/test/bfelf/elf64_ehdr_t/CMakeLists.txt similarity index 82% rename from cmake/function/hypervisor_add_header_depends.cmake rename to kernel/test/bfelf/elf64_ehdr_t/CMakeLists.txt index afad37c8..cb793e42 100644 --- a/cmake/function/hypervisor_add_header_depends.cmake +++ b/kernel/test/bfelf/elf64_ehdr_t/CMakeLists.txt @@ -19,8 +19,5 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -# Add's header dependencies to a source file to ensure proper tracking -# -macro(hypervisor_add_header_depends SOURCE_FILE) - set_property(SOURCE ${SOURCE_FILE} APPEND PROPERTY OBJECT_DEPENDS ${ARGN}) -endmacro(hypervisor_add_header_depends) +bf_add_test(requirements INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) +bf_add_test(behavior INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) diff --git a/kernel/test/bfelf/elf64_ehdr_t/behavior.cpp b/kernel/test/bfelf/elf64_ehdr_t/behavior.cpp new file mode 100644 index 00000000..e28de637 --- /dev/null +++ b/kernel/test/bfelf/elf64_ehdr_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/bfelf/elf64_ehdr_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/bfelf/elf64_ehdr_t/requirements.cpp b/kernel/test/bfelf/elf64_ehdr_t/requirements.cpp new file mode 100644 index 00000000..c599e1a8 --- /dev/null +++ b/kernel/test/bfelf/elf64_ehdr_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/bfelf/elf64_ehdr_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/bfelf/elf64_phdr_t/CMakeLists.txt b/kernel/test/bfelf/elf64_phdr_t/CMakeLists.txt new file mode 100644 index 00000000..cb793e42 --- /dev/null +++ b/kernel/test/bfelf/elf64_phdr_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) +bf_add_test(behavior INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) diff --git a/kernel/test/bfelf/elf64_phdr_t/behavior.cpp b/kernel/test/bfelf/elf64_phdr_t/behavior.cpp new file mode 100644 index 00000000..bb3d41e7 --- /dev/null +++ b/kernel/test/bfelf/elf64_phdr_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/bfelf/elf64_phdr_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/bfelf/elf64_phdr_t/requirements.cpp b/kernel/test/bfelf/elf64_phdr_t/requirements.cpp new file mode 100644 index 00000000..ab03ca01 --- /dev/null +++ b/kernel/test/bfelf/elf64_phdr_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/bfelf/elf64_phdr_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/common_arch/tls_t.hpp b/kernel/test/common_arch/tls_t.hpp new file mode 100644 index 00000000..95dec6d8 --- /dev/null +++ b/kernel/test/common_arch/tls_t.hpp @@ -0,0 +1,202 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TLS_T_HPP +#define TLS_T_HPP + +#include + +#include +#include + +namespace mk +{ + /// @struct mk::tls_t + /// + /// + /// @brief Defines the layout of the microkernel's TLS block. This + /// should not be confused with the TLS blocks given to an extension, + /// for which there are two, the TLS block for thread_local and the + /// TLS block provided by the microkernel's ABI. + /// + struct tls_t final + { + /// -------------------------------------------------------------------- + /// Extension State + /// -------------------------------------------------------------------- + + /// @brief RAX, stores the extension's syscall + bsl::uintmax ext_syscall; + /// @brief RDI, stores the value of REG0 for the extension + bsl::uintmax ext_reg0; + /// @brief RSI, stores the value of REG1 for the extension + bsl::uintmax ext_reg1; + /// @brief RDX, stores the value of REG2 for the extension + bsl::uintmax ext_reg2; + /// @brief R10, stores the value of REG3 for the extension + bsl::uintmax ext_reg3; + /// @brief R8, stores the value of REG4 for the extension + bsl::uintmax ext_reg4; + /// @brief R9, stores the value of REG5 for the extension + bsl::uintmax ext_reg5; + + /// -------------------------------------------------------------------- + /// ESR State + /// -------------------------------------------------------------------- + + /// @brief stores the value of ip for the ESR + bsl::uintmax esr_ip; + /// @brief stores the value of sp for the ESR + bsl::uintmax esr_sp; + + /// @brief stores the value of the ESR vector + bsl::uintmax esr_vector; + /// @brief stores the value of the ESR error code + bsl::uintmax esr_error_code; + + /// @brief stores the value of a page fault address for the ESR + bsl::uintmax esr_pf_addr; + + /// -------------------------------------------------------------------- + /// Fast Fail Information + /// -------------------------------------------------------------------- + + /// @brief stores the current fast fail address + bsl::uintmax current_fast_fail_ip; + /// @brief stores the current fast fail stack + bsl::uintmax current_fast_fail_sp; + + /// @brief stores the mk_main fast fail address + bsl::uintmax mk_main_fast_fail_ip; + /// @brief stores the mk_main fast fail stack + bsl::uintmax mk_main_fast_fail_sp; + + /// @brief stores the call_ext fast fail address + bsl::uintmax call_ext_fast_fail_ip; + /// @brief stores the call_ext fast fail stack + bsl::uintmax call_ext_fast_fail_sp; + + /// @brief stores the dispatch_syscall fast fail address + bsl::uintmax dispatch_syscall_fast_fail_ip; + /// @brief stores the dispatch_syscall fast fail stack + bsl::uintmax dispatch_syscall_fast_fail_sp; + + /// @brief stores the vmexit loop address + bsl::uintmax vmexit_loop_ip; + /// @brief stores the vmexit loop stack + bsl::uintmax vmexit_loop_sp; + + /// -------------------------------------------------------------------- + /// Context Information + /// -------------------------------------------------------------------- + + /// @brief stores the virtual address of this TLS block + tls_t *self; + + /// @brief stores the currently active VMID + bsl::uint16 ppid; + /// @brief stores the total number of online PPs + bsl::uint16 online_pps; + /// @brief reserved + bsl::uint16 reserved_padding0; + /// @brief reserved + bsl::uint16 reserved_padding1; + + /// @brief stores the currently active extension + void *ext; + /// @brief stores the extension registered for VMExits + void *ext_vmexit; + /// @brief stores the extension registered for fast fail events + void *ext_fail; + + /// @brief stores the loader provided state for the microkernel + loader::state_save_t *mk_state; + /// @brief stores the loader provided state for the root VP + loader::state_save_t *root_vp_state; + + /// @brief stores the currently active extension ID + bsl::uint16 active_extid; + /// @brief stores the currently active VMID + bsl::uint16 active_vmid; + /// @brief stores the currently active VPID + bsl::uint16 active_vpid; + /// @brief stores the currently active VPSID + bsl::uint16 active_vpsid; + + /// @brief stores the sp used by extensions for callbacks + bsl::uintmax sp; + /// @brief stores the tps used by extensions for callbacks + bsl::uintmax tp; + + /// @brief used to store a return address for unsafe ops + bsl::uintmax unsafe_rip; + + /// @brief reserved + bsl::uintmax reserved_padding2; + /// @brief reserved + bsl::uintmax reserved_padding3; + + /// @brief stores whether or not the first launch succeeded + bsl::uintmax first_launch_succeeded; + + /// @brief stores the currently active root page table + void *active_rpt; + + /// -------------------------------------------------------------------- + /// Failure Handling + /// -------------------------------------------------------------------- + + /// @brief stores a whether or not state is changing + bool state_reversal_required; + + /// @brief stores the syscall return status + bsl::uintmax syscall_ret_status; + + /// @brief logs an extid for state reversal if needed + bsl::uint16 log_extid; + /// @brief logs a vmid for state reversal if needed + bsl::uint16 log_vmid; + /// @brief logs a vpid for state reversal if needed + bsl::uint16 log_vpid; + /// @brief logs a vpsid for state reversal if needed + bsl::uint16 log_vpsid; + + /// @brief logs an ext for state reversal if needed + void *log_ext; + /// @brief logs a vm for state reversal if needed + void *log_vm; + /// @brief logs a vp for state reversal if needed + void *log_vp; + /// @brief logs a vps for state reversal if needed + void *log_vps; + + /// -------------------------------------------------------------------- + /// Unit Test Specific + /// -------------------------------------------------------------------- + + bsl::errc_type test_ret; + }; +} + +#endif diff --git a/kernel/test/common_platform/bfelf/elf64_ehdr_t.hpp b/kernel/test/common_platform/bfelf/elf64_ehdr_t.hpp new file mode 100644 index 00000000..99dfa2a0 --- /dev/null +++ b/kernel/test/common_platform/bfelf/elf64_ehdr_t.hpp @@ -0,0 +1,195 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TEST_BFELF_ELF64_EHDR_T_HPP +#define TEST_BFELF_ELF64_EHDR_T_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma pack(push, 1) + +namespace bfelf +{ + /// @brief e_ident[EI_MAG0] contains 0x7FU for file identification + constexpr auto EI_MAG0{0_umax}; + /// @brief e_ident[EI_MAG1] contains 0x45U for file identification + constexpr auto EI_MAG1{1_umax}; + /// @brief e_ident[EI_MAG2] contains 0x4CU for file identification + constexpr auto EI_MAG2{2_umax}; + /// @brief e_ident[EI_MAG3] contains 0x46U for file identification + constexpr auto EI_MAG3{3_umax}; + /// @brief e_ident[EI_CLASS] identifies if the file is 32bit or 64 bit + constexpr auto EI_CLASS{4_umax}; + /// @brief e_ident[EI_DATA] specifies the data bit encoding of the file + constexpr auto EI_DATA{5_umax}; + /// @brief e_ident[EI_VERSION] identifies the version of the file + constexpr auto EI_VERSION{6_umax}; + /// @brief e_ident[EI_OSABI] identifies file's ABI scheme + constexpr auto EI_OSABI{7_umax}; + /// @brief e_ident[EI_ABIVERSION] identifies file's ABI version + constexpr auto EI_ABIVERSION{8_umax}; + /// @brief defines the size of e_ident + constexpr auto EI_NIDENT{16_umax}; + + /// @brief defines the expected e_ident[EI_MAG0] value + constexpr auto ELFMAG0{0x7F_u8}; + /// @brief defines the expected e_ident[EI_MAG1] value + constexpr auto ELFMAG1{0x45_u8}; + /// @brief defines the expected e_ident[EI_MAG2] value + constexpr auto ELFMAG2{0x4C_u8}; + /// @brief defines the expected e_ident[EI_MAG3] value + constexpr auto ELFMAG3{0x46_u8}; + + /// @brief defines e_ident[EI_CLASS] for 32bit objects + constexpr auto ELFCLASS32{1_u8}; + /// @brief defines e_ident[EI_CLASS] for 64bit objects + constexpr auto ELFCLASS64{2_u8}; + + /// @brief defines e_ident[EI_DATA] for little endian + constexpr auto ELFDATA2LSB{1_u8}; + /// @brief defines e_ident[EI_DATA] for big endian + constexpr auto ELFDATA2MSB{2_u8}; + + /// @brief defines e_ident[EI_OSABI] for system v abi + constexpr auto ELFOSABI_SYSV{0_u8}; + /// @brief defines e_ident[EI_OSABI] for hp-ux operating system + constexpr auto ELFOSABI_HPUX{1_u8}; + /// @brief defines e_ident[EI_OSABI] for standalone applications + constexpr auto ELFOSABI_STANDALONE{255_u8}; + + /// @brief defines e_type for no file type + constexpr auto ET_NONE{0_u16}; + /// @brief defines e_type for an relocatable object file + constexpr auto ET_REL{1_u16}; + /// @brief defines e_type for an executable file + constexpr auto ET_EXEC{2_u16}; + /// @brief defines e_type for an shared object file + constexpr auto ET_DYN{3_u16}; + /// @brief defines e_type for an core file + constexpr auto ET_CORE{4_u16}; + /// @brief defines e_type for an environment-specific use (lo) + constexpr auto ET_LOOS{0xFE00_u16}; + /// @brief defines e_type for an environment-specific use (hi) + constexpr auto ET_HIOS{0xFEFF_u16}; + /// @brief defines e_type for an processor-specific use (lo) + constexpr auto ET_LOPROC{0xFF00_u16}; + /// @brief defines e_type for an processor-specific use (hi) + constexpr auto ET_HIPROC{0xFFFF_u16}; + + /// @struct elf64_ehdr_t + /// + /// + /// @brief The file header is located at the beginning of the file, + /// and is used to locate the other parts of the file + /// + struct elf64_ehdr_t final + { + /// @brief ELF identification + bsl::array e_ident; + /// @brief object file type + bsl::uint16 e_type; + /// @brief machine type + bsl::uint16 e_machine; + /// @brief object file version + bsl::uint32 e_version; + /// @brief entry point address + bsl::uint64 e_entry; + /// @brief program header offset + bsl::uint64 e_phoff; + /// @brief section header offset + bsl::uint64 e_shoff; + /// @brief processor-specific flags + bsl::uint32 e_flags; + /// @brief ELF header size + bsl::uint16 e_ehsize; + /// @brief size of program header entry + bsl::uint16 e_phentsize; + /// @brief number of program header entries + bsl::uint16 e_phnum; + /// @brief size of section header entry + bsl::uint16 e_shentsize; + /// @brief number of section header entries + bsl::uint16 e_shnum; + /// @brief section name string table index + bsl::uint16 e_shstrndx; + }; + + /// + /// @brief Returns a pointer to an ELF header given an ELF file + /// + /// + /// @param file the ELF file to get the header from + /// @return returns a pointer to the ELF header, or nullptr on error + /// + [[nodiscard]] constexpr auto + get_elf64_ehdr(bsl::span const &file) noexcept -> elf64_ehdr_t const * + { + bsl::discard(file); + return nullptr; + } + + /// + /// @brief Checks whether or not a given ELF file is in a format that + /// this ELF loader can handle. + /// + /// + /// @param file a pointer to the elf file + /// @return Returns 0 on success or an error code on failure. + /// + [[nodiscard]] constexpr auto + validate_elf64_ehdr(bsl::span const &file) noexcept -> bsl::errc_type + { + bsl::discard(file); + return bsl::errc_failure; + } + + /// + /// @brief Returns the ELF entry point given an ELF file, or + /// bsl::safe_uintmax::failure() if a entry point does not exist or + /// a failure occurs. + /// + /// + /// @param file the ELF file to get the ELF entry point from + /// @return Returns the ELF entry point given an ELF file, or + /// bsl::safe_uintmax::failure() if a entry point does not exist or + /// a failure occurs. + /// + [[nodiscard]] constexpr auto + get_elf64_ip(bsl::span const &file) noexcept -> bsl::safe_uintmax + { + bsl::discard(file); + return bsl::safe_uintmax::failure(); + } +} + +#pragma pack(pop) + +#endif diff --git a/kernel/test/common_platform/bfelf/elf64_phdr_t.hpp b/kernel/test/common_platform/bfelf/elf64_phdr_t.hpp new file mode 100644 index 00000000..a69679f4 --- /dev/null +++ b/kernel/test/common_platform/bfelf/elf64_phdr_t.hpp @@ -0,0 +1,126 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TEST_BFELF_ELF64_PHDR_T_HPP +#define TEST_BFELF_ELF64_PHDR_T_HPP + +#include "elf64_ehdr_t.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#pragma pack(push, 1) + +namespace bfelf +{ + /// @brief defines p_type for unused entry + constexpr auto PT_NULL{0_u32}; + /// @brief defines p_type for a loadable segment + constexpr auto PT_LOAD{1_u32}; + /// @brief defines p_type for dynamic linking tables + constexpr auto PT_DYNAMIC{2_u32}; + /// @brief defines p_type for the program interpreter path + constexpr auto PT_INTERP{3_u32}; + /// @brief defines p_type for note sections + constexpr auto PT_NOTE{4_u32}; + /// @brief defines p_type for reserved + constexpr auto PT_SHLIB{5_u32}; + /// @brief defines p_type for the program header table + constexpr auto PT_PHDR{6_u32}; + /// @brief defines p_type for the tls segment + constexpr auto PT_TLS{7_u32}; + /// @brief defines p_type for environment-specific use (lo) + constexpr auto PT_LOOS{0x60000000_u32}; + /// @brief defines p_type for the GNU stack segment + constexpr auto PT_GNU_STACK{0x6474e551_u32}; + /// @brief defines p_type for environment-specific use (hi) + constexpr auto PT_HIOS{0x6FFFFFFF_u32}; + /// @brief defines p_type for processor-specific use (lo) + constexpr auto PT_LOPROC{0x70000000_u32}; + /// @brief defines p_type for processor-specific use (hi) + constexpr auto PT_HIPROC{0x7FFFFFFF_u32}; + + /// @brief defines p_flags for execute permissions + constexpr auto PF_X{1_u32}; + /// @brief defines p_flags for write permissions + constexpr auto PF_W{2_u32}; + /// @brief defines p_flags for read permissions + constexpr auto PF_R{4_u32}; + /// @brief defines p_flags for environment-specific use + constexpr auto PF_MASKOS{0x00FF0000_u32}; + /// @brief defines p_flags for environment-specific use + constexpr auto PF_MASKPROC{0xFF000000_u32}; + + /// @struct elf64_phdr_t + /// + /// + /// @brief In executable and shared object files, sections are grouped + /// into segments for loading. The program header table contains a + /// list of entries describing each segment. + /// + struct elf64_phdr_t final + { + /// @brief Type of segment + bsl::uint32 p_type; + /// @brief Segment attributes + bsl::uint32 p_flags; + /// @brief Offset in file + bsl::uint64 p_offset; + /// @brief Virtual address in memory + bsl::uint64 p_vaddr; + /// @brief Reserved + bsl::uint64 p_paddr; + /// @brief Size of segment in file + bsl::uint64 p_filesz; + /// @brief Size of segment in memory + bsl::uint64 p_memsz; + /// @brief Alignment of segment + bsl::uint64 p_align; + }; + + /// + /// @brief Returns a pointer to an ELF program header given an ELF file + /// + /// + /// @param file the ELF file to get the ELF program header from + /// @return returns a pointer to the ELF program header, or nullptr + /// on error + /// + [[nodiscard]] constexpr auto + get_elf64_phdrtab(bsl::span const &file) noexcept + -> bsl::span + { + bsl::discard(file); + return {}; + } +} + +#pragma pack(pop) + +#endif diff --git a/kernel/test/common_platform/dispatch_esr_nmi.hpp b/kernel/test/common_platform/dispatch_esr_nmi.hpp new file mode 100644 index 00000000..c39ea900 --- /dev/null +++ b/kernel/test/common_platform/dispatch_esr_nmi.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TEST_DISPATCH_ESR_NMI_HPP +#define TEST_DISPATCH_ESR_NMI_HPP + +#include +#include + +#include +#include + +namespace mk +{ + /// + /// @brief Provides the main entry point for NMI exceptions + /// + /// + /// @param tls the current TLS block + /// @param intrinsic the intrinsics to use + /// @return Returns bsl::exit_success if the exception was handled, + /// bsl::exit_failure otherwise + /// + [[nodiscard]] constexpr auto + dispatch_esr_nmi(tls_t &tls, intrinsic_t &intrinsic) noexcept -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(intrinsic); + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/test/common_platform/dispatch_esr_page_fault.hpp b/kernel/test/common_platform/dispatch_esr_page_fault.hpp new file mode 100644 index 00000000..7edb52e0 --- /dev/null +++ b/kernel/test/common_platform/dispatch_esr_page_fault.hpp @@ -0,0 +1,55 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TEST_DISPATCH_ESR_PAGE_FAULT_HPP +#define TEST_DISPATCH_ESR_PAGE_FAULT_HPP + +#include +#include + +#include +#include + +namespace mk +{ + /// + /// @brief Provides the ESR handler for page faults + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns bsl::exit_success if the exception was handled, + /// bsl::exit_failure otherwise + /// + [[nodiscard]] constexpr auto + dispatch_esr_page_fault(tls_t &tls, ext_t *const ext) noexcept -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(ext); + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/test/common_platform/dispatch_syscall_callback_op.hpp b/kernel/test/common_platform/dispatch_syscall_callback_op.hpp new file mode 100644 index 00000000..13c3776c --- /dev/null +++ b/kernel/test/common_platform/dispatch_syscall_callback_op.hpp @@ -0,0 +1,56 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TEST_DISPATCH_SYSCALL_CALLBACK_OP_HPP +#define TEST_DISPATCH_SYSCALL_CALLBACK_OP_HPP + +#include +#include +#include + +#include +#include + +namespace mk +{ + /// + /// @brief Dispatches the bf_callback_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + dispatch_syscall_callback_op(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(ext); + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/test/common_platform/dispatch_syscall_control_op.hpp b/kernel/test/common_platform/dispatch_syscall_control_op.hpp new file mode 100644 index 00000000..a3901ec1 --- /dev/null +++ b/kernel/test/common_platform/dispatch_syscall_control_op.hpp @@ -0,0 +1,52 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TEST_DISPATCH_SYSCALL_CONTROL_OP_HPP +#define TEST_DISPATCH_SYSCALL_CONTROL_OP_HPP + +#include +#include + +#include +#include + +namespace mk +{ + /// + /// @brief Dispatches the bf_callback_op syscalls + /// + /// + /// @param tls the current TLS block + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + dispatch_syscall_control_op(tls_t &tls) noexcept -> bsl::errc_type + { + bsl::discard(tls); + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/src/vmexit_loop_trampoline.cpp b/kernel/test/common_platform/dispatch_syscall_debug_op.hpp similarity index 59% rename from kernel/src/vmexit_loop_trampoline.cpp rename to kernel/test/common_platform/dispatch_syscall_debug_op.hpp index d7b1a5d8..30f11732 100644 --- a/kernel/src/vmexit_loop_trampoline.cpp +++ b/kernel/test/common_platform/dispatch_syscall_debug_op.hpp @@ -22,32 +22,43 @@ /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE /// SOFTWARE. -#include -#include -#include +#ifndef TEST_DISPATCH_SYSCALL_DEBUG_OP_HPP +#define TEST_DISPATCH_SYSCALL_DEBUG_OP_HPP -#include +#include +#include +#include +#include +#include + +#include +#include namespace mk { /// - /// @brief Since we cannot create a template function pointer, we need - /// a way to call a template function from our ASM entry point. - /// Normally the way this works in a normal program is the OS calls - /// _start, which then calls main(). The main() function, which is - /// an extern C function, similar to this function, can then call a - /// template function as needed. So the whole point of this function - /// is to simply trampoline from our ASM logic, to a C++ template - /// function that is easy to test. + /// @brief Dispatches the bf_debug_op syscalls /// /// /// @param tls the current TLS block - /// @return Returns bsl::exit_success on success and bsl::exit_failure - /// otherwise + /// @param vm_pool the VM pool to use + /// @param vp_pool the VP pool to use + /// @param vps_pool the VPS pool to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. /// - extern "C" [[nodiscard]] auto - vmexit_loop_trampoline(tls_t *const tls) noexcept -> bsl::exit_code + [[nodiscard]] constexpr auto + dispatch_syscall_debug_op( + tls_t &tls, vm_pool_t &vm_pool, vp_pool_t &vp_pool, vps_pool_t &vps_pool) noexcept + -> bsl::errc_type { - return vmexit_loop(*tls, *static_cast(tls->ext_vmexit), g_vps_pool); + bsl::discard(tls); + bsl::discard(vm_pool); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + return bsl::errc_success; } } + +#endif diff --git a/kernel/test/common_platform/dispatch_syscall_handle_op.hpp b/kernel/test/common_platform/dispatch_syscall_handle_op.hpp new file mode 100644 index 00000000..76386236 --- /dev/null +++ b/kernel/test/common_platform/dispatch_syscall_handle_op.hpp @@ -0,0 +1,56 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TEST_DISPATCH_SYSCALL_HANDLE_OP_HPP +#define TEST_DISPATCH_SYSCALL_HANDLE_OP_HPP + +#include +#include +#include + +#include +#include + +namespace mk +{ + /// + /// @brief Dispatches the bf_handle_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + dispatch_syscall_handle_op(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(ext); + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/test/common_platform/dispatch_syscall_intrinsic_op.hpp b/kernel/test/common_platform/dispatch_syscall_intrinsic_op.hpp new file mode 100644 index 00000000..f302449c --- /dev/null +++ b/kernel/test/common_platform/dispatch_syscall_intrinsic_op.hpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TEST_DISPATCH_SYSCALL_INTRINSIC_OP_HPP +#define TEST_DISPATCH_SYSCALL_INTRINSIC_OP_HPP + +#include +#include +#include +#include + +#include +#include + +namespace mk +{ + /// + /// @brief Dispatches the bf_intrinsic_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @param intrinsic the intrinsics to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + dispatch_syscall_intrinsic_op(tls_t &tls, ext_t const &ext, intrinsic_t &intrinsic) noexcept + -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(ext); + bsl::discard(intrinsic); + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/test/common_platform/dispatch_syscall_mem_op.hpp b/kernel/test/common_platform/dispatch_syscall_mem_op.hpp new file mode 100644 index 00000000..f2e58b33 --- /dev/null +++ b/kernel/test/common_platform/dispatch_syscall_mem_op.hpp @@ -0,0 +1,56 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TEST_DISPATCH_SYSCALL_MEM_OP_HPP +#define TEST_DISPATCH_SYSCALL_MEM_OP_HPP + +#include +#include +#include + +#include +#include + +namespace mk +{ + /// + /// @brief Dispatches the bf_mem_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + dispatch_syscall_mem_op(tls_t &tls, ext_t &ext) noexcept -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(ext); + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/test/common_platform/dispatch_syscall_vm_op.hpp b/kernel/test/common_platform/dispatch_syscall_vm_op.hpp new file mode 100644 index 00000000..f8d60883 --- /dev/null +++ b/kernel/test/common_platform/dispatch_syscall_vm_op.hpp @@ -0,0 +1,61 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TEST_DISPATCH_SYSCALL_VM_OP_HPP +#define TEST_DISPATCH_SYSCALL_VM_OP_HPP + +#include +#include + +#include +#include + +namespace mk +{ + /// + /// @brief Dispatches the bf_vm_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param ext_pool the extension pool to use + /// @param ext the extension that made the syscall + /// @param vm_pool the VM pool to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + dispatch_syscall_vm_op( + tls_t &tls, ext_pool_t &ext_pool, ext_t const &ext, vm_pool_t &vm_pool) noexcept + -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(ext_pool); + bsl::discard(ext); + bsl::discard(vm_pool); + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/test/common_platform/dispatch_syscall_vp_op.hpp b/kernel/test/common_platform/dispatch_syscall_vp_op.hpp new file mode 100644 index 00000000..b413701a --- /dev/null +++ b/kernel/test/common_platform/dispatch_syscall_vp_op.hpp @@ -0,0 +1,58 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef TEST_DISPATCH_SYSCALL_VP_OP_HPP +#define TEST_DISPATCH_SYSCALL_VP_OP_HPP + +#include +#include + +#include +#include + +namespace mk +{ + /// + /// @brief Dispatches the bf_vp_op syscalls + /// + /// + /// @param tls the current TLS block + /// @param ext the extension that made the syscall + /// @param vp_pool the VP pool to use + /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error + /// code on failure. + /// + [[nodiscard]] constexpr auto + dispatch_syscall_vp_op(tls_t &tls, ext_t const &ext, vp_pool_t &vp_pool) noexcept + -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(ext); + bsl::discard(vp_pool); + + return bsl::errc_success; + } +} + +#endif diff --git a/kernel/src/dispatch_syscall_trampoline.cpp b/kernel/test/common_platform/dispatch_syscall_vps_op.hpp similarity index 59% rename from kernel/src/dispatch_syscall_trampoline.cpp rename to kernel/test/common_platform/dispatch_syscall_vps_op.hpp index c236b527..1b318576 100644 --- a/kernel/src/dispatch_syscall_trampoline.cpp +++ b/kernel/test/common_platform/dispatch_syscall_vps_op.hpp @@ -22,35 +22,48 @@ /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE /// SOFTWARE. -#include -#include -#include -#include +#ifndef TEST_DISPATCH_SYSCALL_VPS_OP_HPP +#define TEST_DISPATCH_SYSCALL_VPS_OP_HPP + +#include #include +#include +#include + namespace mk { /// - /// @brief Since we cannot create a template function pointer, we need - /// a way to call a template function from our ASM entry point. - /// Normally the way this works in a normal program is the OS calls - /// _start, which then calls main(). The main() function, which is - /// an extern C function, similar to this function, can then call a - /// template function as needed. So the whole point of this function - /// is to simply trampoline from our ASM logic, to a C++ template - /// function that is easy to test. + /// @brief Dispatches the bf_vps_op syscalls /// /// /// @param tls the current TLS block + /// @param ext_pool the extension pool to use + /// @param ext the extension that made the syscall + /// @param vm_pool the VM pool to use + /// @param vp_pool the VP pool to use + /// @param vps_pool the VPS pool to use /// @return Returns syscall::BF_STATUS_SUCCESS on success or an error /// code on failure. /// - [[nodiscard]] extern "C" auto - dispatch_syscall_trampoline(tls_t *const tls) noexcept -> syscall::bf_status_t::value_type + [[nodiscard]] constexpr auto + dispatch_syscall_vps_op( + tls_t &tls, + ext_pool_t &ext_pool, + ext_t &ext, + vm_pool_t &vm_pool, + vp_pool_t &vp_pool, + vps_pool_t &vps_pool) noexcept -> bsl::errc_type { - auto *const ext{static_cast(tls->ext)}; - return dispatch_syscall( - *tls, *ext, g_intrinsic, g_vm_pool, g_vp_pool, g_vps_pool) - .get(); + bsl::discard(tls); + bsl::discard(ext_pool); + bsl::discard(ext); + bsl::discard(vm_pool); + bsl::discard(vp_pool); + bsl::discard(vps_pool); + + return bsl::errc_success; } } + +#endif diff --git a/kernel/test/common_platform/dummy_errc_types.hpp b/kernel/test/common_platform/dummy_errc_types.hpp new file mode 100644 index 00000000..5b72d50c --- /dev/null +++ b/kernel/test/common_platform/dummy_errc_types.hpp @@ -0,0 +1,84 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DUMMY_ERRC_TYPES_HPP +#define DUMMY_ERRC_TYPES_HPP + +#include +#include + +namespace mk +{ + /// @brief Defines the "fail initialize" case + // We want our implementation to mimic C++ here. + // NOLINTNEXTLINE(bsl-name-case) + constexpr bsl::errc_type errc_fail_initialize{0x00FF0001_i32}; + + /// @brief Defines the "fail initialize and release" case + // We want our implementation to mimic C++ here. + // NOLINTNEXTLINE(bsl-name-case) + constexpr bsl::errc_type errc_fail_initialize_and_release{0x00FF0002_i32}; + + /// @brief Defines the "fail release" case + // We want our implementation to mimic C++ here. + // NOLINTNEXTLINE(bsl-name-case) + constexpr bsl::errc_type errc_fail_release{0x00FF0003_i32}; + + /// @brief Defines the "vm pool failure" case + // We want our implementation to mimic C++ here. + // NOLINTNEXTLINE(bsl-name-case) + constexpr bsl::errc_type errc_vm_pool_failure{0x00FF0004_i32}; + + /// @brief Defines the "vp pool failure" case + // We want our implementation to mimic C++ here. + // NOLINTNEXTLINE(bsl-name-case) + constexpr bsl::errc_type errc_vp_pool_failure{0x00FF0005_i32}; + + /// @brief Defines the "vps pool failure" case + // We want our implementation to mimic C++ here. + // NOLINTNEXTLINE(bsl-name-case) + constexpr bsl::errc_type errc_vps_pool_failure{0x00FF0006_i32}; + + /// @brief Defines the "ext pool failure" case + // We want our implementation to mimic C++ here. + // NOLINTNEXTLINE(bsl-name-case) + constexpr bsl::errc_type errc_ext_pool_failure{0x00FF0007_i32}; + + /// @brief Defines the "vm is deallocated failure" case + // We want our implementation to mimic C++ here. + // NOLINTNEXTLINE(bsl-name-case) + constexpr bsl::errc_type errc_vm_is_deallocated_failure{0x00FF0008_i32}; + + /// @brief Defines the "vm is allocated failure" case + // We want our implementation to mimic C++ here. + // NOLINTNEXTLINE(bsl-name-case) + constexpr bsl::errc_type errc_vm_is_allocated_failure{0x00FF0009_i32}; + + /// @brief Defines the "vm is zombie failure" case + // We want our implementation to mimic C++ here. + // NOLINTNEXTLINE(bsl-name-case) + constexpr bsl::errc_type errc_vm_is_zombie_failure{0x00FF000A_i32}; +} + +#endif diff --git a/kernel/test/common_platform/dummy_ext_pool_t.hpp b/kernel/test/common_platform/dummy_ext_pool_t.hpp new file mode 100644 index 00000000..ca7de6ee --- /dev/null +++ b/kernel/test/common_platform/dummy_ext_pool_t.hpp @@ -0,0 +1,91 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DUMMY_EXT_POOL_T_HPP +#define DUMMY_EXT_POOL_T_HPP + +#include "dummy_errc_types.hpp" + +#include + +#include +#include + +namespace mk +{ + /// @class mk::dummy_ext_pool_t + /// + /// + /// @brief Provides the base ext_pool_t for testing. + /// + class dummy_ext_pool_t final + { + public: + /// + /// @brief Tells each extension that a VM was created so that it + /// can initialize it's VM specific resources. + /// + /// + /// @param tls the current TLS block + /// @param vmid the VMID of the VM that was created. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + signal_vm_created(tls_t &tls, bsl::safe_uint16 const &vmid) noexcept -> bsl::errc_type + { + bsl::discard(vmid); + + if (tls.test_ret == errc_ext_pool_failure) { + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Tells each extension that a VM was destroyed so that it + /// can release it's VM specific resources. + /// + /// + /// @param tls the current TLS block + /// @param vmid the VMID of the VM that was destroyed. + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] static constexpr auto + signal_vm_destroyed(tls_t &tls, bsl::safe_uint16 const &vmid) noexcept -> bsl::errc_type + { + bsl::discard(vmid); + + if (tls.test_ret == errc_ext_pool_failure) { + return bsl::errc_failure; + } + + return bsl::errc_success; + } + }; +} + +#endif diff --git a/kernel/test/common_platform/dummy_lock_t.hpp b/kernel/test/common_platform/dummy_lock_t.hpp new file mode 100644 index 00000000..5b646522 --- /dev/null +++ b/kernel/test/common_platform/dummy_lock_t.hpp @@ -0,0 +1,85 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DUMMYLOCK_T_HPP +#define DUMMYLOCK_T_HPP + +#include + +#include + +namespace mk +{ + /// @class mk::dummy_lock_t + /// + /// + /// @brief A placeholder lock for unit testing + /// + class dummy_lock_t final + { + /// @brief stores the status of the dummy_lock_t + bool m_locked{}; + + public: + /// + /// @brief Locks the dummy_lock_t. + /// + /// + /// @param tls the current TLS block + /// + constexpr void + lock(tls_t const &tls) noexcept + { + bsl::discard(tls); + m_locked = true; + } + + /// + /// @brief Unlocks the dummy_lock_t. + /// + /// + /// @param tls the current TLS block + /// + constexpr void + unlock(tls_t const &tls) noexcept + { + bsl::discard(tls); + m_locked = false; + } + + /// + /// @brief Returns true if the dummy_lock_t is locked + /// + /// + /// @return Returns true if the dummy_lock_t is locked + /// + [[nodiscard]] constexpr auto + is_locked() const noexcept -> bool + { + return m_locked; + } + }; +} + +#endif diff --git a/kernel/test/common_platform/dummy_vm_pool_t.hpp b/kernel/test/common_platform/dummy_vm_pool_t.hpp new file mode 100644 index 00000000..336c3ac8 --- /dev/null +++ b/kernel/test/common_platform/dummy_vm_pool_t.hpp @@ -0,0 +1,104 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DUMMY_VM_POOL_T_HPP +#define DUMMY_VM_POOL_T_HPP + +#include "dummy_errc_types.hpp" + +#include + +#include +#include + +namespace mk +{ + /// @class mk::dummy_vm_pool_t + /// + /// + /// @brief Provides the base vm_pool_t for testing. + /// + class dummy_vm_pool_t final + { + public: + /// + /// @brief Returns true if the requested vm_t is deallocated, false + /// if the provided VMID is invalid, or if the vm_t is not + /// deallocated. + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID of the vm_t to query + /// @return Returns true if the requested vm_t is deallocated, false + /// if the provided VMID is invalid, or if the vm_t is not + /// deallocated. + /// + [[nodiscard]] static constexpr auto + is_deallocated(tls_t &tls, bsl::safe_uint16 const &vmid) noexcept -> bool + { + bsl::discard(vmid); + return tls.test_ret == errc_vm_is_deallocated_failure; + } + + /// + /// @brief Returns true if the requested vm_t is allocated, false + /// if the provided VMID is invalid, or if the vm_t is not + /// allocated. + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID of the vm_t to query + /// @return Returns true if the requested vm_t is allocated, false + /// if the provided VMID is invalid, or if the vm_t is not + /// allocated. + /// + [[nodiscard]] static constexpr auto + is_allocated(tls_t &tls, bsl::safe_uint16 const &vmid) noexcept -> bool + { + bsl::discard(vmid); + return tls.test_ret != errc_vm_is_allocated_failure; + } + + /// + /// @brief Returns true if the requested vm_t is a zombie, false + /// if the provided VMID is invalid, or if the vm_t is not + /// a zombie. + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID of the vm_t to query + /// @return Returns true if the requested vm_t is a zombie, false + /// if the provided VMID is invalid, or if the vm_t is not + /// a zombie. + /// + [[nodiscard]] static constexpr auto + is_zombie(tls_t &tls, bsl::safe_uint16 const &vmid) noexcept -> bool + { + bsl::discard(vmid); + return tls.test_ret == errc_vm_is_zombie_failure; + } + }; +} + +#endif diff --git a/kernel/test/common_platform/dummy_vm_t.hpp b/kernel/test/common_platform/dummy_vm_t.hpp new file mode 100644 index 00000000..21ea622e --- /dev/null +++ b/kernel/test/common_platform/dummy_vm_t.hpp @@ -0,0 +1,274 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VM_T_BASE_HPP +#define VM_T_BASE_HPP + +#include "dummy_errc_types.hpp" + +#include +#include + +#include +#include +#include + +namespace mk +{ + /// @class mk::dummy_vm_t + /// + /// + /// @brief Provides the vm_t for testing. + /// + class dummy_vm_t final + { + /// @brief stores the ID associated with this vm_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + /// @brief stores whether or not this vm_t is allocated. + allocated_status_t m_allocated{allocated_status_t::deallocated}; + /// @brief stores whether or not this vm_t is active. + bool m_active{}; + + public: + /// + /// @brief Initializes this vm_t + /// + /// + /// @param tls the current TLS block + /// @param i the ID for this vm_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize(tls_t &tls, bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + if (tls.test_ret == errc_fail_initialize) { + return bsl::errc_failure; + } + + if (tls.test_ret == errc_fail_initialize_and_release) { + return bsl::errc_failure; + } + + m_id = i; + return bsl::errc_success; + } + + /// + /// @brief Release the vm_t. + /// + /// + /// @param tls the current TLS block + /// @param ext_pool the extension pool to use + /// @param vp_pool the VP pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + release(tls_t &tls, ext_pool_t &ext_pool, vp_pool_t &vp_pool) noexcept -> bsl::errc_type + { + bsl::discard(ext_pool); + bsl::discard(vp_pool); + + if (tls.test_ret == errc_fail_initialize_and_release) { + return bsl::errc_failure; + } + + if (tls.test_ret == errc_fail_release) { + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Allocates this vm_t + /// + /// + /// @param ext_pool the extension pool to use + /// @return Returns ID of the newly allocated vm + /// + [[nodiscard]] constexpr auto + allocate(tls_t &tls, ext_pool_t &ext_pool) noexcept -> bsl::safe_uint16 + { + bsl::discard(ext_pool); + + if (!tls.test_ret) { + return bsl::safe_uint16::failure(); + } + + m_allocated = allocated_status_t::allocated; + return m_id; + } + + /// + /// @brief Deallocates this vm_t + /// + /// + /// @param tls the current TLS block + /// @param ext_pool the extension pool to use + /// @param vp_pool the VP pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + deallocate(tls_t &tls, ext_pool_t &ext_pool, vp_pool_t &vp_pool) noexcept -> bsl::errc_type + { + bsl::discard(ext_pool); + bsl::discard(vp_pool); + + m_allocated = allocated_status_t::deallocated; + return tls.test_ret; + } + + /// + /// @brief Sets this vm_t's status as zombified, meaning it is no + /// longer usable. + /// + constexpr void + zombify() noexcept + { + m_allocated = allocated_status_t::zombie; + } + + /// + /// @brief Returns true if this vm_t is deallocated, false otherwise + /// + /// + /// @return Returns true if this vm_t is deallocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_deallocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::deallocated; + } + + /// + /// @brief Returns true if this vm_t is allocated, false otherwise + /// + /// + /// @return Returns true if this vm_t is allocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_allocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::allocated; + } + + /// + /// @brief Returns true if this vm_t is a zombie, false otherwise + /// + /// + /// @return Returns true if this vm_t is a zombie, false otherwise + /// + [[nodiscard]] constexpr auto + is_zombie() const noexcept -> bool + { + return m_allocated == allocated_status_t::zombie; + } + + /// + /// @brief Sets this vm_t as active. + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_active(tls_t &tls) noexcept -> bsl::errc_type + { + m_active = true; + return tls.test_ret; + } + + /// + /// @brief Sets this vm_t as inactive. + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_inactive(tls_t &tls) noexcept -> bsl::errc_type + { + m_active = {}; + return tls.test_ret; + } + + /// + /// @brief Returns the ID of the first PP identified that this VM + /// is still active on. If the VM is inactive, this function + /// returns bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @return Returns the ID of the first PP identified that this VM + /// is still active on. If the VM is inactive, this function + /// returns bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_active(tls_t &tls) const noexcept -> bsl::safe_uint16 + { + bsl::discard(tls); + + if (m_active) { + return {}; + } + + return bsl::safe_uint16::failure(); + } + + /// + /// @brief Returns true if this vm_t is active on the current PP, + /// false otherwise + /// + /// + /// @param tls the current TLS block + /// @return Returns true if this vm_t is active on the current PP, + /// false otherwise + /// + [[nodiscard]] constexpr auto + is_active_on_current_pp(tls_t &tls) const noexcept -> bool + { + bsl::discard(tls); + return m_active; + } + + // + /// @brief Dumps the vm_t + /// + /// + /// @param tls the current TLS block + /// + constexpr void + dump(tls_t &tls) const noexcept + { + bsl::discard(tls); + } + }; +} + +#endif diff --git a/kernel/test/common_platform/dummy_vp_pool_t.hpp b/kernel/test/common_platform/dummy_vp_pool_t.hpp new file mode 100644 index 00000000..55a237fe --- /dev/null +++ b/kernel/test/common_platform/dummy_vp_pool_t.hpp @@ -0,0 +1,70 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DUMMY_VP_POOL_T_HPP +#define DUMMY_VP_POOL_T_HPP + +#include "dummy_errc_types.hpp" + +#include + +#include +#include + +namespace mk +{ + /// @class mk::dummy_vp_pool_t + /// + /// + /// @brief Provides the base vp_pool_t for testing. + /// + class dummy_vp_pool_t final + { + public: + /// + /// @brief If a vp_t in the pool is assigned to the requested VM, + /// the ID of the first vp_t found is returned. Otherwise, this + /// function will return bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @param vmid the ID fo the VM to query + /// @return If a vp_t in the pool is assigned to the requested VM, + /// the ID of the first vp_t found is returned. Otherwise, this + /// function will return bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_assigned_to_vm(tls_t &tls, bsl::safe_uint16 const &vmid) const noexcept + -> bsl::safe_uint16 + { + if (tls.test_ret == errc_vp_pool_failure) { + return vmid; + } + + return bsl::safe_uint16::failure(); + } + }; +} + +#endif diff --git a/kernel/test/common_platform/dummy_vp_t.hpp b/kernel/test/common_platform/dummy_vp_t.hpp new file mode 100644 index 00000000..f71f931e --- /dev/null +++ b/kernel/test/common_platform/dummy_vp_t.hpp @@ -0,0 +1,360 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef VP_T_BASE_HPP +#define VP_T_BASE_HPP + +#include "dummy_errc_types.hpp" + +#include +#include + +#include +#include +#include + +namespace mk +{ + /// @class mk::dummy_vp_t + /// + /// + /// @brief Provides the vp_t for testing. + /// + class dummy_vp_t final + { + /// @brief stores the ID associated with this vp_t + bsl::safe_uint16 m_id{bsl::safe_uint16::failure()}; + /// @brief stores whether or not this vp_t is allocated. + allocated_status_t m_allocated{allocated_status_t::deallocated}; + /// @brief stores the ID of the VM this vp_t is assigned to + bsl::safe_uint16 m_assigned_vmid{syscall::BF_INVALID_ID}; + /// @brief stores the ID of the PP this vp_t is assigned to + bsl::safe_uint16 m_assigned_ppid{syscall::BF_INVALID_ID}; + /// @brief stores whether or not this vp_t is active. + bool m_active{}; + + public: + /// + /// @brief Initializes this vp_t + /// + /// + /// @param tls the current TLS block + /// @param i the ID for this vp_t + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize(tls_t &tls, bsl::safe_uint16 const &i) noexcept -> bsl::errc_type + { + if (tls.test_ret == errc_fail_initialize) { + return bsl::errc_failure; + } + + if (tls.test_ret == errc_fail_initialize_and_release) { + return bsl::errc_failure; + } + + m_id = i; + return bsl::errc_success; + } + + /// + /// @brief Release the vp_t. + /// + /// + /// @param tls the current TLS block + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + release(tls_t &tls, vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(vps_pool); + + if (tls.test_ret == errc_fail_initialize_and_release) { + return bsl::errc_failure; + } + + if (tls.test_ret == errc_fail_release) { + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Returns the ID of this vp_t + /// + /// + /// @return Returns the ID of this vp_t + /// + [[nodiscard]] constexpr auto + id() const noexcept -> bsl::safe_uint16 const & + { + return m_id; + } + + /// + /// @brief Allocates this vp_t + /// + /// + /// @param tls the current TLS block + /// @param vm_pool the VM pool to use + /// @param vmid The ID of the VM to assign the newly created VP to + /// @param ppid The ID of the PP to assign the newly created VP to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + allocate( + tls_t &tls, + vm_pool_t &vm_pool, + bsl::safe_uint16 const &vmid, + bsl::safe_uint16 const &ppid) noexcept -> bsl::safe_uint16 + { + bsl::discard(vm_pool); + + if (!tls.test_ret) { + return bsl::safe_uint16::failure(); + } + + m_assigned_vmid = vmid; + m_assigned_ppid = ppid; + m_allocated = allocated_status_t::allocated; + + return m_id; + } + + /// + /// @brief Deallocates this vp_t + /// + /// + /// @param tls the current TLS block + /// @param vps_pool the VPS pool to use + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + deallocate(tls_t &tls, vps_pool_t &vps_pool) noexcept -> bsl::errc_type + { + bsl::discard(vps_pool); + + m_assigned_ppid = syscall::BF_INVALID_ID; + m_assigned_vmid = syscall::BF_INVALID_ID; + m_allocated = allocated_status_t::deallocated; + + return tls.test_ret; + } + + /// + /// @brief Sets this vp_t's status as zombified, meaning it is no + /// longer usable. + /// + constexpr void + zombify() noexcept + { + m_allocated = allocated_status_t::zombie; + } + + /// + /// @brief Returns true if this vp_t is deallocated, false otherwise + /// + /// + /// @return Returns true if this vp_t is deallocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_deallocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::deallocated; + } + + /// + /// @brief Returns true if this vp_t is allocated, false otherwise + /// + /// + /// @return Returns true if this vp_t is allocated, false otherwise + /// + [[nodiscard]] constexpr auto + is_allocated() const noexcept -> bool + { + return m_allocated == allocated_status_t::allocated; + } + + /// + /// @brief Returns true if this vp_t is a zombie, false otherwise + /// + /// + /// @return Returns true if this vp_t is a zombie, false otherwise + /// + [[nodiscard]] constexpr auto + is_zombie() const noexcept -> bool + { + return m_allocated == allocated_status_t::zombie; + } + + /// + /// @brief Sets this vp_t as active. + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_active(tls_t &tls) noexcept -> bsl::errc_type + { + m_active = true; + return tls.test_ret; + } + + /// + /// @brief Sets this vp_t as inactive. + /// + /// + /// @param tls the current TLS block + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + set_inactive(tls_t &tls) noexcept -> bsl::errc_type + { + m_active = {}; + return tls.test_ret; + } + + /// + /// @brief Returns the ID of the first PP identified that this VP + /// is still active on. If the VP is inactive, this function + /// returns bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @return Returns the ID of the first PP identified that this VP + /// is still active on. If the VP is inactive, this function + /// returns bsl::safe_uint16::failure() + /// + [[nodiscard]] constexpr auto + is_active(tls_t &tls) const noexcept -> bsl::safe_uint16 + { + bsl::discard(tls); + + if (m_active) { + return {}; + } + + return bsl::safe_uint16::failure(); + } + + /// + /// @brief Returns true if this vp_t is active on the current PP, + /// false otherwise + /// + /// + /// @param tls the current TLS block + /// @return Returns true if this vp_t is active on the current PP, + /// false otherwise + /// + [[nodiscard]] constexpr auto + is_active_on_current_pp(tls_t &tls) const noexcept -> bool + { + bsl::discard(tls); + return m_active; + } + + /// + /// @brief Migrates this vp_t from one PP to another. If this calls + /// completes successfully, the VPS's assigned PP will not + /// match the VP's assigned PP. Future calls to the run ABI + /// will be able to detect this an migrate mismatched VPSs to + /// the proper PP as needed. Note that since the VP doesn't control + /// any hardware state, all we have to do here is set which PP + /// this VP is allowed to execute on. The VPS is what actually + /// needs to be migrated, and that will not happen until a call + /// to the run ABIs made. Once the run ABI detects a mismatch with + /// the VPS and it's assigned VP, it will be migrated then. + /// + /// + /// @param tls the current TLS block + /// @param ppid the ID of the PP to migrate to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + migrate(tls_t &tls, bsl::safe_uint16 const &ppid) noexcept -> bsl::errc_type + { + bsl::discard(tls); + bsl::discard(ppid); + + m_assigned_ppid = ppid; + return tls.test_ret; + } + + /// + /// @brief Returns the ID of the VM this vp_t is assigned to + /// + /// + /// @return Returns the ID of the VM this vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_vm() const noexcept -> bsl::safe_uint16 + { + if (bsl::unlikely(syscall::BF_INVALID_ID == m_assigned_vmid)) { + return bsl::safe_uint16::failure(); + } + + return m_assigned_vmid; + } + + /// + /// @brief Returns the ID of the PP this vp_t is assigned to + /// + /// + /// @return Returns the ID of the PP this vp_t is assigned to + /// + [[nodiscard]] constexpr auto + assigned_pp() const noexcept -> bsl::safe_uint16 + { + if (bsl::unlikely(syscall::BF_INVALID_ID == m_assigned_ppid)) { + return bsl::safe_uint16::failure(); + } + + return m_assigned_ppid; + } + + // + /// @brief Dumps the vp_t + /// + /// + /// @param tls the current TLS block + /// + constexpr void + dump(tls_t &tls) const noexcept + { + bsl::discard(tls); + } + }; +} + +#endif diff --git a/kernel/test/common_platform/dummy_vps_pool_t.hpp b/kernel/test/common_platform/dummy_vps_pool_t.hpp new file mode 100644 index 00000000..466d1ef1 --- /dev/null +++ b/kernel/test/common_platform/dummy_vps_pool_t.hpp @@ -0,0 +1,69 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef DUMMY_VPS_POOL_T_HPP +#define DUMMY_VPS_POOL_T_HPP + +#include "dummy_errc_types.hpp" + +#include + +#include +#include + +namespace mk +{ + /// @class mk::dummy_vps_pool_t + /// + /// + /// @brief Provides the base vps_pool_t for testing. + /// + class dummy_vps_pool_t final + { + public: + /// + /// @brief If a vps_t is assigned to the requested VP, the ID of + /// the vps_t is returned. Otherwise, this function will return + /// bsl::safe_uint16::failure() + /// + /// + /// @param tls the current TLS block + /// @param vpid the ID fo the VP to query + /// @return If a vps_t is assigned to the requested VP, the ID of + /// the vps_t is returned. Otherwise, this function will return + /// bsl::safe_uint16::failure() + /// + [[nodiscard]] static constexpr auto + is_assigned_to_vp(tls_t &tls, bsl::safe_uint16 const &vpid) noexcept -> bsl::safe_uint16 + { + if (tls.test_ret == errc_vps_pool_failure) { + return vpid; + } + + return bsl::safe_uint16::failure(); + } + }; +} + +#endif diff --git a/kernel/test/cstdio/CMakeLists.txt b/kernel/test/cstdio/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/cstdio/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/cstdio/behavior.cpp b/kernel/test/cstdio/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/kernel/test/cstdio/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/cstdio/requirements.cpp b/kernel/test/cstdio/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/kernel/test/cstdio/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/debug_ring_write/CMakeLists.txt b/kernel/test/debug_ring_write/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/debug_ring_write/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/debug_ring_write/behavior.cpp b/kernel/test/debug_ring_write/behavior.cpp new file mode 100644 index 00000000..667306da --- /dev/null +++ b/kernel/test/debug_ring_write/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/debug_ring_write.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/debug_ring_write/requirements.cpp b/kernel/test/debug_ring_write/requirements.cpp new file mode 100644 index 00000000..c3e0064a --- /dev/null +++ b/kernel/test/debug_ring_write/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/debug_ring_write.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/details/print_thread_id/CMakeLists.txt b/kernel/test/details/print_thread_id/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/details/print_thread_id/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/details/print_thread_id/behavior.cpp b/kernel/test/details/print_thread_id/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/kernel/test/details/print_thread_id/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/details/print_thread_id/requirements.cpp b/kernel/test/details/print_thread_id/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/kernel/test/details/print_thread_id/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/details/putc_stderr/CMakeLists.txt b/kernel/test/details/putc_stderr/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/details/putc_stderr/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/details/putc_stderr/behavior.cpp b/kernel/test/details/putc_stderr/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/kernel/test/details/putc_stderr/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/details/putc_stderr/requirements.cpp b/kernel/test/details/putc_stderr/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/kernel/test/details/putc_stderr/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/details/putc_stdout/CMakeLists.txt b/kernel/test/details/putc_stdout/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/details/putc_stdout/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/details/putc_stdout/behavior.cpp b/kernel/test/details/putc_stdout/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/kernel/test/details/putc_stdout/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/details/putc_stdout/requirements.cpp b/kernel/test/details/putc_stdout/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/kernel/test/details/putc_stdout/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/details/puts_stderr/CMakeLists.txt b/kernel/test/details/puts_stderr/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/details/puts_stderr/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/details/puts_stderr/behavior.cpp b/kernel/test/details/puts_stderr/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/kernel/test/details/puts_stderr/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/details/puts_stderr/requirements.cpp b/kernel/test/details/puts_stderr/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/kernel/test/details/puts_stderr/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/details/puts_stdout/CMakeLists.txt b/kernel/test/details/puts_stdout/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/details/puts_stdout/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/details/puts_stdout/behavior.cpp b/kernel/test/details/puts_stdout/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/kernel/test/details/puts_stdout/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/details/puts_stdout/requirements.cpp b/kernel/test/details/puts_stdout/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/kernel/test/details/puts_stdout/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_esr_page_fault/CMakeLists.txt b/kernel/test/dispatch_esr_page_fault/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_esr_page_fault/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_esr_page_fault/behavior.cpp b/kernel/test/dispatch_esr_page_fault/behavior.cpp new file mode 100644 index 00000000..51b58d95 --- /dev/null +++ b/kernel/test/dispatch_esr_page_fault/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_esr_page_fault.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_esr_page_fault/requirements.cpp b/kernel/test/dispatch_esr_page_fault/requirements.cpp new file mode 100644 index 00000000..7c4d55a1 --- /dev/null +++ b/kernel/test/dispatch_esr_page_fault/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_esr_page_fault.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall/CMakeLists.txt b/kernel/test/dispatch_syscall/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall/behavior.cpp b/kernel/test/dispatch_syscall/behavior.cpp new file mode 100644 index 00000000..1dd58366 --- /dev/null +++ b/kernel/test/dispatch_syscall/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall/requirements.cpp b/kernel/test/dispatch_syscall/requirements.cpp new file mode 100644 index 00000000..5c816464 --- /dev/null +++ b/kernel/test/dispatch_syscall/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_callback_op/CMakeLists.txt b/kernel/test/dispatch_syscall_callback_op/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_callback_op/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_callback_op/behavior.cpp b/kernel/test/dispatch_syscall_callback_op/behavior.cpp new file mode 100644 index 00000000..daae1f0c --- /dev/null +++ b/kernel/test/dispatch_syscall_callback_op/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_callback_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_callback_op/requirements.cpp b/kernel/test/dispatch_syscall_callback_op/requirements.cpp new file mode 100644 index 00000000..97608ba9 --- /dev/null +++ b/kernel/test/dispatch_syscall_callback_op/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_callback_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_callback_op_failure/CMakeLists.txt b/kernel/test/dispatch_syscall_callback_op_failure/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_callback_op_failure/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_callback_op_failure/behavior.cpp b/kernel/test/dispatch_syscall_callback_op_failure/behavior.cpp new file mode 100644 index 00000000..a157acdb --- /dev/null +++ b/kernel/test/dispatch_syscall_callback_op_failure/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_callback_op_failure.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_callback_op_failure/requirements.cpp b/kernel/test/dispatch_syscall_callback_op_failure/requirements.cpp new file mode 100644 index 00000000..0afee8db --- /dev/null +++ b/kernel/test/dispatch_syscall_callback_op_failure/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_callback_op_failure.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_control_op/CMakeLists.txt b/kernel/test/dispatch_syscall_control_op/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_control_op/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_control_op/behavior.cpp b/kernel/test/dispatch_syscall_control_op/behavior.cpp new file mode 100644 index 00000000..056e3d1f --- /dev/null +++ b/kernel/test/dispatch_syscall_control_op/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_control_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_control_op/requirements.cpp b/kernel/test/dispatch_syscall_control_op/requirements.cpp new file mode 100644 index 00000000..18cfb5ca --- /dev/null +++ b/kernel/test/dispatch_syscall_control_op/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_control_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_control_op_failure/CMakeLists.txt b/kernel/test/dispatch_syscall_control_op_failure/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_control_op_failure/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_control_op_failure/behavior.cpp b/kernel/test/dispatch_syscall_control_op_failure/behavior.cpp new file mode 100644 index 00000000..056e3d1f --- /dev/null +++ b/kernel/test/dispatch_syscall_control_op_failure/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_control_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_control_op_failure/requirements.cpp b/kernel/test/dispatch_syscall_control_op_failure/requirements.cpp new file mode 100644 index 00000000..18cfb5ca --- /dev/null +++ b/kernel/test/dispatch_syscall_control_op_failure/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_control_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_debug_op/CMakeLists.txt b/kernel/test/dispatch_syscall_debug_op/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_debug_op/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_debug_op/behavior.cpp b/kernel/test/dispatch_syscall_debug_op/behavior.cpp new file mode 100644 index 00000000..01281288 --- /dev/null +++ b/kernel/test/dispatch_syscall_debug_op/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_debug_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_debug_op/requirements.cpp b/kernel/test/dispatch_syscall_debug_op/requirements.cpp new file mode 100644 index 00000000..d562621f --- /dev/null +++ b/kernel/test/dispatch_syscall_debug_op/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_debug_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_debug_op_failure/CMakeLists.txt b/kernel/test/dispatch_syscall_debug_op_failure/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_debug_op_failure/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_debug_op_failure/behavior.cpp b/kernel/test/dispatch_syscall_debug_op_failure/behavior.cpp new file mode 100644 index 00000000..01281288 --- /dev/null +++ b/kernel/test/dispatch_syscall_debug_op_failure/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_debug_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_debug_op_failure/requirements.cpp b/kernel/test/dispatch_syscall_debug_op_failure/requirements.cpp new file mode 100644 index 00000000..d562621f --- /dev/null +++ b/kernel/test/dispatch_syscall_debug_op_failure/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_debug_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_failure/CMakeLists.txt b/kernel/test/dispatch_syscall_failure/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_failure/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_failure/behavior.cpp b/kernel/test/dispatch_syscall_failure/behavior.cpp new file mode 100644 index 00000000..1dd58366 --- /dev/null +++ b/kernel/test/dispatch_syscall_failure/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_failure/requirements.cpp b/kernel/test/dispatch_syscall_failure/requirements.cpp new file mode 100644 index 00000000..5c816464 --- /dev/null +++ b/kernel/test/dispatch_syscall_failure/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_handle_op/CMakeLists.txt b/kernel/test/dispatch_syscall_handle_op/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_handle_op/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_handle_op/behavior.cpp b/kernel/test/dispatch_syscall_handle_op/behavior.cpp new file mode 100644 index 00000000..c9ccb94d --- /dev/null +++ b/kernel/test/dispatch_syscall_handle_op/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_handle_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_handle_op/requirements.cpp b/kernel/test/dispatch_syscall_handle_op/requirements.cpp new file mode 100644 index 00000000..3f26a7e6 --- /dev/null +++ b/kernel/test/dispatch_syscall_handle_op/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_handle_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_handle_op_failure/CMakeLists.txt b/kernel/test/dispatch_syscall_handle_op_failure/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_handle_op_failure/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_handle_op_failure/behavior.cpp b/kernel/test/dispatch_syscall_handle_op_failure/behavior.cpp new file mode 100644 index 00000000..c9ccb94d --- /dev/null +++ b/kernel/test/dispatch_syscall_handle_op_failure/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_handle_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_handle_op_failure/requirements.cpp b/kernel/test/dispatch_syscall_handle_op_failure/requirements.cpp new file mode 100644 index 00000000..3f26a7e6 --- /dev/null +++ b/kernel/test/dispatch_syscall_handle_op_failure/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_handle_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_mem_op/CMakeLists.txt b/kernel/test/dispatch_syscall_mem_op/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_mem_op/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_mem_op/behavior.cpp b/kernel/test/dispatch_syscall_mem_op/behavior.cpp new file mode 100644 index 00000000..d3a3aa1f --- /dev/null +++ b/kernel/test/dispatch_syscall_mem_op/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_mem_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_mem_op/requirements.cpp b/kernel/test/dispatch_syscall_mem_op/requirements.cpp new file mode 100644 index 00000000..8cc822f4 --- /dev/null +++ b/kernel/test/dispatch_syscall_mem_op/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_mem_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_mem_op_failure/CMakeLists.txt b/kernel/test/dispatch_syscall_mem_op_failure/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_mem_op_failure/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_mem_op_failure/behavior.cpp b/kernel/test/dispatch_syscall_mem_op_failure/behavior.cpp new file mode 100644 index 00000000..d3a3aa1f --- /dev/null +++ b/kernel/test/dispatch_syscall_mem_op_failure/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_mem_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_mem_op_failure/requirements.cpp b/kernel/test/dispatch_syscall_mem_op_failure/requirements.cpp new file mode 100644 index 00000000..8cc822f4 --- /dev/null +++ b/kernel/test/dispatch_syscall_mem_op_failure/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_mem_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_vm_op/CMakeLists.txt b/kernel/test/dispatch_syscall_vm_op/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_vm_op/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_vm_op/behavior.cpp b/kernel/test/dispatch_syscall_vm_op/behavior.cpp new file mode 100644 index 00000000..fe5fe7a6 --- /dev/null +++ b/kernel/test/dispatch_syscall_vm_op/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vm_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_vm_op/requirements.cpp b/kernel/test/dispatch_syscall_vm_op/requirements.cpp new file mode 100644 index 00000000..fc6a3be2 --- /dev/null +++ b/kernel/test/dispatch_syscall_vm_op/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vm_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_vm_op_failure/CMakeLists.txt b/kernel/test/dispatch_syscall_vm_op_failure/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_vm_op_failure/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_vm_op_failure/behavior.cpp b/kernel/test/dispatch_syscall_vm_op_failure/behavior.cpp new file mode 100644 index 00000000..fe5fe7a6 --- /dev/null +++ b/kernel/test/dispatch_syscall_vm_op_failure/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vm_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_vm_op_failure/requirements.cpp b/kernel/test/dispatch_syscall_vm_op_failure/requirements.cpp new file mode 100644 index 00000000..fc6a3be2 --- /dev/null +++ b/kernel/test/dispatch_syscall_vm_op_failure/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vm_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_vp_op/CMakeLists.txt b/kernel/test/dispatch_syscall_vp_op/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_vp_op/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_vp_op/behavior.cpp b/kernel/test/dispatch_syscall_vp_op/behavior.cpp new file mode 100644 index 00000000..4b6791fe --- /dev/null +++ b/kernel/test/dispatch_syscall_vp_op/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vp_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_vp_op/requirements.cpp b/kernel/test/dispatch_syscall_vp_op/requirements.cpp new file mode 100644 index 00000000..e1bd00eb --- /dev/null +++ b/kernel/test/dispatch_syscall_vp_op/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vp_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_vp_op_failure/CMakeLists.txt b/kernel/test/dispatch_syscall_vp_op_failure/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_vp_op_failure/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_vp_op_failure/behavior.cpp b/kernel/test/dispatch_syscall_vp_op_failure/behavior.cpp new file mode 100644 index 00000000..4b6791fe --- /dev/null +++ b/kernel/test/dispatch_syscall_vp_op_failure/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vp_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_vp_op_failure/requirements.cpp b/kernel/test/dispatch_syscall_vp_op_failure/requirements.cpp new file mode 100644 index 00000000..e1bd00eb --- /dev/null +++ b/kernel/test/dispatch_syscall_vp_op_failure/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vp_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_vps_op/CMakeLists.txt b/kernel/test/dispatch_syscall_vps_op/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_vps_op/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_vps_op/behavior.cpp b/kernel/test/dispatch_syscall_vps_op/behavior.cpp new file mode 100644 index 00000000..e49442de --- /dev/null +++ b/kernel/test/dispatch_syscall_vps_op/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vps_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_vps_op/requirements.cpp b/kernel/test/dispatch_syscall_vps_op/requirements.cpp new file mode 100644 index 00000000..d6cc7805 --- /dev/null +++ b/kernel/test/dispatch_syscall_vps_op/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vps_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/dispatch_syscall_vps_op_failure/CMakeLists.txt b/kernel/test/dispatch_syscall_vps_op_failure/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/dispatch_syscall_vps_op_failure/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/dispatch_syscall_vps_op_failure/behavior.cpp b/kernel/test/dispatch_syscall_vps_op_failure/behavior.cpp new file mode 100644 index 00000000..e49442de --- /dev/null +++ b/kernel/test/dispatch_syscall_vps_op_failure/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vps_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/dispatch_syscall_vps_op_failure/requirements.cpp b/kernel/test/dispatch_syscall_vps_op_failure/requirements.cpp new file mode 100644 index 00000000..d6cc7805 --- /dev/null +++ b/kernel/test/dispatch_syscall_vps_op_failure/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/dispatch_syscall_vps_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/ext_pool_t/CMakeLists.txt b/kernel/test/ext_pool_t/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/ext_pool_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/ext_pool_t/behavior.cpp b/kernel/test/ext_pool_t/behavior.cpp new file mode 100644 index 00000000..80dfbf8f --- /dev/null +++ b/kernel/test/ext_pool_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/ext_pool_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/ext_pool_t/requirements.cpp b/kernel/test/ext_pool_t/requirements.cpp new file mode 100644 index 00000000..3d8395fa --- /dev/null +++ b/kernel/test/ext_pool_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/ext_pool_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/ext_t/CMakeLists.txt b/kernel/test/ext_t/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/ext_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/ext_t/behavior.cpp b/kernel/test/ext_t/behavior.cpp new file mode 100644 index 00000000..8632f491 --- /dev/null +++ b/kernel/test/ext_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/ext_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/ext_t/requirements.cpp b/kernel/test/ext_t/requirements.cpp new file mode 100644 index 00000000..a1f1f30c --- /dev/null +++ b/kernel/test/ext_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/ext_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/fast_fail/CMakeLists.txt b/kernel/test/fast_fail/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/fast_fail/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/fast_fail/behavior.cpp b/kernel/test/fast_fail/behavior.cpp new file mode 100644 index 00000000..3044117a --- /dev/null +++ b/kernel/test/fast_fail/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/fast_fail.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/fast_fail/requirements.cpp b/kernel/test/fast_fail/requirements.cpp new file mode 100644 index 00000000..a3548ae0 --- /dev/null +++ b/kernel/test/fast_fail/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/fast_fail.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/huge_pool_t/CMakeLists.txt b/kernel/test/huge_pool_t/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/huge_pool_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/huge_pool_t/behavior.cpp b/kernel/test/huge_pool_t/behavior.cpp new file mode 100644 index 00000000..3f7bd2d5 --- /dev/null +++ b/kernel/test/huge_pool_t/behavior.cpp @@ -0,0 +1,205 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/huge_pool_t.hpp" + +#include + +namespace mk +{ + /// @brief used by most of the tests + constexpr auto POOL_SIZE{0x3000_umax}; + /// @brief only used by the dump test as this is too large for the stack + constexpr auto LARGE_POOL_SIZE{0x1000000_umax}; + + /// @brief used for dump to prevent the unit test from running out of stack + bsl::array g_pool{}; + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"allocate invalid size"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + huge_pool_t huge_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + huge_pool.initialize(view); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!huge_pool.allocate(tls, bsl::safe_uintmax::failure())); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate 4k pages"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + huge_pool_t huge_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + huge_pool.initialize(view); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(huge_pool.allocate(tls, 0x1000_umax).size() == 0x1000_umax); + bsl::ut_check(huge_pool.allocate(tls, 0x1000_umax).size() == 0x1000_umax); + bsl::ut_check(huge_pool.allocate(tls, 0x1000_umax).size() == 0x1000_umax); + bsl::ut_check(!huge_pool.allocate(tls, 0x1000_umax)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate 8k pages"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + huge_pool_t huge_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + huge_pool.initialize(view); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(huge_pool.allocate(tls, 0x2000_umax).size() == 0x2000_umax); + bsl::ut_check(!huge_pool.allocate(tls, 0x2000_umax)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate non page sizes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + huge_pool_t huge_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + huge_pool.initialize(view); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(huge_pool.allocate(tls, 0xFFF_umax).size() == 0x1000_umax); + bsl::ut_check(huge_pool.allocate(tls, 0x001_umax).size() == 0x1000_umax); + bsl::ut_check(huge_pool.allocate(tls, 0x800_umax).size() == 0x1000_umax); + bsl::ut_check(!huge_pool.allocate(tls, 0x001_umax)); + }; + }; + }; + }; + + bsl::ut_scenario{"quiet deallocate"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + huge_pool_t huge_pool{}; + tls_t tls{}; + huge_pool.deallocate(tls, {}); + }; + }; + + bsl::ut_scenario{"virt_to_phys"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + huge_pool_t huge_pool{}; + bool b{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!huge_pool.virt_to_phys(nullptr)); + bsl::ut_check( + huge_pool.virt_to_phys(&b) == + bsl::to_umax(&b) - HYPERVISOR_MK_PAGE_POOL_ADDR); + }; + }; + }; + + bsl::ut_scenario{"phys_to_virt"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + huge_pool_t huge_pool{}; + bool b{}; + constexpr auto bad_phys{0xFFFFFFFFFFFFFFFF_umax}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(nullptr == huge_pool.phys_to_virt(bad_phys)); + bsl::ut_check( + huge_pool.phys_to_virt( + bsl::to_umax(&b) - HYPERVISOR_MK_PAGE_POOL_ADDR) == &b); + }; + }; + }; + + bsl::ut_scenario{"dump"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + huge_pool_t huge_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + huge_pool.initialize(view); + bsl::ut_required_step(!!huge_pool.allocate(tls, 0x1000_umax)); + bsl::ut_required_step(!!huge_pool.allocate(tls, 0x1000_umax)); + bsl::ut_required_step(!!huge_pool.allocate(tls, 0x1000_umax)); + bsl::ut_then{} = [&]() noexcept { + huge_pool.dump(); + }; + }; + }; + + bsl::ut_given_at_runtime{} = []() noexcept { + huge_pool_t huge_pool{}; + bsl::span view{g_pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + huge_pool.initialize(view); + for (bsl::safe_uintmax i{}; i < 1024_umax; ++i) { + bsl::ut_required_step(!!huge_pool.allocate(tls, 0x1000_umax)); + } + bsl::ut_then{} = [&]() noexcept { + huge_pool.dump(); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/huge_pool_t/requirements.cpp b/kernel/test/huge_pool_t/requirements.cpp new file mode 100644 index 00000000..8692944a --- /dev/null +++ b/kernel/test/huge_pool_t/requirements.cpp @@ -0,0 +1,121 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/huge_pool_t.hpp" + +#include +#include +#include + +namespace +{ + constinit mk::huge_pool_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + mk::huge_pool_t m_pool{}; + + public: + [[nodiscard]] constexpr auto + test_member_const() const noexcept -> bool + { + bool b{}; + + bsl::discard(m_pool.virt_to_phys(&b)); + bsl::discard(m_pool.phys_to_virt({})); + m_pool.dump(); + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + bsl::span view{}; + mk::tls_t tls{}; + bool b{}; + + bsl::discard(mk::huge_pool_t{}); + m_pool.initialize(view); + bsl::discard(m_pool.allocate(tls, {})); + m_pool.deallocate(tls, {}); + bsl::discard(m_pool.virt_to_phys(&b)); + bsl::discard(m_pool.phys_to_virt({})); + m_pool.dump(); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit/constexpr"} = []() noexcept { + bsl::discard(g_verify_constinit); + bsl::discard(FIXTURE1); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + mk::huge_pool_t pool{}; + bsl::span view{}; + mk::tls_t tls{}; + bool b{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(mk::huge_pool_t{})); + static_assert(noexcept(pool.initialize(view))); + static_assert(noexcept(pool.allocate(tls, {}))); + static_assert(noexcept(pool.deallocate(tls, {}))); + static_assert(noexcept(pool.virt_to_phys(&b))); + static_assert(noexcept(pool.phys_to_virt({}))); + static_assert(noexcept(pool.dump())); + }; + }; + }; + + bsl::ut_scenario{"verify constness without using constexpr"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + fixture_t const fixture3{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(fixture3.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/kernel/test/lock_guard_t/CMakeLists.txt b/kernel/test/lock_guard_t/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/lock_guard_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/lock_guard_t/behavior.cpp b/kernel/test/lock_guard_t/behavior.cpp new file mode 100644 index 00000000..7e72cfaa --- /dev/null +++ b/kernel/test/lock_guard_t/behavior.cpp @@ -0,0 +1,80 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/lock_guard_t.hpp" + +#include +#include + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"lock/unlock"} = []() { + bsl::ut_given{} = []() { + tls_t tls{}; + dummy_lock_t dummy_lock{}; + bsl::ut_then{} = [&tls, &dummy_lock]() { + { + bsl::ut_check(!dummy_lock.is_locked()); + lock_guard_t lock{tls, dummy_lock}; + bsl::ut_check(dummy_lock.is_locked()); + } + bsl::ut_check(!dummy_lock.is_locked()); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/lock_guard_t/requirements.cpp b/kernel/test/lock_guard_t/requirements.cpp new file mode 100644 index 00000000..8b5bdaae --- /dev/null +++ b/kernel/test/lock_guard_t/requirements.cpp @@ -0,0 +1,57 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/lock_guard_t.hpp" + +#include +#include + +#include +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + bsl::ut_scenario{"verify noexcept"} = []() { + bsl::ut_given{} = []() { + mk::tls_t tls{}; + mk::dummy_lock_t dummy_lock{}; + bsl::ut_then{} = []() { + static_assert(noexcept(mk::lock_guard_t{tls, dummy_lock})); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/kernel/test/mk_main/CMakeLists.txt b/kernel/test/mk_main/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/mk_main/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/mk_main/behavior.cpp b/kernel/test/mk_main/behavior.cpp new file mode 100644 index 00000000..ba60ab3e --- /dev/null +++ b/kernel/test/mk_main/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/mk_main.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/mk_main/requirements.cpp b/kernel/test/mk_main/requirements.cpp new file mode 100644 index 00000000..8527feca --- /dev/null +++ b/kernel/test/mk_main/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/mk_main.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/msg_halt/CMakeLists.txt b/kernel/test/msg_halt/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/msg_halt/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/msg_halt/behavior.cpp b/kernel/test/msg_halt/behavior.cpp new file mode 100644 index 00000000..ba60ab3e --- /dev/null +++ b/kernel/test/msg_halt/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/mk_main.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/msg_halt/requirements.cpp b/kernel/test/msg_halt/requirements.cpp new file mode 100644 index 00000000..8527feca --- /dev/null +++ b/kernel/test/msg_halt/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/mk_main.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/msg_stack_chk_fail/CMakeLists.txt b/kernel/test/msg_stack_chk_fail/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/msg_stack_chk_fail/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/msg_stack_chk_fail/behavior.cpp b/kernel/test/msg_stack_chk_fail/behavior.cpp new file mode 100644 index 00000000..ba60ab3e --- /dev/null +++ b/kernel/test/msg_stack_chk_fail/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/mk_main.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/msg_stack_chk_fail/requirements.cpp b/kernel/test/msg_stack_chk_fail/requirements.cpp new file mode 100644 index 00000000..8527feca --- /dev/null +++ b/kernel/test/msg_stack_chk_fail/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/mk_main.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/page_pool_t/CMakeLists.txt b/kernel/test/page_pool_t/CMakeLists.txt new file mode 100644 index 00000000..9f0277c6 --- /dev/null +++ b/kernel/test/page_pool_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${COMMON_DEFINES}) diff --git a/kernel/test/page_pool_t/behavior.cpp b/kernel/test/page_pool_t/behavior.cpp new file mode 100644 index 00000000..5a86a103 --- /dev/null +++ b/kernel/test/page_pool_t/behavior.cpp @@ -0,0 +1,470 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/page_pool_t.hpp" + +#include + +#include +#include + +/// NOTE: +/// - The page pool is unit tested using constexpr. How this works is really +/// simple. There are two different points of view to pay attention to here: +/// - The unit test for the page pool (this file) +/// - The unit test for something else that uses the page pool +/// - This unit test is responsible for unit testing the page pool itself, and +/// it has to do this as a constexpr. This ensures that we do not invoke +/// undefined behavior. This is really important as the allocator is not only +/// managing memory in a way that could lead to really bad things if not +/// handled correctly, it is also responsible for defining the lifetime of +/// an allocated object, and the constexpr nature of this unit test ensures +/// that this lifetime is handled properly. This unit test however cannot +/// test the allocation of anything other than nodes. Meaning, the allocator +/// allocates loader::page_pool_node_t nodes, and deallocates them. The +/// runtime logic allocates things like page tables and uint8 buffers for +/// random memory used by an extension. In a constexpr however, you cannot +/// change the type of memory. So for example, the page pool is managing a +/// linked list of pages, with each page in the list being a node. The page +/// pool cannot change a node from a node to a page table. This is not +/// allowed from a constexpr. That is not because it invokes UB, it is just +/// a rule that we must overcome. Interestingly though, we are not interested +/// in allocating page tables from this unit test. Instead, we are interested +/// in testing the logic itself, as well as things like object lifetime. +/// So, we only allocate nodes. This prevents a node from being changed to +/// something other than a node, which makes the unit test compile. +/// - The other point of view is from code that uses the page pool. That code +/// will use a mocked version of the page pool. So when that code calls +/// allocate from the page pool, it will allocate memory using new and then +/// deallocate memory using delete. These operators are allowed from a +/// constexpr, and they properly construct as required. Therefor, that mocked +/// version of the page pool can also be used in a constexpr, which means +/// that UB cannot occur there are well, including forgetting to deallocate +/// or deallocating using the wrong memory or wrong types. +/// - Using this approach, all of the code can be unit tested as a constexpr, +/// even with a custom allocator. +/// - Finally virt to phys translations. It would be possible to implement +/// these in a way that is also constexpr friendly as well. +/// - To convert a virtual address to a physical address, you would simply +/// use a null bsl::uint8 pointer. You can then use the address of the +/// direct map as the index into this array and grab it's address, and +/// perform pointer arithmetic to calculate the pointer version of the +/// physical address as follows: +/// +/// @code +/// T *base{}; +/// auto *const addr{&base[(HYPERVISOR_MK_PAGE_POOL_ADDR / HYPERVISOR_PAGE_SIZE).get()]}; +/// auto *const phys{virt - addr}; +/// for (bsl::safe_uintmax i{}; i < bsl::safe_uintmax::max(); ++i) { +/// if (&base[i.get()] == phys) { +/// return i; +/// } +/// } +/// +/// return bsl::safe_uintmax::failure(); +/// @endcode +/// +/// This example works because we never actually dereference the nullptr, +/// we are simply using it to perform pointer arithmetic. We need the loop +/// because we have no way of converting the calculated pointer to an +/// integral, so we loop until we find it. Even with some optimizations +/// this would be slow. It would work because we are not using any casts +/// to perform the translation, but it would be slow. +/// - To convert a physical address to a virtual addres, we can simply do +/// the same thing but in reverse, only this time the loop is not needed +/// as we can simply return the address of base at the calculated index. +/// +/// Although it is possible to make these constexpr friendly, there are a +/// couple of reasons why this would be a bad idea: +/// - Well, its slow, which is pretty obvious +/// - The translation is simple arithmetic. There is nothing UB to worry +/// about here. We are simply returning a calculation. If there is no +/// need to worry about UB, there is no need to worry about constexpr +/// here. The only UB to worry about is an overflow. +/// - It's not clear what would happen with the above arithmetic here if +/// an overflow were to occur. During the unit test, this type of overflow +/// would likely be detected, but at runtime, it wouldn't be and the +/// result would likely be UB. Using a cast, we can ensure that the pointer +/// becomes a safe integral, which means that any overflow, either at +/// compile time or runtime would be detected. +/// - The above code is no more compliant with AUTOSAR than the use of the +/// cast is. The above code performs pointer arithmetic which is also not +/// allowed. It is constexpr friendly, but that is not a requirement for +/// AUTOSAR, so no matter what, we would need an exception for this +/// operation. +/// - The only code that would need to be runtime only is in this unit test. +/// Any code that uses a mocked version of the page pool can use a map +/// of the allocated pointers to generate a physical address that can +/// then be used by the code in a constexpr, so at the end of the day, +/// yes it can be done, but no it should not be. +/// + +namespace mk +{ + /// @brief used by most of the tests + constexpr auto POOL_SIZE{3_umax}; + /// @brief used by the fill tag buffer test + constexpr auto TAG_POOL_SIZE{10_umax}; + /// @brief only used by the dump test as this is too large for the stack + constexpr auto LARGE_POOL_SIZE{2048_umax}; + + /// @brief used for dump to prevent the unit test from running out of stack + bsl::array g_pool{}; + + /// @brief reduce the verbosity of the tests. + using nd_t = loader::page_pool_node_t; + + /// + /// @brief Sets up the pool. Note that this similar to how the loader + /// would set up the pool, but not the same. The loader's pages will + /// be spare in their layout the virtual addresses of each page are + /// based on their physical address as they are in the direct map. + /// This spare nature of the pages is not a requirement of the page + /// pool. All the page pool cares about is that it is given a linked + /// list of pages. How those pages are layed out in memory does not + /// matter, so in the case of the unit test, we use a simple array. + /// + /// + /// @param pool the pool to initialize + /// + constexpr void + initialize_pool(bsl::span &pool) noexcept + { + constexpr auto one{1_umax}; + for (bsl::safe_uintmax i{}; i < pool.size() - one; ++i) { + pool.at_if(i)->next = pool.at_if(i + one); + } + + pool.back_if()->next = nullptr; + } + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"allocate invalid tag"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + page_pool_t page_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + initialize_pool(view); + page_pool.initialize(view); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(page_pool.allocate(tls, "") == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate empty"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + page_pool_t page_pool{}; + bsl::span view{}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + page_pool.initialize(view); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(page_pool.allocate(tls, "*") == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate until empty"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + page_pool_t page_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + initialize_pool(view); + page_pool.initialize(view); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(page_pool.allocate(tls, "*") == pool.at_if(0_umax)); + bsl::ut_check(page_pool.allocate(tls, "*") == pool.at_if(1_umax)); + bsl::ut_check(page_pool.allocate(tls, "*") == pool.at_if(2_umax)); + bsl::ut_check(page_pool.allocate(tls, "*") == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate until tags are full"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + page_pool_t page_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + initialize_pool(view); + page_pool.initialize(view); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(page_pool.allocate(tls, "0") == pool.at_if(0_umax)); + bsl::ut_check(page_pool.allocate(tls, "1") == pool.at_if(1_umax)); + bsl::ut_check(page_pool.allocate(tls, "2") == pool.at_if(2_umax)); + bsl::ut_check(page_pool.allocate(tls, "3") == pool.at_if(3_umax)); + bsl::ut_check(page_pool.allocate(tls, "4") == pool.at_if(4_umax)); + bsl::ut_check(page_pool.allocate(tls, "5") == pool.at_if(5_umax)); + bsl::ut_check(page_pool.allocate(tls, "6") == pool.at_if(6_umax)); + bsl::ut_check(page_pool.allocate(tls, "7") == pool.at_if(7_umax)); + bsl::ut_check(page_pool.allocate(tls, "8") == pool.at_if(8_umax)); + bsl::ut_check(page_pool.allocate(tls, "9") == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate nullptr"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + page_pool_t page_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + nd_t *node0{}; + bsl::ut_when{} = [&]() noexcept { + initialize_pool(view); + page_pool.initialize(view); + node0 = page_pool.allocate(tls, "*"); + bsl::ut_required_step(page_pool.allocated(tls, "*") == HYPERVISOR_PAGE_SIZE); + bsl::ut_then{} = [&]() noexcept { + page_pool.deallocate(tls, nullptr, "*"); + bsl::ut_check(page_pool.allocated(tls, "*") == HYPERVISOR_PAGE_SIZE); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate invalid tag"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + page_pool_t page_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + nd_t *node0{}; + bsl::ut_when{} = [&]() noexcept { + initialize_pool(view); + page_pool.initialize(view); + node0 = page_pool.allocate(tls, "*"); + bsl::ut_required_step(page_pool.allocated(tls, "*") == HYPERVISOR_PAGE_SIZE); + bsl::ut_then{} = [&]() noexcept { + page_pool.deallocate(tls, node0, "42"); + bsl::ut_check(page_pool.allocated(tls, "*") == HYPERVISOR_PAGE_SIZE); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + page_pool_t page_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + nd_t *node0{}; + bsl::ut_when{} = [&]() noexcept { + initialize_pool(view); + page_pool.initialize(view); + node0 = page_pool.allocate(tls, "*"); + bsl::ut_required_step(page_pool.allocated(tls, "*") == HYPERVISOR_PAGE_SIZE); + bsl::ut_then{} = [&]() noexcept { + page_pool.deallocate(tls, node0, "*"); + bsl::ut_check(page_pool.allocated(tls, "*").is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate from empty"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + page_pool_t page_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + nd_t *node0{}; + nd_t *node1{}; + nd_t *node2{}; + bsl::ut_when{} = [&]() noexcept { + initialize_pool(view); + page_pool.initialize(view); + node0 = page_pool.allocate(tls, "*"); + node1 = page_pool.allocate(tls, "*"); + node2 = page_pool.allocate(tls, "*"); + bsl::ut_required_step(page_pool.allocate(tls, "*") == nullptr); + bsl::ut_then{} = [&]() noexcept { + page_pool.deallocate(tls, node2, "*"); + page_pool.deallocate(tls, node1, "*"); + page_pool.deallocate(tls, node0, "*"); + bsl::ut_check(page_pool.allocated(tls, "*").is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate from empty in reverse order"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + page_pool_t page_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + nd_t *node0{}; + nd_t *node1{}; + nd_t *node2{}; + bsl::ut_when{} = [&]() noexcept { + initialize_pool(view); + page_pool.initialize(view); + node0 = page_pool.allocate(tls, "*"); + node1 = page_pool.allocate(tls, "*"); + node2 = page_pool.allocate(tls, "*"); + bsl::ut_required_step(page_pool.allocate(tls, "*") == nullptr); + bsl::ut_then{} = [&]() noexcept { + page_pool.deallocate(tls, node0, "*"); + page_pool.deallocate(tls, node1, "*"); + page_pool.deallocate(tls, node2, "*"); + bsl::ut_check(page_pool.allocated(tls, "*").is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"allocated"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + page_pool_t page_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + initialize_pool(view); + page_pool.initialize(view); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!page_pool.allocated(tls, "")); + bsl::ut_check(!page_pool.allocated(tls, "*")); + bsl::ut_check(page_pool.allocate(tls, "*") == pool.at_if(0_umax)); + bsl::ut_check( + page_pool.allocated(tls, "*") == HYPERVISOR_PAGE_SIZE * 1_umax); + bsl::ut_check(page_pool.allocate(tls, "*") == pool.at_if(1_umax)); + bsl::ut_check( + page_pool.allocated(tls, "*") == HYPERVISOR_PAGE_SIZE * 2_umax); + bsl::ut_check(page_pool.allocate(tls, "*") == pool.at_if(2_umax)); + bsl::ut_check( + page_pool.allocated(tls, "*") == HYPERVISOR_PAGE_SIZE * 3_umax); + bsl::ut_check(!page_pool.allocated(tls, "42")); + }; + }; + }; + }; + + bsl::ut_scenario{"virt_to_phys"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + page_pool_t page_pool{}; + nd_t node{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!page_pool.virt_to_phys(nullptr)); + bsl::ut_check( + page_pool.virt_to_phys(&node) == + bsl::to_umax(&node) - HYPERVISOR_MK_PAGE_POOL_ADDR); + }; + }; + }; + + bsl::ut_scenario{"phys_to_virt"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + page_pool_t page_pool{}; + nd_t node{}; + constexpr auto bad_phys{0xFFFFFFFFFFFFFFFF_umax}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(nullptr == page_pool.phys_to_virt(bad_phys)); + bsl::ut_check( + page_pool.phys_to_virt( + bsl::to_umax(&node) - HYPERVISOR_MK_PAGE_POOL_ADDR) == &node); + }; + }; + }; + + bsl::ut_scenario{"dump"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + page_pool_t page_pool{}; + bsl::array pool{}; + bsl::span view{pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + initialize_pool(view); + page_pool.initialize(view); + bsl::ut_required_step(page_pool.allocate(tls, "*") != nullptr); + bsl::ut_required_step(page_pool.allocate(tls, "*") != nullptr); + bsl::ut_required_step(page_pool.allocate(tls, "*") != nullptr); + bsl::ut_then{} = [&]() noexcept { + page_pool.dump(); + }; + }; + }; + + bsl::ut_given_at_runtime{} = []() noexcept { + page_pool_t page_pool{}; + bsl::span view{g_pool}; + tls_t tls{}; + bsl::ut_when{} = [&]() noexcept { + initialize_pool(view); + page_pool.initialize(view); + for (bsl::safe_uintmax i{}; i < 1024_umax; ++i) { + bsl::ut_required_step( + page_pool.allocate(tls, "memory hog") != nullptr); + } + bsl::ut_required_step(page_pool.allocate(tls, "*") != nullptr); + bsl::ut_then{} = [&]() noexcept { + page_pool.dump(); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/page_pool_t/requirements.cpp b/kernel/test/page_pool_t/requirements.cpp new file mode 100644 index 00000000..f4c43d35 --- /dev/null +++ b/kernel/test/page_pool_t/requirements.cpp @@ -0,0 +1,123 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/page_pool_t.hpp" + +#include + +#include +#include +#include + +namespace +{ + constinit mk::page_pool_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + mk::page_pool_t m_pool{}; + + public: + [[nodiscard]] constexpr auto + test_member_const() const noexcept -> bool + { + mk::page_t page{}; + + bsl::discard(m_pool.virt_to_phys(&page)); + bsl::discard(m_pool.phys_to_virt({})); + m_pool.dump(); + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + bsl::span view{}; + mk::tls_t tls{}; + mk::page_t page{}; + + bsl::discard(mk::page_pool_t{}); + m_pool.initialize(view); + bsl::discard(m_pool.allocate(tls, "")); + m_pool.deallocate(tls, {}, ""); + bsl::discard(m_pool.virt_to_phys(&page)); + bsl::discard(m_pool.phys_to_virt({})); + m_pool.dump(); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit/constexpr"} = []() noexcept { + bsl::discard(g_verify_constinit); + bsl::discard(FIXTURE1); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + mk::page_pool_t pool{}; + bsl::span view{}; + mk::tls_t tls{}; + mk::page_t page{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(mk::page_pool_t{})); + static_assert(noexcept(pool.initialize(view))); + static_assert(noexcept(pool.allocate(tls, ""))); + static_assert(noexcept(pool.deallocate(tls, {}, ""))); + static_assert(noexcept(pool.virt_to_phys(&page))); + static_assert(noexcept(pool.phys_to_virt({}))); + static_assert(noexcept(pool.dump())); + }; + }; + }; + + bsl::ut_scenario{"verify constness without using constexpr"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + fixture_t fixture2{}; + fixture_t const fixture3{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(fixture3.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/kernel/test/serial_write/CMakeLists.txt b/kernel/test/serial_write/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/serial_write/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/serial_write/behavior.cpp b/kernel/test/serial_write/behavior.cpp new file mode 100644 index 00000000..429f06fa --- /dev/null +++ b/kernel/test/serial_write/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/serial_write.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/serial_write/requirements.cpp b/kernel/test/serial_write/requirements.cpp new file mode 100644 index 00000000..34c5eeab --- /dev/null +++ b/kernel/test/serial_write/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/serial_write.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/spinlock_t/CMakeLists.txt b/kernel/test/spinlock_t/CMakeLists.txt new file mode 100644 index 00000000..21563d59 --- /dev/null +++ b/kernel/test/spinlock_t/CMakeLists.txt @@ -0,0 +1,29 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if(NOT WIN32) + list(APPEND LIBRARIES + pthread + ) +endif() + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES} LIBRARIES ${LIBRARIES}) diff --git a/kernel/test/spinlock_t/behavior.cpp b/kernel/test/spinlock_t/behavior.cpp new file mode 100644 index 00000000..2acde99c --- /dev/null +++ b/kernel/test/spinlock_t/behavior.cpp @@ -0,0 +1,449 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/spinlock_t.hpp" + +#include +#include +#include + +#include +#include + +namespace mk +{ + /// @brief defines the max number of wait threads + constexpr auto MAX_WAIT_THREADS{1024_umax}; + /// @brief defines the global spin lock used for the thread tests + constinit spinlock_t g_spinlock{}; + /// @brief defines the dummy TLS block for the block thread + constinit tls_t g_tls_block{}; + /// @brief defines the dummy TLS block for wait thread + constinit bsl::array g_tls_wait{}; + /// @brief stores how many threads are started + constinit std::atomic g_threads_started{}; + /// @brief stores how many threads had to wait + constinit std::atomic g_threads_that_waited{}; + + /// + /// @brief Implements a yield for the spinlock + /// + extern "C" void + yield() noexcept + { + std::this_thread::yield(); + } + + /// + /// @brief Used to test to make sure that threads have to wait + /// + void + thread_func(bsl::safe_uintmax const ppid) + { + bool this_thread_waited{}; + + auto *const tls{g_tls_wait.at_if(ppid)}; + tls->ppid = bsl::to_u16(ppid).get(); + + ++g_threads_started; + + g_spinlock.lock(*tls); + while (static_cast(g_threads_started) < MAX_WAIT_THREADS) { + if (!this_thread_waited) { + ++g_threads_that_waited; + this_thread_waited = true; + } + + yield(); + } + g_spinlock.unlock(*tls); + } + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"lock/unlock"} = []() { + bsl::ut_given_at_runtime{} = []() { + spinlock_t spinlock{}; + tls_t tls{}; + bsl::ut_when{} = [&spinlock, &tls]() { + tls.esr_ip = {}; + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(!spinlock.is_locked()); + }; + }; + }; + }; + + bsl::ut_scenario{"lock/unlock from esr"} = []() { + bsl::ut_given_at_runtime{} = []() { + spinlock_t spinlock{}; + tls_t tls{}; + bsl::ut_when{} = [&spinlock, &tls]() { + tls.esr_ip = (1_umax).get(); + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(!spinlock.is_locked()); + }; + }; + }; + }; + + bsl::ut_scenario{"lock twice"} = []() { + bsl::ut_given_at_runtime{} = []() { + spinlock_t spinlock{}; + tls_t tls{}; + bsl::ut_when{} = [&spinlock, &tls]() { + tls.esr_ip = {}; + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(!spinlock.is_locked()); + }; + }; + }; + }; + + bsl::ut_scenario{"lock twice from esr"} = []() { + bsl::ut_given_at_runtime{} = []() { + spinlock_t spinlock{}; + tls_t tls{}; + bsl::ut_when{} = [&spinlock, &tls]() { + tls.esr_ip = (1_umax).get(); + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(!spinlock.is_locked()); + }; + }; + }; + }; + + bsl::ut_scenario{"lock std, lock esr, unlock esr, unlock std"} = []() { + bsl::ut_given_at_runtime{} = []() { + spinlock_t spinlock{}; + tls_t tls{}; + bsl::ut_when{} = [&spinlock, &tls]() { + tls.esr_ip = {}; + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(!spinlock.is_locked()); + }; + }; + }; + }; + + bsl::ut_scenario{"lock esr, lock std, unlock std, unlock esr"} = []() { + bsl::ut_given_at_runtime{} = []() { + spinlock_t spinlock{}; + tls_t tls{}; + bsl::ut_when{} = [&spinlock, &tls]() { + tls.esr_ip = (1_umax).get(); + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(!spinlock.is_locked()); + }; + }; + }; + }; + + bsl::ut_scenario{"lock esr, lock std, unlock esr, unlock std"} = []() { + bsl::ut_given_at_runtime{} = []() { + spinlock_t spinlock{}; + tls_t tls{}; + bsl::ut_when{} = [&spinlock, &tls]() { + tls.esr_ip = (1_umax).get(); + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(!spinlock.is_locked()); + }; + }; + }; + }; + + bsl::ut_scenario{"lock std, lock esr, unlock std, unlock esr"} = []() { + bsl::ut_given_at_runtime{} = []() { + spinlock_t spinlock{}; + tls_t tls{}; + bsl::ut_when{} = [&spinlock, &tls]() { + tls.esr_ip = {}; + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(!spinlock.is_locked()); + }; + }; + }; + }; + + bsl::ut_scenario{"lock std, lock esr, lock esr, unlock std, unlock esr"} = []() { + bsl::ut_given_at_runtime{} = []() { + spinlock_t spinlock{}; + tls_t tls{}; + bsl::ut_when{} = [&spinlock, &tls]() { + tls.esr_ip = {}; + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(!spinlock.is_locked()); + }; + }; + }; + }; + + bsl::ut_scenario{"lock esr, lock std, lock std, unlock esr, unlock std"} = []() { + bsl::ut_given_at_runtime{} = []() { + spinlock_t spinlock{}; + tls_t tls{}; + bsl::ut_when{} = [&spinlock, &tls]() { + tls.esr_ip = (1_umax).get(); + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.lock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = (1_umax).get(); + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(spinlock.is_locked()); + }; + + tls.esr_ip = {}; + spinlock.unlock(tls); + bsl::ut_then{} = [&spinlock]() { + bsl::ut_check(!spinlock.is_locked()); + }; + }; + }; + }; + + bsl::ut_scenario{"prove spin locks wait"} = []() { + bsl::ut_given_at_runtime{} = []() { + bsl::array threads{}; + bsl::ut_when{} = [&threads]() { + for (bsl::safe_uintmax i{}; i < MAX_WAIT_THREADS; ++i) { + *threads.at_if(i) = std::thread{&thread_func, i}; + } + for (bsl::safe_uintmax i{}; i < MAX_WAIT_THREADS; ++i) { + threads.at_if(i)->join(); + } + bsl::ut_then{} = []() { + bsl::ut_check( + static_cast(g_threads_started) == MAX_WAIT_THREADS); + + // NOTE: + // - If g_threads_that_waited is one, it means that + // all of the threads were locked until they were + // all started. Once there are all started, the + // thread that gets the critical region first will + // be the only thread that had to wait. The rest + // will get access to the critical region and just + // pass through. This proves that some of the threads + // had to spin on the spinlock and not pass through, + // otherwise this count would be higher than 1. + // - What is great about this approach is that it will + // work no matter how many threads you create, and + // it will also work on single core systems. It also + // ensures that every line and break is executed, so + // there are no race conditions, which previous + // attempts at this test had. + // + + bsl::ut_check(static_cast(g_threads_that_waited) == 1_umax); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + mk::yield(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/spinlock_t/requirements.cpp b/kernel/test/spinlock_t/requirements.cpp new file mode 100644 index 00000000..c289bb91 --- /dev/null +++ b/kernel/test/spinlock_t/requirements.cpp @@ -0,0 +1,115 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/spinlock_t.hpp" + +#include + +#include +#include + +namespace mk +{ + constinit spinlock_t const verify_constinit{}; + + // Needed for requirements testing + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + spinlock_t spinlock{}; + + public: + [[nodiscard]] constexpr auto + test_member_const() const noexcept -> bool + { + bsl::discard(spinlock.is_locked()); + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + tls_t tls{}; + spinlock.lock(tls); + spinlock.unlock(tls); + bsl::discard(spinlock.is_locked()); + + return true; + } + }; + + constexpr fixture_t fixture1{}; + + /// + /// @brief Implements a yield for the spinlock + /// + extern "C" void + yield() noexcept + {} +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + mk::yield(); + + bsl::ut_scenario{"verify supports constinit"} = []() { + bsl::discard(mk::verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() { + bsl::ut_given{} = []() { + mk::spinlock_t spinlock{}; + mk::tls_t tls{}; + bsl::ut_then{} = []() { + static_assert(noexcept(mk::spinlock_t{})); + static_assert(noexcept(spinlock.lock(tls))); + static_assert(noexcept(spinlock.unlock(tls))); + static_assert(noexcept(spinlock.is_locked())); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() { + bsl::ut_given{} = []() { + mk::fixture_t fixture2{}; + bsl::ut_then{} = [&fixture2]() { + static_assert(mk::fixture1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/kernel/test/vm_pool_t/CMakeLists.txt b/kernel/test/vm_pool_t/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/vm_pool_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/vm_pool_t/behavior.cpp b/kernel/test/vm_pool_t/behavior.cpp new file mode 100644 index 00000000..b7102533 --- /dev/null +++ b/kernel/test/vm_pool_t/behavior.cpp @@ -0,0 +1,481 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vm_pool_t.hpp" + +#include +#include +#include + +#include + +namespace mk +{ + /// @brief defines the 3 max VMs used in testing + constexpr bsl::safe_uintmax INTEGRATION_MAX_VMS{bsl::to_umax(3)}; + + /// @brief defines VMID0 + constexpr bsl::safe_uint16 VMID0{bsl::to_u16(0)}; + /// @brief defines VMID1 + constexpr bsl::safe_uint16 VMID1{bsl::to_u16(1)}; + /// @brief defines VMID2 + constexpr bsl::safe_uint16 VMID2{bsl::to_u16(2)}; + + /// + /// @brief Implements a yield for the spinlock + /// + extern "C" void + yield() noexcept + {} + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize vm_t reports success"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + }; + }; + }; + + bsl::ut_scenario{"initialize vm_t reports failure"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + tls.test_ret = errc_fail_initialize; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize vm_t and release report failure"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + tls.test_ret = errc_fail_initialize_and_release; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + }; + }; + }; + }; + + bsl::ut_scenario{"release without initialize"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.release(tls, bsl::dontcare, bsl::dontcare)); + }; + }; + }; + + bsl::ut_scenario{"release with initialize"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.release(tls, bsl::dontcare, bsl::dontcare)); + }; + }; + }; + }; + + bsl::ut_scenario{"release with initialize and vm_t reports failure"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + tls.test_ret = errc_fail_release; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.release(tls, bsl::dontcare, bsl::dontcare)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate all vms"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.allocate(tls, bsl::dontcare) == VMID0); + bsl::ut_check(pool.allocate(tls, bsl::dontcare) == VMID1); + bsl::ut_check(pool.allocate(tls, bsl::dontcare) == VMID2); + bsl::ut_check(!pool.allocate(tls, bsl::dontcare)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate vm_t reports failure"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.allocate(tls, bsl::dontcare)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate invalid id"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.deallocate( + tls, bsl::dontcare, bsl::dontcare, syscall::BF_INVALID_ID)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate vm_t reports failure"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + auto const vmid{pool.allocate(tls, bsl::dontcare)}; + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&pool, &tls, &vmid]() { + bsl::ut_check(!pool.deallocate(tls, bsl::dontcare, bsl::dontcare, vmid)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate success"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + auto const vmid{pool.allocate(tls, bsl::dontcare)}; + bsl::ut_then{} = [&pool, &tls, &vmid]() { + bsl::ut_check(pool.deallocate(tls, bsl::dontcare, bsl::dontcare, vmid)); + }; + }; + }; + }; + + bsl::ut_scenario{"zombify invalid id"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + bsl::ut_then{} = [&pool]() { + bsl::ut_check(!pool.zombify(syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"zombify success"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + bsl::ut_then{} = [&pool]() { + bsl::ut_check(pool.zombify(VMID1)); + }; + }; + }; + + bsl::ut_scenario{"status invalid id"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_allocated(tls, syscall::BF_INVALID_ID)); + bsl::ut_check(!pool.is_deallocated(tls, syscall::BF_INVALID_ID)); + bsl::ut_check(!pool.is_zombie(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + }; + + bsl::ut_scenario{"status after initialize"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_allocated(tls, VMID0)); + bsl::ut_check(pool.is_deallocated(tls, VMID0)); + bsl::ut_check(!pool.is_zombie(tls, VMID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"status after allocate"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + auto const vmid{pool.allocate(tls, bsl::dontcare)}; + bsl::ut_then{} = [&pool, &tls, &vmid]() { + bsl::ut_check(pool.is_allocated(tls, vmid)); + bsl::ut_check(!pool.is_deallocated(tls, vmid)); + bsl::ut_check(!pool.is_zombie(tls, vmid)); + }; + }; + }; + }; + + bsl::ut_scenario{"status after deallocate"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + auto const vmid{pool.allocate(tls, bsl::dontcare)}; + bsl::ut_required_step(pool.deallocate(tls, bsl::dontcare, bsl::dontcare, vmid)); + bsl::ut_then{} = [&pool, &tls, &vmid]() { + bsl::ut_check(!pool.is_allocated(tls, vmid)); + bsl::ut_check(pool.is_deallocated(tls, vmid)); + bsl::ut_check(!pool.is_zombie(tls, vmid)); + }; + }; + }; + }; + + bsl::ut_scenario{"status after zombify"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare, bsl::dontcare)); + bsl::ut_required_step(pool.zombify(VMID1)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_allocated(tls, VMID1)); + bsl::ut_check(!pool.is_deallocated(tls, VMID1)); + bsl::ut_check(pool.is_zombie(tls, VMID1)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active invalid id"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.set_active(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"set_active vm_t reports failure"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.set_active(tls, VMID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active success"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.set_active(tls, VMID0)); + }; + }; + }; + + bsl::ut_scenario{"set_inactive invalid id"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.set_inactive(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"set_inactive vm_t reports failure"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.set_inactive(tls, VMID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive success"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.set_inactive(tls, VMID0)); + }; + }; + }; + + bsl::ut_scenario{"is_active invalid id"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"is_active success"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active(tls, VMID0)); + }; + + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_check(pool.set_active(tls, VMID0)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.is_active(tls, VMID0)); + }; + }; + + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_check(pool.set_inactive(tls, VMID0)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active(tls, VMID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp invalid id"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active_on_current_pp(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp success"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active_on_current_pp(tls, VMID0)); + }; + + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_check(pool.set_active(tls, VMID0)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.is_active_on_current_pp(tls, VMID0)); + }; + }; + + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_check(pool.set_inactive(tls, VMID0)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active_on_current_pp(tls, VMID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"dump invalid id"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + pool.dump(tls, syscall::BF_INVALID_ID); + }; + }; + }; + + bsl::ut_scenario{"dump success"} = []() { + bsl::ut_given{} = []() { + vm_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + pool.dump(tls, VMID0); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + mk::yield(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/vm_pool_t/requirements.cpp b/kernel/test/vm_pool_t/requirements.cpp new file mode 100644 index 00000000..91e6e18d --- /dev/null +++ b/kernel/test/vm_pool_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vm_pool_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/vm_t/CMakeLists.txt b/kernel/test/vm_t/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/vm_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/vm_t/behavior.cpp b/kernel/test/vm_t/behavior.cpp new file mode 100644 index 00000000..a43dae3f --- /dev/null +++ b/kernel/test/vm_t/behavior.cpp @@ -0,0 +1,1081 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vm_t.hpp" + +#include +#include +#include +#include + +#include + +namespace mk +{ + /// @brief defines the max number of PPs used in testing + constexpr bsl::safe_uint16 INTEGRATION_MAX_PPS{bsl::to_u16(3)}; + + /// @brief defines VMID0 + constexpr bsl::safe_uint16 VMID0{bsl::to_u16(0)}; + /// @brief defines VMID1 + constexpr bsl::safe_uint16 VMID1{bsl::to_u16(1)}; + + /// + /// @brief Implements a yield for the spinlock + /// + extern "C" void + yield() noexcept + {} + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize invalid id version #1"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_then{} = [&vm, &tls]() { + bsl::ut_check(!vm.initialize(tls, bsl::safe_uint16::failure())); + }; + }; + }; + + bsl::ut_scenario{"initialize invalid id version #2"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_then{} = [&vm, &tls]() { + bsl::ut_check(!vm.initialize(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_then{} = [&vm, &tls]() { + bsl::ut_check(vm.initialize(tls, VMID0)); + }; + }; + }; + + bsl::ut_scenario{"initialize more than once failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_when{} = [&vm, &tls]() { + bsl::ut_required_step(vm.initialize(tls, VMID0)); + bsl::ut_then{} = [&vm, &tls]() { + bsl::ut_check(!vm.initialize(tls, VMID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"release of the root VM is ignored"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID0)); + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(vm.release(tls, ext_pool, vp_pool)); + bsl::ut_check(vm.id()); + }; + }; + }; + }; + + bsl::ut_scenario{"release success"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(vm.release(tls, ext_pool, vp_pool)); + bsl::ut_check(!vm.id()); + }; + }; + }; + }; + + bsl::ut_scenario{"release success after allocate"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(vm.release(tls, ext_pool, vp_pool)); + bsl::ut_check(!vm.id()); + bsl::ut_check(!vm.is_allocated()); + }; + }; + }; + }; + + bsl::ut_scenario{"release of a zombie vm is ignored"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + vm.zombify(); + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(vm.release(tls, ext_pool, vp_pool)); + bsl::ut_check(vm.id()); + bsl::ut_check(vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"release of a vm that is still assigned results in a zombie"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + tls.test_ret = errc_vp_pool_failure; + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(!vm.release(tls, ext_pool, vp_pool)); + bsl::ut_check(vm.id()); + bsl::ut_check(vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"release of a vm that is still active results in a zombie"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(!vm.release(tls, ext_pool, vp_pool)); + bsl::ut_check(vm.id()); + bsl::ut_check(vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"release with extension failure results in zombie"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + tls.test_ret = errc_ext_pool_failure; + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(!vm.release(tls, ext_pool, vp_pool)); + bsl::ut_check(vm.id()); + bsl::ut_check(vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate without initialize failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_then{} = [&vm, &tls, &ext_pool]() { + bsl::ut_check(!vm.allocate(tls, ext_pool)); + }; + }; + }; + + bsl::ut_scenario{"allocate zombie failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + vm.zombify(); + bsl::ut_then{} = [&vm, &tls, &ext_pool]() { + bsl::ut_check(!vm.allocate(tls, ext_pool)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate with extension failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + tls.test_ret = errc_ext_pool_failure; + bsl::ut_then{} = [&vm, &tls, &ext_pool]() { + bsl::ut_check(!vm.allocate(tls, ext_pool)); + bsl::ut_check(tls.state_reversal_required); + bsl::ut_check(tls.log_vmid == VMID1); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate success"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_then{} = [&vm, &tls, &ext_pool]() { + bsl::ut_check(vm.allocate(tls, ext_pool)); + bsl::ut_check(tls.state_reversal_required); + bsl::ut_check(tls.log_vmid == VMID1); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate more than once failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID0)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&vm, &tls, &ext_pool]() { + bsl::ut_check(!vm.allocate(tls, ext_pool)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate not initialized failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(!vm.deallocate(tls, ext_pool, vp_pool)); + }; + }; + }; + + bsl::ut_scenario{"deallocate root vm failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID0)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(!vm.deallocate(tls, ext_pool, vp_pool)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate zombie failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + vm.zombify(); + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(!vm.deallocate(tls, ext_pool, vp_pool)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate already deallocated failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.deallocate(tls, ext_pool, vp_pool)); + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(!vm.deallocate(tls, ext_pool, vp_pool)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate assigned failure results in zombie"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + tls.test_ret = errc_vp_pool_failure; + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(!vm.deallocate(tls, ext_pool, vp_pool)); + bsl::ut_check(vm.is_zombie()); + bsl::ut_check(tls.state_reversal_required); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate still active failure results in zombie"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(!vm.deallocate(tls, ext_pool, vp_pool)); + bsl::ut_check(vm.is_zombie()); + bsl::ut_check(tls.state_reversal_required); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate with extension failure results in zombie"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + tls.test_ret = errc_ext_pool_failure; + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(!vm.deallocate(tls, ext_pool, vp_pool)); + bsl::ut_check(vm.is_zombie()); + bsl::ut_check(tls.state_reversal_required); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate success"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_check(vm.deallocate(tls, ext_pool, vp_pool)); + bsl::ut_check(tls.state_reversal_required); + }; + }; + }; + }; + + bsl::ut_scenario{"zombify without initialize success"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + bsl::ut_when{} = [&vm]() { + vm.zombify(); + bsl::ut_then{} = [&vm]() { + bsl::ut_check(!vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"zombify success"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_when{} = [&vm, &tls]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + vm.zombify(); + bsl::ut_then{} = [&vm]() { + bsl::ut_check(vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"zombify root vm is ignored"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_when{} = [&vm, &tls]() { + bsl::ut_required_step(vm.initialize(tls, VMID0)); + vm.zombify(); + bsl::ut_then{} = [&vm]() { + bsl::ut_check(!vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"zombify more than once is ignored"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_when{} = [&vm, &tls]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + vm.zombify(); + vm.zombify(); + bsl::ut_then{} = [&vm]() { + bsl::ut_check(vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"status without initialize"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + bsl::ut_then{} = [&vm]() { + bsl::ut_check(vm.is_deallocated()); + bsl::ut_check(!vm.is_allocated()); + bsl::ut_check(!vm.is_zombie()); + }; + }; + }; + + bsl::ut_scenario{"status after initialize"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_when{} = [&vm, &tls]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_then{} = [&vm]() { + bsl::ut_check(vm.is_deallocated()); + bsl::ut_check(!vm.is_allocated()); + bsl::ut_check(!vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"status after allocation"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&vm]() { + bsl::ut_check(!vm.is_deallocated()); + bsl::ut_check(vm.is_allocated()); + bsl::ut_check(!vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"status after deallocation"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + dummy_vp_pool_t vp_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool, &vp_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.deallocate(tls, ext_pool, vp_pool)); + bsl::ut_then{} = [&vm]() { + bsl::ut_check(vm.is_deallocated()); + bsl::ut_check(!vm.is_allocated()); + bsl::ut_check(!vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"status after zombify"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_when{} = [&vm, &tls]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + vm.zombify(); + bsl::ut_then{} = [&vm]() { + bsl::ut_check(!vm.is_deallocated()); + bsl::ut_check(!vm.is_allocated()); + bsl::ut_check(vm.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active without initialize failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_active(tls)); + }; + }; + }; + + bsl::ut_scenario{"set_active without allocate failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_when{} = [&tls, &vm]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active zombie failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + vm.zombify(); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active already active"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active corrupt already active"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active another vm is active failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = VMID0.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active invalid ppid failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + tls.ppid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active success"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(vm.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive without initialize failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_inactive(tls)); + }; + }; + }; + + bsl::ut_scenario{"set_inactive without activate failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_when{} = [&tls, &vm]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive zombie is allowed"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + vm.zombify(); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(vm.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive already inactive"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive active vm is not this vm"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + tls.active_vmid = VMID0.get(); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive invalid ppid failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + tls.ppid = syscall::BF_INVALID_ID.get(); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive more than once failure"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + bsl::ut_required_step(vm.set_inactive(tls)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive corrupt active vm"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + bsl::ut_required_step(vm.set_inactive(tls)); + tls.active_vmid = VMID1.get(); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive success"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(vm.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active reports true"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(vm.is_active(tls) == tls.ppid); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active reports false"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.is_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active reports false with corrupt online_pps"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = syscall::BF_INVALID_ID.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.is_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active reports false with no online_pps"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.is_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp reports true"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(vm.is_active_on_current_pp(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp reports false"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.is_active_on_current_pp(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp invalid ppid"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + tls.ppid = syscall::BF_INVALID_ID.get(); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.is_active_on_current_pp(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp reports false with corrupt online_pps"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = syscall::BF_INVALID_ID.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&tls, &vm]() { + bsl::ut_check(!vm.is_active_on_current_pp(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"dump without initialize"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_then{} = [&tls, &vm]() { + vm.dump(tls); + }; + }; + }; + + bsl::ut_scenario{"dump with initialize"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + bsl::ut_when{} = [&tls, &vm]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_then{} = [&tls, &vm]() { + vm.dump(tls); + }; + }; + }; + }; + + bsl::ut_scenario{"dump with allocate"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_then{} = [&tls, &vm]() { + vm.dump(tls); + }; + }; + }; + }; + + bsl::ut_scenario{"dump with active"} = []() { + bsl::ut_given{} = []() { + vm_t vm{}; + tls_t tls{}; + dummy_ext_pool_t ext_pool{}; + bsl::ut_when{} = [&vm, &tls, &ext_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vm.initialize(tls, VMID1)); + bsl::ut_required_step(vm.allocate(tls, ext_pool)); + bsl::ut_required_step(vm.set_active(tls)); + bsl::ut_then{} = [&tls, &vm]() { + vm.dump(tls); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + mk::yield(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/vm_t/requirements.cpp b/kernel/test/vm_t/requirements.cpp new file mode 100644 index 00000000..145b2f1f --- /dev/null +++ b/kernel/test/vm_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vm_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/vmexit_loop/CMakeLists.txt b/kernel/test/vmexit_loop/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/vmexit_loop/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/vmexit_loop/behavior.cpp b/kernel/test/vmexit_loop/behavior.cpp new file mode 100644 index 00000000..643ade51 --- /dev/null +++ b/kernel/test/vmexit_loop/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vmexit_loop.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/vmexit_loop/requirements.cpp b/kernel/test/vmexit_loop/requirements.cpp new file mode 100644 index 00000000..2bd40927 --- /dev/null +++ b/kernel/test/vmexit_loop/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vmexit_loop.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/vp_pool_t/CMakeLists.txt b/kernel/test/vp_pool_t/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/vp_pool_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/vp_pool_t/behavior.cpp b/kernel/test/vp_pool_t/behavior.cpp new file mode 100644 index 00000000..2300e520 --- /dev/null +++ b/kernel/test/vp_pool_t/behavior.cpp @@ -0,0 +1,676 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vp_pool_t.hpp" + +#include +#include +#include + +#include + +namespace mk +{ + /// @brief defines the max number of VMs used in testing + constexpr bsl::safe_uintmax INTEGRATION_MAX_VPS{bsl::to_umax(3)}; + + /// @brief defines VMID0 + constexpr bsl::safe_uint16 VMID0{bsl::to_u16(0)}; + /// @brief defines VMID1 + constexpr bsl::safe_uint16 VMID1{bsl::to_u16(1)}; + + /// @brief defines PPID0 + constexpr bsl::safe_uint16 PPID0{bsl::to_u16(0)}; + + /// @brief defines VPID0 + constexpr bsl::safe_uint16 VPID0{bsl::to_u16(0)}; + /// @brief defines VPID1 + constexpr bsl::safe_uint16 VPID1{bsl::to_u16(1)}; + /// @brief defines VPID2 + constexpr bsl::safe_uint16 VPID2{bsl::to_u16(2)}; + + /// + /// @brief Implements a yield for the spinlock + /// + extern "C" void + yield() noexcept + {} + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize vp_t reports success"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.initialize(tls, bsl::dontcare)); + }; + }; + }; + + bsl::ut_scenario{"initialize vp_t reports failure"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + tls.test_ret = errc_fail_initialize; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.initialize(tls, bsl::dontcare)); + }; + }; + }; + }; + + bsl::ut_scenario{"initialize vp_t and release report failure"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + tls.test_ret = errc_fail_initialize_and_release; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.initialize(tls, bsl::dontcare)); + }; + }; + }; + }; + + bsl::ut_scenario{"release without initialize"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.release(tls, bsl::dontcare)); + }; + }; + }; + + bsl::ut_scenario{"release with initialize"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.release(tls, bsl::dontcare)); + }; + }; + }; + }; + + bsl::ut_scenario{"release with initialize and vp_t reports failure"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + tls.test_ret = errc_fail_release; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.release(tls, bsl::dontcare)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate all vps"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.allocate(tls, bsl::dontcare, VMID0, PPID0) == VPID0); + bsl::ut_check(pool.allocate(tls, bsl::dontcare, VMID0, PPID0) == VPID1); + bsl::ut_check(pool.allocate(tls, bsl::dontcare, VMID0, PPID0) == VPID2); + bsl::ut_check(!pool.allocate(tls, bsl::dontcare, VMID0, PPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate vp_t reports failure"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.allocate(tls, bsl::dontcare, VMID0, PPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.deallocate(tls, bsl::dontcare, syscall::BF_INVALID_ID)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate vp_t reports failure"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + auto const vpid{pool.allocate(tls, bsl::dontcare, VMID0, PPID0)}; + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&pool, &tls, &vpid]() { + bsl::ut_check(!pool.deallocate(tls, bsl::dontcare, vpid)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate success"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + auto const vpid{pool.allocate(tls, bsl::dontcare, VMID0, PPID0)}; + bsl::ut_then{} = [&pool, &tls, &vpid]() { + bsl::ut_check(pool.deallocate(tls, bsl::dontcare, vpid)); + }; + }; + }; + }; + + bsl::ut_scenario{"zombify invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + bsl::ut_then{} = [&pool]() { + bsl::ut_check(!pool.zombify(syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"zombify success"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + bsl::ut_then{} = [&pool]() { + bsl::ut_check(pool.zombify(VPID1)); + }; + }; + }; + + bsl::ut_scenario{"status invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_allocated(tls, syscall::BF_INVALID_ID)); + bsl::ut_check(!pool.is_deallocated(tls, syscall::BF_INVALID_ID)); + bsl::ut_check(!pool.is_zombie(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + }; + + bsl::ut_scenario{"status after initialize"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_allocated(tls, VPID0)); + bsl::ut_check(pool.is_deallocated(tls, VPID0)); + bsl::ut_check(!pool.is_zombie(tls, VPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"status after allocate"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + auto const vpid{pool.allocate(tls, bsl::dontcare, VMID0, PPID0)}; + bsl::ut_then{} = [&pool, &tls, &vpid]() { + bsl::ut_check(pool.is_allocated(tls, vpid)); + bsl::ut_check(!pool.is_deallocated(tls, vpid)); + bsl::ut_check(!pool.is_zombie(tls, vpid)); + }; + }; + }; + }; + + bsl::ut_scenario{"status after deallocate"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + auto const vpid{pool.allocate(tls, bsl::dontcare, VMID0, PPID0)}; + bsl::ut_required_step(pool.deallocate(tls, bsl::dontcare, vpid)); + bsl::ut_then{} = [&pool, &tls, &vpid]() { + bsl::ut_check(!pool.is_allocated(tls, vpid)); + bsl::ut_check(pool.is_deallocated(tls, vpid)); + bsl::ut_check(!pool.is_zombie(tls, vpid)); + }; + }; + }; + }; + + bsl::ut_scenario{"status after zombify"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_required_step(pool.zombify(VPID1)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_allocated(tls, VPID1)); + bsl::ut_check(!pool.is_deallocated(tls, VPID1)); + bsl::ut_check(pool.is_zombie(tls, VPID1)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_assigned_to_vm invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_assigned_to_vm(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"is_assigned_to_vm id with error code"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_assigned_to_vm(tls, bsl::safe_uint16::failure())); + }; + }; + }; + + bsl::ut_scenario{"is_assigned_to_vm without initialize"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_assigned_to_vm(tls, VMID0)); + }; + }; + }; + + bsl::ut_scenario{"is_assigned_to_vm nothing assigned"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_assigned_to_vm(tls, VMID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_assigned_to_vm assigned"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_required_step(pool.allocate(tls, bsl::dontcare, VMID0, PPID0)); + bsl::ut_required_step(pool.allocate(tls, bsl::dontcare, VMID0, PPID0)); + bsl::ut_required_step(pool.deallocate(tls, bsl::dontcare, VPID0)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.is_assigned_to_vm(tls, VMID0) == VPID1); + }; + }; + }; + }; + + bsl::ut_scenario{"is_assigned_to_vm assigned but wrong query"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_required_step(pool.allocate(tls, bsl::dontcare, VMID0, PPID0)); + bsl::ut_required_step(pool.allocate(tls, bsl::dontcare, VMID0, PPID0)); + bsl::ut_required_step(pool.deallocate(tls, bsl::dontcare, VPID0)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_assigned_to_vm(tls, VMID1)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.set_active(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"set_active vp_t reports failure"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.set_active(tls, VPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active success"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.set_active(tls, VPID0)); + }; + }; + }; + + bsl::ut_scenario{"set_inactive invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.set_inactive(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"set_inactive vp_t reports failure"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.set_inactive(tls, VPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive success"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.set_inactive(tls, VPID0)); + }; + }; + }; + + bsl::ut_scenario{"is_active invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"is_active success"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active(tls, VPID0)); + }; + + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_check(pool.set_active(tls, VPID0)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.is_active(tls, VPID0)); + }; + }; + + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_check(pool.set_inactive(tls, VPID0)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active(tls, VPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active_on_current_pp(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp success"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active_on_current_pp(tls, VPID0)); + }; + + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_check(pool.set_active(tls, VPID0)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.is_active_on_current_pp(tls, VPID0)); + }; + }; + + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_check(pool.set_inactive(tls, VPID0)); + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.is_active_on_current_pp(tls, VPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"migrate invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.migrate(tls, PPID0, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"migrate vp_t reports failure"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + tls.test_ret = bsl::errc_failure; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(!pool.migrate(tls, PPID0, VPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"migrate success"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + bsl::ut_check(pool.migrate(tls, PPID0, VPID0)); + }; + }; + }; + + bsl::ut_scenario{"assigned_vm invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_then{} = [&pool]() { + bsl::ut_check(!pool.assigned_vm(syscall::BF_INVALID_ID)); + }; + }; + }; + }; + + bsl::ut_scenario{"assigned_vm unassigned"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_then{} = [&pool]() { + bsl::ut_check(!pool.assigned_vm(VPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"assigned_vm success"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_required_step(pool.allocate(tls, bsl::dontcare, VMID0, PPID0)); + bsl::ut_then{} = [&pool]() { + bsl::ut_check(pool.assigned_vm(VPID0) == VMID0); + }; + }; + }; + }; + + bsl::ut_scenario{"assigned_pp invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_then{} = [&pool]() { + bsl::ut_check(!pool.assigned_pp(syscall::BF_INVALID_ID)); + }; + }; + }; + }; + + bsl::ut_scenario{"assigned_pp unassigned"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_then{} = [&pool]() { + bsl::ut_check(!pool.assigned_pp(VPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"assigned_pp success"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_when{} = [&pool, &tls]() { + bsl::ut_required_step(pool.initialize(tls, bsl::dontcare)); + bsl::ut_required_step(pool.allocate(tls, bsl::dontcare, VMID0, PPID0)); + bsl::ut_then{} = [&pool]() { + bsl::ut_check(pool.assigned_pp(VPID0) == PPID0); + }; + }; + }; + }; + + bsl::ut_scenario{"dump invalid id"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + pool.dump(tls, syscall::BF_INVALID_ID); + }; + }; + }; + + bsl::ut_scenario{"dump success"} = []() { + bsl::ut_given{} = []() { + vp_pool_t pool{}; + tls_t tls{}; + bsl::ut_then{} = [&pool, &tls]() { + pool.dump(tls, VPID0); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + mk::yield(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/vp_pool_t/requirements.cpp b/kernel/test/vp_pool_t/requirements.cpp new file mode 100644 index 00000000..52df6f08 --- /dev/null +++ b/kernel/test/vp_pool_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vp_pool_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/vp_t/CMakeLists.txt b/kernel/test/vp_t/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/vp_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/vp_t/behavior.cpp b/kernel/test/vp_t/behavior.cpp new file mode 100644 index 00000000..6c4b8249 --- /dev/null +++ b/kernel/test/vp_t/behavior.cpp @@ -0,0 +1,1282 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vp_t.hpp" + +#include +#include +#include + +#include + +namespace mk +{ + /// @brief defines the max number of VMs used in testing + constexpr bsl::safe_uint16 INTEGRATION_MAX_PPS{bsl::to_u16(2)}; + + /// @brief defines VMID0 + constexpr bsl::safe_uint16 VMID0{bsl::to_u16(0)}; + + /// @brief defines PPID0 + constexpr bsl::safe_uint16 PPID0{bsl::to_u16(0)}; + /// @brief defines PPID1 + constexpr bsl::safe_uint16 PPID1{bsl::to_u16(1)}; + /// @brief defines PPID2 + constexpr bsl::safe_uint16 PPID2{bsl::to_u16(2)}; + + /// @brief defines VPID0 + constexpr bsl::safe_uint16 VPID0{bsl::to_u16(0)}; + /// @brief defines VPID1 + constexpr bsl::safe_uint16 VPID1{bsl::to_u16(1)}; + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize invalid id version #1"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_then{} = [&vp, &tls]() { + bsl::ut_check(!vp.initialize(tls, bsl::safe_uint16::failure())); + }; + }; + }; + + bsl::ut_scenario{"initialize invalid id version #2"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_then{} = [&vp, &tls]() { + bsl::ut_check(!vp.initialize(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_then{} = [&vp, &tls]() { + bsl::ut_check(vp.initialize(tls, VPID0)); + }; + }; + }; + + bsl::ut_scenario{"initialize more than once failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&vp, &tls]() { + bsl::ut_required_step(vp.initialize(tls, VPID0)); + bsl::ut_then{} = [&vp, &tls]() { + bsl::ut_check(!vp.initialize(tls, VPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"release success"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_when{} = [&vp, &tls, &vps_pool]() { + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&vp, &tls, &vps_pool]() { + bsl::ut_check(vp.release(tls, vps_pool)); + bsl::ut_check(!vp.id()); + }; + }; + }; + }; + + bsl::ut_scenario{"release success after allocate"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool, &vps_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&vp, &tls, &vps_pool]() { + bsl::ut_check(vp.release(tls, vps_pool)); + bsl::ut_check(!vp.id()); + bsl::ut_check(!vp.is_allocated()); + bsl::ut_check(!vp.assigned_vm()); + bsl::ut_check(!vp.assigned_pp()); + }; + }; + }; + }; + + bsl::ut_scenario{"release of a zombie vp is ignored"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_when{} = [&vp, &tls, &vps_pool]() { + bsl::ut_required_step(vp.initialize(tls, VPID1)); + vp.zombify(); + bsl::ut_then{} = [&vp, &tls, &vps_pool]() { + bsl::ut_check(vp.release(tls, vps_pool)); + bsl::ut_check(vp.id()); + bsl::ut_check(vp.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"release of a vp that is still assigned results in a zombie"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_when{} = [&vp, &tls, &vps_pool]() { + bsl::ut_required_step(vp.initialize(tls, VPID1)); + tls.test_ret = errc_vps_pool_failure; + bsl::ut_then{} = [&vp, &tls, &vps_pool]() { + bsl::ut_check(!vp.release(tls, vps_pool)); + bsl::ut_check(vp.id()); + bsl::ut_check(vp.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"release of a vp that is still active results in a zombie"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool, &vps_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + bsl::ut_then{} = [&vp, &tls, &vps_pool]() { + bsl::ut_check(!vp.release(tls, vps_pool)); + bsl::ut_check(vp.id()); + bsl::ut_check(vp.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate without initialize failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_then{} = [&vp, &tls, &vm_pool]() { + bsl::ut_check(!vp.allocate(tls, vm_pool, VMID0, PPID0)); + }; + }; + }; + + bsl::ut_scenario{"allocate invalid vmid version #1"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&vp, &tls, &vm_pool]() { + bsl::ut_check( + !vp.allocate(tls, vm_pool, bsl::safe_uint16::failure(), PPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid vmid version #2"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&vp, &tls, &vm_pool]() { + bsl::ut_check(!vp.allocate(tls, vm_pool, syscall::BF_INVALID_ID, PPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid vmid version #3"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + tls.test_ret = errc_vm_is_zombie_failure; + bsl::ut_then{} = [&vp, &tls, &vm_pool]() { + bsl::ut_check(!vp.allocate(tls, vm_pool, VMID0, PPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid vmid version #4"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + tls.test_ret = errc_vm_is_deallocated_failure; + bsl::ut_then{} = [&vp, &tls, &vm_pool]() { + bsl::ut_check(!vp.allocate(tls, vm_pool, VMID0, PPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid ppid version #1"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&vp, &tls, &vm_pool]() { + bsl::ut_check( + !vp.allocate(tls, vm_pool, VMID0, bsl::safe_uint16::failure())); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid ppid version #2"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&vp, &tls, &vm_pool]() { + bsl::ut_check(!vp.allocate(tls, vm_pool, VMID0, syscall::BF_INVALID_ID)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate invalid ppid version #3"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = {}; + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&vp, &tls, &vm_pool]() { + bsl::ut_check(!vp.allocate(tls, vm_pool, VMID0, PPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate zombie failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + vp.zombify(); + bsl::ut_then{} = [&vp, &tls, &vm_pool]() { + bsl::ut_check(!vp.allocate(tls, vm_pool, VMID0, PPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"allocate more than once failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID0)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&vp, &tls, &vm_pool]() { + bsl::ut_check(!vp.allocate(tls, vm_pool, VMID0, PPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate not initialized failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_then{} = [&vp, &tls, &vps_pool]() { + bsl::ut_check(!vp.deallocate(tls, vps_pool)); + }; + }; + }; + + bsl::ut_scenario{"deallocate zombie failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool, &vps_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + vp.zombify(); + bsl::ut_then{} = [&vp, &tls, &vps_pool]() { + bsl::ut_check(!vp.deallocate(tls, vps_pool)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate already deallocated failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool, &vps_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.deallocate(tls, vps_pool)); + bsl::ut_then{} = [&vp, &tls, &vps_pool]() { + bsl::ut_check(!vp.deallocate(tls, vps_pool)); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate assigned failure results in zombie"} = []() { + bsl::ut_given{} = []() { + dummy_vm_pool_t vm_pool{}; + vp_t vp{}; + tls_t tls{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool, &vps_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + tls.test_ret = errc_vps_pool_failure; + bsl::ut_then{} = [&vp, &tls, &vps_pool]() { + bsl::ut_check(!vp.deallocate(tls, vps_pool)); + bsl::ut_check(vp.is_zombie()); + bsl::ut_check(tls.state_reversal_required); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate still active failure results in zombie"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool, &vps_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + bsl::ut_then{} = [&vp, &tls, &vps_pool]() { + bsl::ut_check(!vp.deallocate(tls, vps_pool)); + bsl::ut_check(vp.is_zombie()); + bsl::ut_check(tls.state_reversal_required); + }; + }; + }; + }; + + bsl::ut_scenario{"deallocate success"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool, &vps_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&vp, &tls, &vps_pool]() { + bsl::ut_check(vp.deallocate(tls, vps_pool)); + bsl::ut_check(tls.state_reversal_required); + }; + }; + }; + }; + + bsl::ut_scenario{"zombify without initialize success"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + bsl::ut_when{} = [&vp]() { + vp.zombify(); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(!vp.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"zombify success"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&vp, &tls]() { + bsl::ut_required_step(vp.initialize(tls, VPID1)); + vp.zombify(); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(vp.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"zombify more than once is ignored"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&vp, &tls]() { + bsl::ut_required_step(vp.initialize(tls, VPID1)); + vp.zombify(); + vp.zombify(); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(vp.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"status without initialize"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + bsl::ut_then{} = [&vp]() { + bsl::ut_check(vp.is_deallocated()); + bsl::ut_check(!vp.is_allocated()); + bsl::ut_check(!vp.is_zombie()); + }; + }; + }; + + bsl::ut_scenario{"status after initialize"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&vp, &tls]() { + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(vp.is_deallocated()); + bsl::ut_check(!vp.is_allocated()); + bsl::ut_check(!vp.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"status after allocation"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(!vp.is_deallocated()); + bsl::ut_check(vp.is_allocated()); + bsl::ut_check(!vp.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"status after deallocation"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + dummy_vps_pool_t vps_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool, &vps_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.deallocate(tls, vps_pool)); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(vp.is_deallocated()); + bsl::ut_check(!vp.is_allocated()); + bsl::ut_check(!vp.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"status after zombify"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&vp, &tls]() { + bsl::ut_required_step(vp.initialize(tls, VPID1)); + vp.zombify(); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(!vp.is_deallocated()); + bsl::ut_check(!vp.is_allocated()); + bsl::ut_check(vp.is_zombie()); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active without initialize failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_active(tls)); + }; + }; + }; + + bsl::ut_scenario{"set_active without allocate failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&tls, &vp]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active zombie failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + vp.zombify(); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active already active"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active corrupt already active"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active another vp is active failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = VPID0.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active invalid active_vmid failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + tls.active_vmid = syscall::BF_INVALID_ID.get(); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active invalid ppid failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + tls.ppid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_active success"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(vp.set_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive without initialize failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_inactive(tls)); + }; + }; + }; + + bsl::ut_scenario{"set_inactive without activate failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&tls, &vp]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive zombie is allowed"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + vp.zombify(); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(vp.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive already inactive"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive active vp is not this vp"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + tls.active_vpid = VPID0.get(); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive invalid ppid failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + tls.ppid = syscall::BF_INVALID_ID.get(); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive more than once failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + bsl::ut_required_step(vp.set_inactive(tls)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive corrupt active vp"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + bsl::ut_required_step(vp.set_inactive(tls)); + tls.active_vpid = VPID1.get(); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"set_inactive success"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(vp.set_inactive(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active reports true"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(vp.is_active(tls) == tls.ppid); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active reports false"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.is_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active reports false with corrupt online_pps"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = syscall::BF_INVALID_ID.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.is_active(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp reports true"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(vp.is_active_on_current_pp(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp reports false"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.is_active_on_current_pp(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp reports false with corrupt online_pps"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = syscall::BF_INVALID_ID.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.is_active_on_current_pp(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"is_active_on_current_pp reports false with corrupt online_pps"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = syscall::BF_INVALID_ID.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.is_active_on_current_pp(tls)); + }; + }; + }; + }; + + bsl::ut_scenario{"migrate without initialize failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&tls, &vp]() { + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.migrate(tls, PPID1)); + }; + }; + }; + }; + + bsl::ut_scenario{"migrate without allocate failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&tls, &vp]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.migrate(tls, PPID1)); + }; + }; + }; + }; + + bsl::ut_scenario{"migrate invalid ppid failure version #1"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.migrate(tls, bsl::safe_uint16::failure())); + }; + }; + }; + }; + + bsl::ut_scenario{"migrate invalid ppid failure version #2"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.migrate(tls, syscall::BF_INVALID_ID)); + }; + }; + }; + }; + + bsl::ut_scenario{"migrate invalid ppid failure version #3"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.migrate(tls, PPID2)); + }; + }; + }; + }; + + bsl::ut_scenario{"migrate already assigned to ppid failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.migrate(tls, PPID0)); + }; + }; + }; + }; + + bsl::ut_scenario{"migrate active failure"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(!vp.migrate(tls, PPID1)); + }; + }; + }; + }; + + bsl::ut_scenario{"migrate success"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + bsl::ut_check(vp.migrate(tls, PPID1)); + }; + }; + }; + }; + + bsl::ut_scenario{"assigned_vm without allocation"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&vp, &tls]() { + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(!vp.assigned_vm()); + }; + }; + }; + }; + + bsl::ut_scenario{"assigned_vm after allocation"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(vp.assigned_vm() == VMID0); + }; + }; + }; + }; + + bsl::ut_scenario{"assigned_pp without allocation"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&vp, &tls]() { + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(!vp.assigned_pp()); + }; + }; + }; + }; + + bsl::ut_scenario{"assigned_pp after allocation"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(vp.assigned_pp() == PPID0); + }; + }; + }; + }; + + bsl::ut_scenario{"assigned_pp after migration"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.migrate(tls, PPID1)); + bsl::ut_then{} = [&vp]() { + bsl::ut_check(vp.assigned_pp() == PPID1); + }; + }; + }; + }; + + bsl::ut_scenario{"dump without initialize"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_then{} = [&tls, &vp]() { + vp.dump(tls); + }; + }; + }; + + bsl::ut_scenario{"dump with initialize"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + bsl::ut_when{} = [&tls, &vp]() { + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_then{} = [&tls, &vp]() { + vp.dump(tls); + }; + }; + }; + }; + + bsl::ut_scenario{"dump with allocate"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_then{} = [&tls, &vp]() { + vp.dump(tls); + }; + }; + }; + }; + + bsl::ut_scenario{"dump with active"} = []() { + bsl::ut_given{} = []() { + vp_t vp{}; + tls_t tls{}; + dummy_vm_pool_t vm_pool{}; + bsl::ut_when{} = [&vp, &tls, &vm_pool]() { + tls.online_pps = INTEGRATION_MAX_PPS.get(); + tls.active_vpid = syscall::BF_INVALID_ID.get(); + bsl::ut_required_step(vp.initialize(tls, VPID1)); + bsl::ut_required_step(vp.allocate(tls, vm_pool, VMID0, PPID0)); + bsl::ut_required_step(vp.set_active(tls)); + bsl::ut_then{} = [&tls, &vp]() { + vp.dump(tls); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/vp_t/requirements.cpp b/kernel/test/vp_t/requirements.cpp new file mode 100644 index 00000000..2b433e3c --- /dev/null +++ b/kernel/test/vp_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vp_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/vps_pool_t/CMakeLists.txt b/kernel/test/vps_pool_t/CMakeLists.txt new file mode 100644 index 00000000..ebf2071b --- /dev/null +++ b/kernel/test/vps_pool_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${COMMON_INCLUDES} SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/kernel/test/vps_pool_t/behavior.cpp b/kernel/test/vps_pool_t/behavior.cpp new file mode 100644 index 00000000..61482cb9 --- /dev/null +++ b/kernel/test/vps_pool_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vps_pool_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/vps_pool_t/requirements.cpp b/kernel/test/vps_pool_t/requirements.cpp new file mode 100644 index 00000000..fbe5c13b --- /dev/null +++ b/kernel/test/vps_pool_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../src/vps_pool_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/x64/amd/dispatch_esr_nmi/CMakeLists.txt b/kernel/test/x64/amd/dispatch_esr_nmi/CMakeLists.txt new file mode 100644 index 00000000..cb793e42 --- /dev/null +++ b/kernel/test/x64/amd/dispatch_esr_nmi/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) +bf_add_test(behavior INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) diff --git a/kernel/test/x64/amd/dispatch_esr_nmi/behavior.cpp b/kernel/test/x64/amd/dispatch_esr_nmi/behavior.cpp new file mode 100644 index 00000000..3c1578ff --- /dev/null +++ b/kernel/test/x64/amd/dispatch_esr_nmi/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/amd/dispatch_esr_nmi.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/x64/amd/dispatch_esr_nmi/requirements.cpp b/kernel/test/x64/amd/dispatch_esr_nmi/requirements.cpp new file mode 100644 index 00000000..2f4c7e09 --- /dev/null +++ b/kernel/test/x64/amd/dispatch_esr_nmi/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/amd/dispatch_esr_nmi.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/x64/amd/dispatch_syscall_intrinsic_op/CMakeLists.txt b/kernel/test/x64/amd/dispatch_syscall_intrinsic_op/CMakeLists.txt new file mode 100644 index 00000000..cb793e42 --- /dev/null +++ b/kernel/test/x64/amd/dispatch_syscall_intrinsic_op/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) +bf_add_test(behavior INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) diff --git a/kernel/test/x64/amd/dispatch_syscall_intrinsic_op/behavior.cpp b/kernel/test/x64/amd/dispatch_syscall_intrinsic_op/behavior.cpp new file mode 100644 index 00000000..1c1f0147 --- /dev/null +++ b/kernel/test/x64/amd/dispatch_syscall_intrinsic_op/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/x64/amd/dispatch_syscall_intrinsic_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/x64/amd/dispatch_syscall_intrinsic_op/requirements.cpp b/kernel/test/x64/amd/dispatch_syscall_intrinsic_op/requirements.cpp new file mode 100644 index 00000000..ad9d7412 --- /dev/null +++ b/kernel/test/x64/amd/dispatch_syscall_intrinsic_op/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/x64/amd/dispatch_syscall_intrinsic_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/x64/amd/intrinsic_t/CMakeLists.txt b/kernel/test/x64/amd/intrinsic_t/CMakeLists.txt new file mode 100644 index 00000000..cb793e42 --- /dev/null +++ b/kernel/test/x64/amd/intrinsic_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) +bf_add_test(behavior INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) diff --git a/kernel/test/x64/amd/intrinsic_t/behavior.cpp b/kernel/test/x64/amd/intrinsic_t/behavior.cpp new file mode 100644 index 00000000..29fbd14f --- /dev/null +++ b/kernel/test/x64/amd/intrinsic_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/amd/intrinsic_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/x64/amd/intrinsic_t/requirements.cpp b/kernel/test/x64/amd/intrinsic_t/requirements.cpp new file mode 100644 index 00000000..ef13d17e --- /dev/null +++ b/kernel/test/x64/amd/intrinsic_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/amd/intrinsic_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/x64/amd/vps_t/CMakeLists.txt b/kernel/test/x64/amd/vps_t/CMakeLists.txt new file mode 100644 index 00000000..cb793e42 --- /dev/null +++ b/kernel/test/x64/amd/vps_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) +bf_add_test(behavior INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) diff --git a/kernel/test/x64/amd/vps_t/behavior.cpp b/kernel/test/x64/amd/vps_t/behavior.cpp new file mode 100644 index 00000000..29fbd14f --- /dev/null +++ b/kernel/test/x64/amd/vps_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/amd/intrinsic_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/x64/amd/vps_t/requirements.cpp b/kernel/test/x64/amd/vps_t/requirements.cpp new file mode 100644 index 00000000..ef13d17e --- /dev/null +++ b/kernel/test/x64/amd/vps_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/amd/intrinsic_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/x64/dispatch_esr/CMakeLists.txt b/kernel/test/x64/dispatch_esr/CMakeLists.txt new file mode 100644 index 00000000..4fc4e188 --- /dev/null +++ b/kernel/test/x64/dispatch_esr/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${X64_INCLUDES} SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} DEFINES ${X64_DEFINES}) +bf_add_test(behavior INCLUDES ${X64_INCLUDES} SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} DEFINES ${X64_DEFINES}) diff --git a/kernel/test/x64/dispatch_esr/behavior.cpp b/kernel/test/x64/dispatch_esr/behavior.cpp new file mode 100644 index 00000000..7fee6d90 --- /dev/null +++ b/kernel/test/x64/dispatch_esr/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/x64/dispatch_esr.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/x64/dispatch_esr/requirements.cpp b/kernel/test/x64/dispatch_esr/requirements.cpp new file mode 100644 index 00000000..39051eda --- /dev/null +++ b/kernel/test/x64/dispatch_esr/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/x64/dispatch_esr.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/x64/intel/dispatch_esr_nmi/CMakeLists.txt b/kernel/test/x64/intel/dispatch_esr_nmi/CMakeLists.txt new file mode 100644 index 00000000..7f4d07b0 --- /dev/null +++ b/kernel/test/x64/intel/dispatch_esr_nmi/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) +bf_add_test(behavior INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) diff --git a/kernel/test/x64/intel/dispatch_esr_nmi/behavior.cpp b/kernel/test/x64/intel/dispatch_esr_nmi/behavior.cpp new file mode 100644 index 00000000..38f8093c --- /dev/null +++ b/kernel/test/x64/intel/dispatch_esr_nmi/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/intel/dispatch_esr_nmi.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/x64/intel/dispatch_esr_nmi/requirements.cpp b/kernel/test/x64/intel/dispatch_esr_nmi/requirements.cpp new file mode 100644 index 00000000..e1d95b81 --- /dev/null +++ b/kernel/test/x64/intel/dispatch_esr_nmi/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/intel/dispatch_esr_nmi.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/x64/intel/dispatch_syscall_intrinsic_op/CMakeLists.txt b/kernel/test/x64/intel/dispatch_syscall_intrinsic_op/CMakeLists.txt new file mode 100644 index 00000000..7f4d07b0 --- /dev/null +++ b/kernel/test/x64/intel/dispatch_syscall_intrinsic_op/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) +bf_add_test(behavior INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) diff --git a/kernel/test/x64/intel/dispatch_syscall_intrinsic_op/behavior.cpp b/kernel/test/x64/intel/dispatch_syscall_intrinsic_op/behavior.cpp new file mode 100644 index 00000000..28c5eee1 --- /dev/null +++ b/kernel/test/x64/intel/dispatch_syscall_intrinsic_op/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/x64/intel/dispatch_syscall_intrinsic_op.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/x64/intel/dispatch_syscall_intrinsic_op/requirements.cpp b/kernel/test/x64/intel/dispatch_syscall_intrinsic_op/requirements.cpp new file mode 100644 index 00000000..031708e7 --- /dev/null +++ b/kernel/test/x64/intel/dispatch_syscall_intrinsic_op/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/x64/intel/dispatch_syscall_intrinsic_op.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/x64/intel/intrinsic_t/CMakeLists.txt b/kernel/test/x64/intel/intrinsic_t/CMakeLists.txt new file mode 100644 index 00000000..7f4d07b0 --- /dev/null +++ b/kernel/test/x64/intel/intrinsic_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) +bf_add_test(behavior INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) diff --git a/kernel/test/x64/intel/intrinsic_t/behavior.cpp b/kernel/test/x64/intel/intrinsic_t/behavior.cpp new file mode 100644 index 00000000..8a91c354 --- /dev/null +++ b/kernel/test/x64/intel/intrinsic_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/intel/intrinsic_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/x64/intel/intrinsic_t/requirements.cpp b/kernel/test/x64/intel/intrinsic_t/requirements.cpp new file mode 100644 index 00000000..f5c48a72 --- /dev/null +++ b/kernel/test/x64/intel/intrinsic_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/intel/intrinsic_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/x64/intel/vps_t/CMakeLists.txt b/kernel/test/x64/intel/vps_t/CMakeLists.txt new file mode 100644 index 00000000..7f4d07b0 --- /dev/null +++ b/kernel/test/x64/intel/vps_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) +bf_add_test(behavior INCLUDES ${INTEL_INCLUDES} SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} DEFINES ${INTEL_DEFINES}) diff --git a/kernel/test/x64/intel/vps_t/behavior.cpp b/kernel/test/x64/intel/vps_t/behavior.cpp new file mode 100644 index 00000000..8a91c354 --- /dev/null +++ b/kernel/test/x64/intel/vps_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/intel/intrinsic_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/x64/intel/vps_t/requirements.cpp b/kernel/test/x64/intel/vps_t/requirements.cpp new file mode 100644 index 00000000..f5c48a72 --- /dev/null +++ b/kernel/test/x64/intel/vps_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/x64/intel/intrinsic_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/x64/root_page_table_t/CMakeLists.txt b/kernel/test/x64/root_page_table_t/CMakeLists.txt new file mode 100644 index 00000000..4fc4e188 --- /dev/null +++ b/kernel/test/x64/root_page_table_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${X64_INCLUDES} SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} DEFINES ${X64_DEFINES}) +bf_add_test(behavior INCLUDES ${X64_INCLUDES} SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} DEFINES ${X64_DEFINES}) diff --git a/kernel/test/x64/root_page_table_t/behavior.cpp b/kernel/test/x64/root_page_table_t/behavior.cpp new file mode 100644 index 00000000..61f849ad --- /dev/null +++ b/kernel/test/x64/root_page_table_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/x64/root_page_table_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/x64/root_page_table_t/requirements.cpp b/kernel/test/x64/root_page_table_t/requirements.cpp new file mode 100644 index 00000000..f80dedbb --- /dev/null +++ b/kernel/test/x64/root_page_table_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/x64/root_page_table_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/kernel/test/x64/vmexit_log_t/CMakeLists.txt b/kernel/test/x64/vmexit_log_t/CMakeLists.txt new file mode 100644 index 00000000..cb793e42 --- /dev/null +++ b/kernel/test/x64/vmexit_log_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) +bf_add_test(behavior INCLUDES ${AMD_INCLUDES} SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} DEFINES ${AMD_DEFINES}) diff --git a/kernel/test/x64/vmexit_log_t/behavior.cpp b/kernel/test/x64/vmexit_log_t/behavior.cpp new file mode 100644 index 00000000..27fdaffa --- /dev/null +++ b/kernel/test/x64/vmexit_log_t/behavior.cpp @@ -0,0 +1,62 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/x64/vmexit_log_t.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/kernel/test/x64/vmexit_log_t/requirements.cpp b/kernel/test/x64/vmexit_log_t/requirements.cpp new file mode 100644 index 00000000..3aed8d5b --- /dev/null +++ b/kernel/test/x64/vmexit_log_t/requirements.cpp @@ -0,0 +1,42 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../src/x64/vmexit_log_t.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 883a5026..9281bc52 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -21,13 +21,35 @@ add_library(loader INTERFACE) +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + target_include_directories(loader SYSTEM INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include/interface/cpp - ${CMAKE_CURRENT_LIST_DIR}/include/interface/cpp/x64 - ${CMAKE_CURRENT_LIST_DIR}/include/interface/cpp/bfelf $<$:${CMAKE_CURRENT_LIST_DIR}/linux/include> $<$:${CMAKE_CURRENT_LIST_DIR}/linux/include/platform_interface/cpp> $<$:${CMAKE_CURRENT_LIST_DIR}/windows/include> $<$:${CMAKE_CURRENT_LIST_DIR}/windows/include/platform_interface/cpp> ) + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + target_include_directories(loader SYSTEM INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/include/interface/cpp/x64 + ) +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + target_include_directories(loader SYSTEM INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/include/interface/cpp/arm/aarch64 + ) +endif() + +# ------------------------------------------------------------------------------ +# Sub Directories +# ------------------------------------------------------------------------------ + +if(HYPERVISOR_BUILD_EFI) + hypervisor_add_efi_cross_compile(../cmake/efi_cross_compile) +endif() diff --git a/loader/efi/CMakeLists.txt b/loader/efi/CMakeLists.txt index a85ff6f5..7ae89393 100644 --- a/loader/efi/CMakeLists.txt +++ b/loader/efi/CMakeLists.txt @@ -19,22 +19,68 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -include(${CMAKE_CURRENT_LIST_DIR}/../../cmake/function/hypervisor_add_header_depends.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../../cmake/function/hypervisor_target_source.cmake) add_executable(bareflank_efi_loader) +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + target_include_directories(bareflank_efi_loader PUBLIC include include/std include/platform_interface/c ../include ../include/interface/c - ../include/interface/c/bfelf ${CMAKE_BINARY_DIR}/include ) +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + target_include_directories(bareflank_efi_loader PUBLIC + include/x64 + ../include/x64/ + ../include/interface/c/x64 + ) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") + target_include_directories(bareflank_efi_loader PUBLIC + include/x64/amd + ../include/x64/amd + ../include/interface/c/x64/amd + ) + endif() + + if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + target_include_directories(bareflank_efi_loader PUBLIC + include/x64/intel + ../include/x64/intel + ../include/interface/c/x64/intel + ) + endif() +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + target_include_directories(bareflank_efi_loader PUBLIC + include/arm/aarch64 + ../include/arm/aarch64 + ../include/interface/c/arm/aarch64 + ) +endif() + +# ------------------------------------------------------------------------------ +# Headers +# ------------------------------------------------------------------------------ + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/include/arch_init.h + ${CMAKE_CURRENT_LIST_DIR}/include/arch_locate_protocols.h + ${CMAKE_CURRENT_LIST_DIR}/include/arch_num_online_cpus.h + ${CMAKE_CURRENT_LIST_DIR}/include/arch_work_on_cpu.h ${CMAKE_CURRENT_LIST_DIR}/include/debug.h + ${CMAKE_CURRENT_LIST_DIR}/include/types.h + ${CMAKE_CURRENT_LIST_DIR}/include/work_on_cpu_callback_args.h + ${CMAKE_CURRENT_LIST_DIR}/include/work_on_cpu_callback.h ${CMAKE_CURRENT_LIST_DIR}/include/efi/efi_allocate_type.h ${CMAKE_CURRENT_LIST_DIR}/include/efi/efi_boot_services.h ${CMAKE_CURRENT_LIST_DIR}/include/efi/efi_configuration_table.h @@ -64,121 +110,140 @@ list(APPEND HEADERS ${CMAKE_CURRENT_LIST_DIR}/include/efi/efi_timer_delay.h ${CMAKE_CURRENT_LIST_DIR}/include/efi/efi_types.h ${CMAKE_CURRENT_LIST_DIR}/include/efi/extened_processor_information.h - ${CMAKE_CURRENT_LIST_DIR}/include/types.h - ${CMAKE_CURRENT_LIST_DIR}/include/work_on_cpu_callback_args.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/bfelf/bfelf_elf64_ehdr_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/bfelf/bfelf_elf64_phdr_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/bfelf/bfelf_types.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/debug_ring_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/dump_vmm_args_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/mutable_span_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/span_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/start_vmm_args_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/stop_vmm_args_t.h ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_and_copy_ext_elf_files_from_user.h + ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_and_copy_mk_code_aliases.h ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_and_copy_mk_elf_file_from_user.h ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_and_copy_mk_elf_segments.h + ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_and_copy_mk_state.h + ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_and_copy_root_vp_state.h ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_mk_args.h ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_mk_debug_ring.h ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_mk_huge_pool.h ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_mk_page_pool.h + ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_mk_root_page_table.h ${CMAKE_CURRENT_LIST_DIR}/../include/alloc_mk_stack.h + ${CMAKE_CURRENT_LIST_DIR}/../include/check_cpu_configuration.h + ${CMAKE_CURRENT_LIST_DIR}/../include/demote.h ${CMAKE_CURRENT_LIST_DIR}/../include/dump_ext_elf_files.h ${CMAKE_CURRENT_LIST_DIR}/../include/dump_mk_args.h + ${CMAKE_CURRENT_LIST_DIR}/../include/dump_mk_code_aliases.h ${CMAKE_CURRENT_LIST_DIR}/../include/dump_mk_debug_ring.h ${CMAKE_CURRENT_LIST_DIR}/../include/dump_mk_elf_file.h ${CMAKE_CURRENT_LIST_DIR}/../include/dump_mk_elf_segments.h ${CMAKE_CURRENT_LIST_DIR}/../include/dump_mk_huge_pool.h ${CMAKE_CURRENT_LIST_DIR}/../include/dump_mk_page_pool.h + ${CMAKE_CURRENT_LIST_DIR}/../include/dump_mk_root_page_table.h ${CMAKE_CURRENT_LIST_DIR}/../include/dump_mk_stack.h + ${CMAKE_CURRENT_LIST_DIR}/../include/dump_mk_state.h + ${CMAKE_CURRENT_LIST_DIR}/../include/dump_root_vp_state.h ${CMAKE_CURRENT_LIST_DIR}/../include/dump_vmm.h + ${CMAKE_CURRENT_LIST_DIR}/../include/dump_vmm_on_error_if_needed.h ${CMAKE_CURRENT_LIST_DIR}/../include/elf_segment_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/flush_cache.h ${CMAKE_CURRENT_LIST_DIR}/../include/free_ext_elf_files.h ${CMAKE_CURRENT_LIST_DIR}/../include/free_mk_args.h + ${CMAKE_CURRENT_LIST_DIR}/../include/free_mk_code_aliases.h ${CMAKE_CURRENT_LIST_DIR}/../include/free_mk_debug_ring.h ${CMAKE_CURRENT_LIST_DIR}/../include/free_mk_elf_file.h ${CMAKE_CURRENT_LIST_DIR}/../include/free_mk_elf_segments.h ${CMAKE_CURRENT_LIST_DIR}/../include/free_mk_huge_pool.h ${CMAKE_CURRENT_LIST_DIR}/../include/free_mk_page_pool.h + ${CMAKE_CURRENT_LIST_DIR}/../include/free_mk_root_page_table.h ${CMAKE_CURRENT_LIST_DIR}/../include/free_mk_stack.h + ${CMAKE_CURRENT_LIST_DIR}/../include/free_mk_state.h + ${CMAKE_CURRENT_LIST_DIR}/../include/free_root_vp_state.h + ${CMAKE_CURRENT_LIST_DIR}/../include/g_cpu_status.h + ${CMAKE_CURRENT_LIST_DIR}/../include/get_mk_huge_pool_addr.h + ${CMAKE_CURRENT_LIST_DIR}/../include/get_mk_page_pool_addr.h ${CMAKE_CURRENT_LIST_DIR}/../include/g_ext_elf_files.h ${CMAKE_CURRENT_LIST_DIR}/../include/g_mk_args.h + ${CMAKE_CURRENT_LIST_DIR}/../include/g_mk_code_aliases.h ${CMAKE_CURRENT_LIST_DIR}/../include/g_mk_debug_ring.h ${CMAKE_CURRENT_LIST_DIR}/../include/g_mk_elf_file.h ${CMAKE_CURRENT_LIST_DIR}/../include/g_mk_elf_segments.h ${CMAKE_CURRENT_LIST_DIR}/../include/g_mk_huge_pool.h ${CMAKE_CURRENT_LIST_DIR}/../include/g_mk_page_pool.h + ${CMAKE_CURRENT_LIST_DIR}/../include/g_mk_root_page_table.h ${CMAKE_CURRENT_LIST_DIR}/../include/g_mk_stack.h + ${CMAKE_CURRENT_LIST_DIR}/../include/g_mk_state.h + ${CMAKE_CURRENT_LIST_DIR}/../include/g_root_vp_state.h + ${CMAKE_CURRENT_LIST_DIR}/../include/g_vmm_status.h ${CMAKE_CURRENT_LIST_DIR}/../include/itoa.h ${CMAKE_CURRENT_LIST_DIR}/../include/loader_fini.h ${CMAKE_CURRENT_LIST_DIR}/../include/loader_init.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_4k_page.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_4k_page_rw.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_4k_page_rx.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_ext_elf_files.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_mk_args.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_mk_code_aliases.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_mk_debug_ring.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_mk_elf_file.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_mk_elf_segments.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_mk_huge_pool.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_mk_page_pool.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_mk_stack.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_mk_state.h + ${CMAKE_CURRENT_LIST_DIR}/../include/map_root_vp_state.h + ${CMAKE_CURRENT_LIST_DIR}/../include/mutable_span_t.h ${CMAKE_CURRENT_LIST_DIR}/../include/platform.h + ${CMAKE_CURRENT_LIST_DIR}/../include/promote.h + ${CMAKE_CURRENT_LIST_DIR}/../include/send_command_report_off.h + ${CMAKE_CURRENT_LIST_DIR}/../include/send_command_report_on.h + ${CMAKE_CURRENT_LIST_DIR}/../include/send_command_stop.h + ${CMAKE_CURRENT_LIST_DIR}/../include/serial_init.h + ${CMAKE_CURRENT_LIST_DIR}/../include/serial_write_c.h + ${CMAKE_CURRENT_LIST_DIR}/../include/serial_write_hex.h + ${CMAKE_CURRENT_LIST_DIR}/../include/serial_write.h + ${CMAKE_CURRENT_LIST_DIR}/../include/span_t.h ${CMAKE_CURRENT_LIST_DIR}/../include/start_vmm.h ${CMAKE_CURRENT_LIST_DIR}/../include/start_vmm_per_cpu.h - ${CMAKE_CURRENT_LIST_DIR}/../include/static_assert.h ${CMAKE_CURRENT_LIST_DIR}/../include/stop_and_free_the_vmm.h ${CMAKE_CURRENT_LIST_DIR}/../include/stop_vmm.h ${CMAKE_CURRENT_LIST_DIR}/../include/stop_vmm_per_cpu.h - ${CMAKE_CURRENT_LIST_DIR}/../include/vmm_status.h + ${CMAKE_CURRENT_LIST_DIR}/../include/bfelf/bfelf_elf64_ehdr_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/bfelf/bfelf_elf64_phdr_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/bfelf/bfelf_types.h + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/debug_ring_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/dump_vmm_args_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/mk_args_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/start_vmm_args_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/stop_vmm_args_t.h ) if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - target_include_directories(bareflank_efi_loader PUBLIC - include/x64 - ../include/x64/ - ../include/interface/c/x64 - ) list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/include/x64/setup_cr0.h + ${CMAKE_CURRENT_LIST_DIR}/include/x64/setup_cr4.h + ${CMAKE_CURRENT_LIST_DIR}/include/x64/setup_tss.h ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/cpuid_commands.h ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/global_descriptor_table_register_t.h ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/interrupt_descriptor_table_register_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/mk_args_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/pdpte_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/pdte_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/pml4te_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/pte_t.h ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/state_save_t.h ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/tss_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/alloc_and_copy_mk_code_aliases.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/alloc_and_copy_mk_state.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/alloc_and_copy_root_vp_state.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/alloc_mk_root_page_table.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/alloc_pdpt.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/alloc_pdt.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/alloc_pt.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/check_for_hve_support.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/code_aliases_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/demote.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/disable_hve.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/dump_mk_code_aliases.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/dump_mk_root_page_table.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/dump_mk_state.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/dump_root_vp_state.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/enable_hve.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/esr_default.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/esr_df.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/esr_gpf.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/esr_nmi.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/esr_pf.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/free_mk_code_aliases.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/free_mk_root_page_table.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/free_mk_state.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/free_pdpt.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/free_pdt.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/free_pml4t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/free_root_vp_state.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/get_gdt_descriptor_attrib.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/get_gdt_descriptor_base.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/get_gdt_descriptor_limit.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/get_mk_huge_pool_addr.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/get_mk_page_pool_addr.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/g_mk_code_aliases.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/g_mk_root_page_table.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/g_mk_state.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/g_root_vp_state.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_cpuid.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_inb.h + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_lcr0.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_lcr4.h + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_lgdt.h + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_ltr.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_outb.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_rdmsr.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_scr0.h @@ -194,302 +259,281 @@ if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STRE ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_sss.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_str.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intrinsic_wrmsr.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_4k_page.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_4k_page_rw.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_4k_page_rx.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_ext_elf_files.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_mk_args.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_mk_code_aliases.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_mk_debug_ring.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_mk_elf_file.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_mk_elf_segments.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_mk_huge_pool.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_mk_page_pool.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_mk_stack.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_mk_state.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/map_root_vp_state.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pdpto.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pdpt_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pdpte_t.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pdto.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pdt_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pdte_t.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pml4to.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pml4t_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/promote.h + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pml4te_t.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pto.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pt_t.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/send_command_report_off.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/send_command_report_on.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/send_command_stop.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/serial_init.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/serial_write.h + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/pte_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/root_page_table_t.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/set_gdt_descriptor.h ${CMAKE_CURRENT_LIST_DIR}/../include/x64/set_idt_descriptor.h ) + + if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intel/intrinsic_vmxoff.h + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intel/intrinsic_vmxon.h + ) + endif() endif() -if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") - target_include_directories(bareflank_efi_loader PUBLIC - include/x64/amd - ../include/x64/amd - ../include/interface/c/x64/amd - ) -elseif(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - target_include_directories(bareflank_efi_loader PUBLIC - include/x64/intel - ../include/x64/intel - ../include/interface/c/x64/intel - ) +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") list(APPEND HEADERS - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intel/intrinsic_vmxoff.h - ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intel/intrinsic_vmxon.h + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/arm/aarch64/cpuid_commands.h + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/arm/aarch64/state_save_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/alloc_l1t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/alloc_l2t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/alloc_l3t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/code_aliases_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/free_l0t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/free_l1t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/free_l2t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l0to.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l0t_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l0te_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l1to.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l1t_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l1te_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l2to.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l2t_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l2te_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l3to.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l3t_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/l3te_t.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/read_currentel.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/read_daif.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/read_hcr_el2.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/read_mair_el2.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/read_sctlr_el2.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/read_spsel.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/read_tcr_el2.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/read_ttbr0_el2.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/read_vbar_el2.h + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64/root_page_table_t.h ) -else() - message(FATAL_ERROR "Unsupported HYPERVISOR_TARGET_ARCH: ${HYPERVISOR_TARGET_ARCH}") endif() -target_sources(bareflank_efi_loader PUBLIC - src/platform.c - src/entry.c - ../src/alloc_and_copy_ext_elf_files_from_user.c - ../src/alloc_and_copy_mk_elf_file_from_user.c - ../src/alloc_and_copy_mk_elf_segments.c - ../src/alloc_mk_args.c - ../src/alloc_mk_debug_ring.c - ../src/alloc_mk_huge_pool.c - ../src/alloc_mk_page_pool.c - ../src/alloc_mk_stack.c - ../src/dump_ext_elf_files.c - ../src/dump_mk_args.c - ../src/dump_mk_debug_ring.c - ../src/dump_mk_elf_file.c - ../src/dump_mk_elf_segments.c - ../src/dump_mk_huge_pool.c - ../src/dump_mk_page_pool.c - ../src/dump_mk_stack.c - ../src/dump_vmm.c - ../src/free_ext_elf_files.c - ../src/free_mk_args.c - ../src/free_mk_debug_ring.c - ../src/free_mk_elf_file.c - ../src/free_mk_elf_segments.c - ../src/free_mk_huge_pool.c - ../src/free_mk_page_pool.c - ../src/free_mk_stack.c - ../src/g_ext_elf_files.c - ../src/g_mk_args.c - ../src/g_mk_debug_ring.c - ../src/g_mk_elf_file.c - ../src/g_mk_elf_segments.c - ../src/g_mk_huge_pool.c - ../src/g_mk_page_pool.c - ../src/g_mk_stack.c - ../src/loader_fini.c - ../src/loader_init.c - ../src/start_vmm_per_cpu.c - ../src/start_vmm.c - ../src/stop_and_free_the_vmm.c - ../src/stop_vmm_per_cpu.c - ../src/stop_vmm.c - ../src/vmm_status.c -) +# ------------------------------------------------------------------------------ +# Sources +# ------------------------------------------------------------------------------ -hypervisor_add_header_depends(src/platform.c ${HEADERS}) -hypervisor_add_header_depends(src/entry.c ${HEADERS}) -hypervisor_add_header_depends(../src/alloc_and_copy_ext_elf_files_from_user.c ${HEADERS}) -hypervisor_add_header_depends(../src/alloc_and_copy_mk_elf_file_from_user.c ${HEADERS}) -hypervisor_add_header_depends(../src/alloc_and_copy_mk_elf_segments.c ${HEADERS}) -hypervisor_add_header_depends(../src/alloc_mk_args.c ${HEADERS}) -hypervisor_add_header_depends(../src/alloc_mk_debug_ring.c ${HEADERS}) -hypervisor_add_header_depends(../src/alloc_mk_huge_pool.c ${HEADERS}) -hypervisor_add_header_depends(../src/alloc_mk_page_pool.c ${HEADERS}) -hypervisor_add_header_depends(../src/alloc_mk_stack.c ${HEADERS}) -hypervisor_add_header_depends(../src/dump_ext_elf_files.c ${HEADERS}) -hypervisor_add_header_depends(../src/dump_mk_args.c ${HEADERS}) -hypervisor_add_header_depends(../src/dump_mk_debug_ring.c ${HEADERS}) -hypervisor_add_header_depends(../src/dump_mk_elf_file.c ${HEADERS}) -hypervisor_add_header_depends(../src/dump_mk_elf_segments.c ${HEADERS}) -hypervisor_add_header_depends(../src/dump_mk_huge_pool.c ${HEADERS}) -hypervisor_add_header_depends(../src/dump_mk_page_pool.c ${HEADERS}) -hypervisor_add_header_depends(../src/dump_mk_stack.c ${HEADERS}) -hypervisor_add_header_depends(../src/dump_vmm.c ${HEADERS}) -hypervisor_add_header_depends(../src/free_ext_elf_files.c ${HEADERS}) -hypervisor_add_header_depends(../src/free_mk_args.c ${HEADERS}) -hypervisor_add_header_depends(../src/free_mk_debug_ring.c ${HEADERS}) -hypervisor_add_header_depends(../src/free_mk_elf_file.c ${HEADERS}) -hypervisor_add_header_depends(../src/free_mk_elf_segments.c ${HEADERS}) -hypervisor_add_header_depends(../src/free_mk_huge_pool.c ${HEADERS}) -hypervisor_add_header_depends(../src/free_mk_page_pool.c ${HEADERS}) -hypervisor_add_header_depends(../src/free_mk_stack.c ${HEADERS}) -hypervisor_add_header_depends(../src/g_ext_elf_files.c ${HEADERS}) -hypervisor_add_header_depends(../src/g_mk_args.c ${HEADERS}) -hypervisor_add_header_depends(../src/g_mk_debug_ring.c ${HEADERS}) -hypervisor_add_header_depends(../src/g_mk_elf_file.c ${HEADERS}) -hypervisor_add_header_depends(../src/g_mk_elf_segments.c ${HEADERS}) -hypervisor_add_header_depends(../src/g_mk_huge_pool.c ${HEADERS}) -hypervisor_add_header_depends(../src/g_mk_page_pool.c ${HEADERS}) -hypervisor_add_header_depends(../src/g_mk_stack.c ${HEADERS}) -hypervisor_add_header_depends(../src/loader_fini.c ${HEADERS}) -hypervisor_add_header_depends(../src/loader_init.c ${HEADERS}) -hypervisor_add_header_depends(../src/start_vmm_per_cpu.c ${HEADERS}) -hypervisor_add_header_depends(../src/start_vmm.c ${HEADERS}) -hypervisor_add_header_depends(../src/stop_and_free_the_vmm.c ${HEADERS}) -hypervisor_add_header_depends(../src/stop_vmm_per_cpu.c ${HEADERS}) -hypervisor_add_header_depends(../src/stop_vmm.c ${HEADERS}) -hypervisor_add_header_depends(../src/vmm_status.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader src/entry.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader src/platform.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader src/work_on_cpu_callback.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/alloc_and_copy_ext_elf_files_from_user.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/alloc_and_copy_mk_elf_file_from_user.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/alloc_and_copy_mk_elf_segments.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/alloc_mk_args.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/alloc_mk_debug_ring.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/alloc_mk_huge_pool.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/alloc_mk_page_pool.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/alloc_mk_stack.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/dump_ext_elf_files.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/dump_mk_args.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/dump_mk_debug_ring.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/dump_mk_elf_file.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/dump_mk_elf_segments.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/dump_mk_huge_pool.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/dump_mk_page_pool.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/dump_mk_root_page_table.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/dump_mk_stack.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/dump_vmm.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/free_ext_elf_files.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/free_mk_args.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/free_mk_debug_ring.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/free_mk_elf_file.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/free_mk_elf_segments.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/free_mk_huge_pool.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/free_mk_page_pool.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/free_mk_stack.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_cpu_status.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/get_mk_huge_pool_addr.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/get_mk_page_pool_addr.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_ext_elf_files.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_mk_args.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_mk_code_aliases.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_mk_debug_ring.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_mk_elf_file.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_mk_elf_segments.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_mk_huge_pool.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_mk_page_pool.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_mk_root_page_table.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_mk_stack.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_mk_state.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_root_vp_state.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/g_vmm_status.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/loader_fini.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/loader_init.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/map_4k_page_rw.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/map_4k_page_rx.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/map_ext_elf_files.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/map_mk_args.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/map_mk_debug_ring.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/map_mk_elf_file.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/map_mk_elf_segments.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/map_mk_huge_pool.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/map_mk_page_pool.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/map_mk_stack.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/serial_write.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/start_vmm.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/start_vmm_per_cpu.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/stop_and_free_the_vmm.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/stop_vmm.c ${HEADERS}) +hypervisor_target_source(bareflank_efi_loader ../src/stop_vmm_per_cpu.c ${HEADERS}) if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - target_sources(bareflank_efi_loader PUBLIC - src/x64/demote.S - src/x64/esr_default.S - src/x64/esr_df.S - src/x64/esr_gpf.S - src/x64/esr_nmi.S - src/x64/esr_pf.S - src/x64/intrinsic_cpuid.S - src/x64/intrinsic_inb.S - src/x64/intrinsic_lcr4.S - src/x64/intrinsic_outb.S - src/x64/intrinsic_rdmsr.S - src/x64/intrinsic_scr0.S - src/x64/intrinsic_scr4.S - src/x64/intrinsic_scs.S - src/x64/intrinsic_sds.S - src/x64/intrinsic_ses.S - src/x64/intrinsic_sfs.S - src/x64/intrinsic_sgdt.S - src/x64/intrinsic_sgs.S - src/x64/intrinsic_sidt.S - src/x64/intrinsic_sldtr.S - src/x64/intrinsic_sss.S - src/x64/intrinsic_str.S - src/x64/intrinsic_wrmsr.S - src/x64/promote.S - ../src/x64/alloc_and_copy_mk_code_aliases.c - ../src/x64/alloc_and_copy_mk_state.c - ../src/x64/alloc_and_copy_root_vp_state.c - ../src/x64/alloc_mk_root_page_table.c - ../src/x64/alloc_pdpt.c - ../src/x64/alloc_pdt.c - ../src/x64/alloc_pt.c - ../src/x64/dump_mk_code_aliases.c - ../src/x64/dump_mk_root_page_table.c - ../src/x64/dump_mk_state.c - ../src/x64/dump_root_vp_state.c - ../src/x64/free_mk_code_aliases.c - ../src/x64/free_mk_root_page_table.c - ../src/x64/free_mk_state.c - ../src/x64/free_pdpt.c - ../src/x64/free_pdt.c - ../src/x64/free_pml4t.c - ../src/x64/free_root_vp_state.c - ../src/x64/g_mk_code_aliases.c - ../src/x64/g_mk_root_page_table.c - ../src/x64/g_mk_state.c - ../src/x64/g_root_vp_state.c - ../src/x64/get_gdt_descriptor_attrib.c - ../src/x64/get_gdt_descriptor_base.c - ../src/x64/get_gdt_descriptor_limit.c - ../src/x64/get_mk_huge_pool_addr.c - ../src/x64/get_mk_page_pool_addr.c - ../src/x64/map_4k_page_rw.c - ../src/x64/map_4k_page_rx.c - ../src/x64/map_4k_page.c - ../src/x64/map_ext_elf_files.c - ../src/x64/map_mk_args.c - ../src/x64/map_mk_debug_ring.c - ../src/x64/map_mk_code_aliases.c - ../src/x64/map_mk_elf_file.c - ../src/x64/map_mk_elf_segments.c - ../src/x64/map_mk_huge_pool.c - ../src/x64/map_mk_page_pool.c - ../src/x64/map_mk_stack.c - ../src/x64/map_mk_state.c - ../src/x64/map_root_vp_state.c - ../src/x64/send_command_report_off.c - ../src/x64/send_command_report_on.c - ../src/x64/send_command_stop.c - ../src/x64/serial_init.c - ../src/x64/serial_write.c - ../src/x64/set_gdt_descriptor.c - ../src/x64/set_idt_descriptor.c - ) + hypervisor_target_source(bareflank_efi_loader src/x64/arch_init.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/arch_locate_protocols.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/arch_num_online_cpus.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/arch_work_on_cpu.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/demote.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/esr_default.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/esr_df.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/esr_gpf.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/esr_nmi.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/esr_pf.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/flush_cache.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_cpuid.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_inb.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_lcr0.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_lcr4.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_lgdt.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_ltr.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_outb.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_rdmsr.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_scr0.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_scr4.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_scs.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_sds.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_ses.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_sfs.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_sgdt.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_sgs.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_sidt.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_sldtr.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_sss.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_str.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intrinsic_wrmsr.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/memops.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/promote.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/serial_write_c.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/serial_write_hex.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/setup_tss.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/alloc_and_copy_mk_code_aliases.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/alloc_and_copy_mk_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/alloc_and_copy_root_vp_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/alloc_mk_root_page_table.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/alloc_pdpt.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/alloc_pdt.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/alloc_pt.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/dump_mk_code_aliases.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/dump_mk_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/dump_root_vp_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/free_mk_code_aliases.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/free_mk_root_page_table.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/free_mk_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/free_pdpt.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/free_pdt.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/free_pml4t.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/free_root_vp_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/get_gdt_descriptor_attrib.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/get_gdt_descriptor_base.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/get_gdt_descriptor_limit.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/map_4k_page.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/map_mk_code_aliases.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/map_mk_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/map_root_vp_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/send_command_report_off.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/send_command_report_on.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/send_command_stop.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/serial_init.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/set_gdt_descriptor.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/set_idt_descriptor.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/alloc_and_copy_mk_code_aliases.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/alloc_and_copy_mk_state.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/alloc_and_copy_root_vp_state.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/alloc_mk_root_page_table.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/alloc_pdpt.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/alloc_pdt.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/alloc_pt.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/dump_mk_code_aliases.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/dump_mk_root_page_table.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/dump_mk_state.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/dump_root_vp_state.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/free_mk_code_aliases.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/free_mk_root_page_table.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/free_mk_state.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/free_pdpt.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/free_pdt.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/free_pml4t.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/free_root_vp_state.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/g_mk_code_aliases.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/g_mk_root_page_table.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/g_mk_state.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/g_root_vp_state.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/get_gdt_descriptor_attrib.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/get_gdt_descriptor_base.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/get_gdt_descriptor_limit.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/get_mk_huge_pool_addr.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/get_mk_page_pool_addr.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_4k_page_rw.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_4k_page_rx.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_4k_page.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_ext_elf_files.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_mk_args.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_mk_debug_ring.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_mk_code_aliases.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_mk_elf_file.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_mk_elf_segments.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_mk_huge_pool.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_mk_page_pool.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_mk_stack.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_mk_state.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/map_root_vp_state.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/send_command_report_off.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/send_command_report_on.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/send_command_stop.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/serial_init.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/serial_write.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/set_gdt_descriptor.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/set_idt_descriptor.c ${HEADERS}) + if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") + hypervisor_target_source(bareflank_efi_loader src/x64/amd/disable_interrupts.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/amd/enable_interrupts.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/amd/setup_cr0.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/amd/setup_cr4.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/amd/check_cpu_configuration.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/amd/disable_hve.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/amd/enable_hve.c ${HEADERS}) + endif() + + if(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + hypervisor_target_source(bareflank_efi_loader src/x64/intel/disable_interrupts.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intel/enable_interrupts.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intel/intrinsic_vmxoff.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intel/intrinsic_vmxon.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intel/setup_cr0.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/x64/intel/setup_cr4.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/intel/check_cpu_configuration.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/intel/disable_hve.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/x64/intel/enable_hve.c ${HEADERS}) + endif() endif() -if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD") - target_sources(bareflank_efi_loader PUBLIC - src/x64/amd/disable_interrupts.S - src/x64/amd/enable_interrupts.S - ../src/x64/amd/enable_hve.c - ../src/x64/amd/disable_hve.c - ../src/x64/amd/check_for_hve_support.c - ) - hypervisor_add_header_depends(../src/x64/amd/enable_hve.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/amd/disable_hve.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/amd/check_for_hve_support.c ${HEADERS}) -elseif(HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") - target_sources(bareflank_efi_loader PUBLIC - src/x64/intel/disable_interrupts.S - src/x64/intel/enable_interrupts.S - src/x64/intel/intrinsic_vmxoff.S - src/x64/intel/intrinsic_vmxon.S - ../src/x64/intel/enable_hve.c - ../src/x64/intel/disable_hve.c - ../src/x64/intel/check_for_hve_support.c - ) - hypervisor_add_header_depends(../src/x64/intel/enable_hve.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/intel/disable_hve.c ${HEADERS}) - hypervisor_add_header_depends(../src/x64/intel/check_for_hve_support.c ${HEADERS}) -else() - message(FATAL_ERROR "Unsupported HYPERVISOR_TARGET_ARCH: ${HYPERVISOR_TARGET_ARCH}") +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/arch_init.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/arch_locate_protocols.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/arch_num_online_cpus.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/arch_work_on_cpu.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/demote.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/esr.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/exception_vectors.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/flush_cache.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/memcpy.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/memset.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/promote.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/read_currentel.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/read_daif.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/read_hcr_el2.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/read_mair_el2.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/read_sctlr_el2.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/read_spsel.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/read_tcr_el2.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/read_ttbr0_el2.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/read_vbar_el2.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/serial_write_c.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader src/arm/aarch64/serial_write_hex.S ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/alloc_and_copy_mk_code_aliases.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/alloc_and_copy_mk_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/alloc_and_copy_root_vp_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/alloc_l1t.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/alloc_l2t.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/alloc_l3t.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/alloc_mk_root_page_table.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/check_cpu_configuration.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/dump_mk_code_aliases.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/dump_mk_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/dump_root_vp_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/free_l0t.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/free_l1t.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/free_l2t.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/free_mk_code_aliases.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/free_mk_root_page_table.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/free_mk_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/free_root_vp_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/map_4k_page.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/map_mk_code_aliases.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/map_mk_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/map_root_vp_state.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/send_command_report_off.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/send_command_report_on.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/send_command_stop.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/serial_init.c ${HEADERS}) + hypervisor_target_source(bareflank_efi_loader ../src/arm/aarch64/serial_write.c ${HEADERS}) endif() +# ------------------------------------------------------------------------------ +# Install +# ------------------------------------------------------------------------------ + install(TARGETS bareflank_efi_loader DESTINATION bin) diff --git a/loader/efi/include/arch_init.h b/loader/efi/include/arch_init.h new file mode 100644 index 00000000..5dadd596 --- /dev/null +++ b/loader/efi/include/arch_init.h @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ARCH_INIT_H +#define ARCH_INIT_H + +#include + +/** + * + * @brief Sets up the CPU above and beyond what UEFI has provided. + * + * + * @return Returns 0 on success, LOADER_FAILURE otherwise + */ +int64_t arch_init(); + +#endif diff --git a/loader/efi/include/arch_locate_protocols.h b/loader/efi/include/arch_locate_protocols.h new file mode 100644 index 00000000..8ba1bc73 --- /dev/null +++ b/loader/efi/include/arch_locate_protocols.h @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ARCH_LOCATE_PROTOCOLS_H +#define ARCH_LOCATE_PROTOCOLS_H + +#include + +/** + * + * @brief Locates all of the protocols that are needed by this architecture + * + * + * @return returns EFI_SUCCESS on success, and a non-EFI_SUCCESS value on + * failure. + */ +EFI_STATUS arch_locate_protocols(void); + +#endif diff --git a/loader/efi/include/arch_num_online_cpus.h b/loader/efi/include/arch_num_online_cpus.h new file mode 100644 index 00000000..b79cc974 --- /dev/null +++ b/loader/efi/include/arch_num_online_cpus.h @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ARCH_NUM_ONLINE_CPUS_H +#define ARCH_NUM_ONLINE_CPUS_H + +#include + +/** + * + * @brief Returns the total number of online CPUs on this architecture + * (i.e. PPs) + * + * + * @return Returns the total number of online CPUs on this architecture + * (i.e. PPs) + */ +uint32_t arch_num_online_cpus(void); + +#endif diff --git a/loader/efi/include/arch_work_on_cpu.h b/loader/efi/include/arch_work_on_cpu.h new file mode 100644 index 00000000..bf899a0a --- /dev/null +++ b/loader/efi/include/arch_work_on_cpu.h @@ -0,0 +1,45 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ARCH_WORK_ON_CPU_H +#define ARCH_WORK_ON_CPU_H + +#include +#include + +/** + * + * @brief Executes a callback on a specific core on this architecture. + * + * + * @param cpu the core to execute the callback on + * @param callback the callback to call + * @param args the arguments for work_on_cpu_callback + */ +void arch_work_on_cpu( + uint32_t const cpu, void *const callback, struct work_on_cpu_callback_args *const args); + +#endif diff --git a/loader/efi/include/debug.h b/loader/efi/include/debug.h index d5ee677c..e31ab74a 100644 --- a/loader/efi/include/debug.h +++ b/loader/efi/include/debug.h @@ -73,6 +73,36 @@ console_write(char const *const str) } } +static inline void +console_write_c(char const c) +{ + char buf[4] = {0}; + + if (c == '\n') { + console_write("\r\n"); + return; + } + + if (c == '\r') { + return; + } + + /** + * NOTE: + * - We cannot simply send the string to OutputString as it is expecting + * a unicode string. + * - The minimum sized unicode string is one character (2 bytes) and a + * second character for the \0, which is why we have a 4 byte array. + * One byte to store the character we wish to print, and a second to + * tell OutputString to stop. + * - This, of course would not be needed if EFI has a character output + * function, which is basically what this function needs to emulate. + */ + + buf[0] = c; + g_st->ConOut->OutputString(g_st->ConOut, ((CHAR16 *)buf)); +} + /** * * @brief Outputs a string to the console @@ -200,6 +230,31 @@ bfdebug_x64(char const *const str, uint64_t const val) console_write("\r\n"); } +/** + * + * @brief Outputs a string and an 64bit hex to the console + * + * + * @param str the string to output + * @param idx an index (for an array) + * @param val the 64bit hex value to output + */ +static inline void +bfdebug_x64_idx(char const *const str, uint64_t const idx, uint64_t const val) +{ + char idx_num[65] = {0}; + char val_num[65] = {0}; + bfitoa(((uint64_t)idx), idx_num, BASE16); + bfitoa(((uint64_t)val), val_num, BASE16); + + serial_write(str); + serial_write("[0x"); + serial_write(idx_num); + serial_write("]: 0x"); + serial_write(val_num); + serial_write("\n"); +} + /** * * @brief Outputs a string and an 8bit dec to the console diff --git a/loader/efi/include/efi/efi_boot_services.h b/loader/efi/include/efi/efi_boot_services.h index 8dcafeac..1bca9b30 100644 --- a/loader/efi/include/efi/efi_boot_services.h +++ b/loader/efi/include/efi/efi_boot_services.h @@ -27,18 +27,18 @@ #ifndef EFI_BOOT_SERVICES_H #define EFI_BOOT_SERVICES_H -#include "efi_allocate_type.h" -#include "efi_device_path_protocol.h" -#include "efi_guid.h" -#include "efi_interface_type.h" -#include "efi_locate_search_type.h" -#include "efi_memory_descriptor.h" -#include "efi_memory_type.h" -#include "efi_open_protocol_information_entry.h" -#include "efi_status.h" -#include "efi_table_header.h" -#include "efi_timer_delay.h" -#include "efi_types.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /** @brief Defines EFI_BOOT_SERVICES_SIGNATURE */ #define EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42 diff --git a/loader/efi/include/efi/efi_device_path_protocol.h b/loader/efi/include/efi/efi_device_path_protocol.h index e38ef6cc..ce33c1e6 100644 --- a/loader/efi/include/efi/efi_device_path_protocol.h +++ b/loader/efi/include/efi/efi_device_path_protocol.h @@ -27,7 +27,7 @@ #ifndef EFI_DEVICE_PATH_PROTOCOL_H #define EFI_DEVICE_PATH_PROTOCOL_H -#include "efi_types.h" +#include /** @brief Defined in EFI_DEVICE_PATH_PROTOCOL */ #define EFI_DEVICE_PATH_PROTOCOL_LENGTH_SIZE 2 diff --git a/loader/efi/include/efi/efi_file_info.h b/loader/efi/include/efi/efi_file_info.h index 8df2f773..2475c8bd 100644 --- a/loader/efi/include/efi/efi_file_info.h +++ b/loader/efi/include/efi/efi_file_info.h @@ -27,8 +27,8 @@ #ifndef EFI_FILE_INFO_H #define EFI_FILE_INFO_H -#include "efi_time.h" -#include "efi_types.h" +#include +#include /** @brief defines the GUID for EFI_FILE_INFO */ #define EFI_FILE_INFO_ID \ diff --git a/loader/efi/include/efi/efi_file_protocol.h b/loader/efi/include/efi/efi_file_protocol.h index 4c4e7929..9167e0c9 100644 --- a/loader/efi/include/efi/efi_file_protocol.h +++ b/loader/efi/include/efi/efi_file_protocol.h @@ -27,11 +27,11 @@ #ifndef EFI_FILE_PROTOCOL_H #define EFI_FILE_PROTOCOL_H -#include "efi_file_info.h" -#include "efi_file_io_token.h" -#include "efi_guid.h" -#include "efi_status.h" -#include "efi_types.h" +#include +#include +#include +#include +#include /** @brief defines the Revision Number 1 for EFI_FILE_PROTOCOL */ #define EFI_FILE_PROTOCOL_REVISION 0x00010000 diff --git a/loader/include/static_assert.h b/loader/efi/include/efi/efi_list_entry.h similarity index 66% rename from loader/include/static_assert.h rename to loader/efi/include/efi/efi_list_entry.h index 8e27e582..e6566bd5 100644 --- a/loader/include/static_assert.h +++ b/loader/efi/include/efi/efi_list_entry.h @@ -24,15 +24,34 @@ * SOFTWARE. */ -#ifndef STATIC_ASSERT_H -#define STATIC_ASSERT_H +#ifndef EFI_LIST_ENTRY_H +#define EFI_LIST_ENTRY_H -#define CTASTR2(pre, post) pre##post -#define CTASTR(pre, post) CTASTR2(pre, post) -#define STATIC_ASSERT(cond, msg) \ - typedef struct \ - { \ - int CTASTR(static_assertion_failed_, msg) : !!(cond); \ - } CTASTR(static_assertion_failed_, __COUNTER__) +/** @brief prototype for _EFI_LIST_ENTRY */ +struct _EFI_LIST_ENTRY; + +/** @brief prototype for EFI_LIST_ENTRY */ +typedef struct _EFI_LIST_ENTRY EFI_LIST_ENTRY; + +/** + * @struct EFI_LIST_ENTRY + * + * + * @brief Defines the layout of the EFI_LIST_ENTRY struct: + * https://uefi.org/sites/default/files/resources/UEFI_Shell_2_2.pdf + */ +typedef struct _EFI_LIST_ENTRY +{ + /** + * @brief n/a + */ + struct _EFI_LIST_ENTRY *Flink; + + /** + * @brief n/a + */ + struct _EFI_LIST_ENTRY *Blink; + +} EFI_LIST_ENTRY; #endif diff --git a/loader/efi/include/efi/efi_memory_descriptor.h b/loader/efi/include/efi/efi_memory_descriptor.h index 0a0ca07c..d3d22ad3 100644 --- a/loader/efi/include/efi/efi_memory_descriptor.h +++ b/loader/efi/include/efi/efi_memory_descriptor.h @@ -27,7 +27,7 @@ #ifndef EFI_MEMORY_DESCRIPTOR_H #define EFI_MEMORY_DESCRIPTOR_H -#include "efi_types.h" +#include /** * @brief Memory cacheability attribute: The memory region supports being diff --git a/loader/efi/include/efi/efi_mp_services_protocol.h b/loader/efi/include/efi/efi_mp_services_protocol.h index 6e159afa..ed551e8e 100644 --- a/loader/efi/include/efi/efi_mp_services_protocol.h +++ b/loader/efi/include/efi/efi_mp_services_protocol.h @@ -27,8 +27,8 @@ #ifndef EFI_MP_SERVICES_PROTOCOL_H #define EFI_MP_SERVICES_PROTOCOL_H -#include "efi_processor_information.h" -#include "efi_types.h" +#include +#include /** @brief defines the GUID for EFI_MP_SERVICES_PROTOCOL_GUID */ #define EFI_MP_SERVICES_PROTOCOL_GUID \ diff --git a/loader/efi/include/efi/efi_open_protocol_information_entry.h b/loader/efi/include/efi/efi_open_protocol_information_entry.h index 55044e18..db050728 100644 --- a/loader/efi/include/efi/efi_open_protocol_information_entry.h +++ b/loader/efi/include/efi/efi_open_protocol_information_entry.h @@ -27,7 +27,7 @@ #ifndef EFI_OPEN_PROTOCOL_INFORMATION_ENTRY_H #define EFI_OPEN_PROTOCOL_INFORMATION_ENTRY_H -#include "efi_types.h" +#include /** * @struct EFI_OPEN_PROTOCOL_INFORMATION_ENTRY diff --git a/loader/efi/include/efi/efi_processor_information.h b/loader/efi/include/efi/efi_processor_information.h index f68ec18a..1aef70b5 100644 --- a/loader/efi/include/efi/efi_processor_information.h +++ b/loader/efi/include/efi/efi_processor_information.h @@ -27,9 +27,9 @@ #ifndef EFI_PROCESSOR_INFORMATION_H #define EFI_PROCESSOR_INFORMATION_H -#include "efi_cpu_physical_location.h" -#include "efi_types.h" -#include "extened_processor_information.h" +#include +#include +#include /** * @brief This bit indicates whether the processor is playing the role of BSP. diff --git a/loader/efi/include/efi/efi_shell_file_info.h b/loader/efi/include/efi/efi_shell_file_info.h new file mode 100644 index 00000000..af52c9f7 --- /dev/null +++ b/loader/efi/include/efi/efi_shell_file_info.h @@ -0,0 +1,80 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef EFI_SHELL_FILE_INFO_H +#define EFI_SHELL_FILE_INFO_H + +#include +#include +#include + +/** @brief n/a */ +typedef VOID *SHELL_FILE_HANDLE; + +/** + * @struct EFI_SHELL_FILE_INFO + * + * + * @brief Defines the layout of the EFI_SHELL_FILE_INFO struct: + * https://uefi.org/sites/default/files/resources/UEFI_Shell_2_2.pdf + */ +typedef struct +{ + /** + * @brief Points to the next and previous entries in the file list. + * If NULL, then no more files. + */ + EFI_LIST_ENTRY Link; + + /** + * @brief The status returned when calling OpenFile() for the entry in + * the file list. + */ + EFI_STATUS Status; + + /** + * @brief Specifies the full name of the file, including the path. + */ + CONST CHAR16 *FullName; + + /** + * @brief n/a + */ + CONST CHAR16 *FileName; + + /** + * @brief The file handle of the file after it was opened. + */ + SHELL_FILE_HANDLE Handle; + + /** + * @brief The file information for the opened file. + */ + EFI_FILE_INFO *Info; + +} EFI_SHELL_FILE_INFO; + +#endif diff --git a/loader/efi/include/efi/efi_shell_protocol.h b/loader/efi/include/efi/efi_shell_protocol.h new file mode 100644 index 00000000..6beb3e92 --- /dev/null +++ b/loader/efi/include/efi/efi_shell_protocol.h @@ -0,0 +1,867 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef EFI_SHELL_PROTOCOL_H +#define EFI_SHELL_PROTOCOL_H + +#include +#include +#include + +/** @brief defines the GUID for EFI_SHELL_PROTOCOL_GUID */ +#define EFI_SHELL_PROTOCOL_GUID \ + { \ + 0x6302d008, 0x7f9b, 0x4f30, \ + { \ + 0x87, 0xac, 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e \ + } \ + } + +/** @brief prototype for _EFI_SHELL_PROTOCOL */ +struct _EFI_SHELL_PROTOCOL; + +/** @brief prototype for EFI_SHELL_PROTOCOL */ +typedef struct _EFI_SHELL_PROTOCOL EFI_SHELL_PROTOCOL; + +/** + * + * @brief Returns whether any script files are currently being processed. + * + * + * @return Returns an EFI_STATUS + */ +typedef BOOLEAN(EFIAPI *EFI_SHELL_BATCH_IS_ACTIVE)(VOID); + +/** + * + * @brief Closes the file handle. + * + * + * @param FileHandle The file handle to be closed + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_CLOSE_FILE)(IN SHELL_FILE_HANDLE FileHandle); + +/** + * + * @brief Creates a file or directory by name. + * + * + * @param FileName Points to the null-terminated file path. + * @param FileAttribs The new file’s attributes. The different attributes + * are described in EFI_FILE_PROTOCOL.Open(). + * @param FileHandle On return, points to the created file or directory’s + * handle. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_CREATE_FILE)( + IN CONST CHAR16 *FileName, IN UINT64 FileAttribs, OUT SHELL_FILE_HANDLE *FileHandle); + +/** + * + * @brief Deletes the file specified by the file handle. + * + * + * @param FileHandle The file handle to delete. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_DELETE_FILE)(IN SHELL_FILE_HANDLE FileHandle); + +/** + * + * @brief Deletes the file specified by the file handle. + * + * + * @param FileName Points to the null-terminated file name. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_DELETE_FILE_BY_NAME)(IN CONST CHAR16 *FileName); + +/** + * + * @brief Disables the page break output mode. + * + * + * @return Returns an EFI_STATUS + */ +typedef VOID(EFIAPI *EFI_SHELL_DISABLE_PAGE_BREAK)(VOID); + +/** + * + * @brief Enables the page break output mode. + * + * + * @return Returns an EFI_STATUS + */ +typedef VOID(EFIAPI *EFI_SHELL_ENABLE_PAGE_BREAK)(VOID); + +/** + * + * @brief Execute the command line. + * + * + * @param ParentImageHandle A handle of the image that is executing the + * specified command line. + * @param CommandLine Points to the null-terminated UCS-2 encoded string + * containing the command line. If NULL then the command-line will be + * empty. + * @param Environment Points to a null-terminated array of environment + * variables with the format ‘x=y’, where x is the environment variable + * name and y is the value. If this is NULL, then the current shell + * environment is used. + * @param ErrorCode Points to the status code returned by the command. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_EXECUTE)( + IN EFI_HANDLE *ParentImageHandle, + IN CHAR16 *CommandLine OPTIONAL, + IN CHAR16 **Environment OPTIONAL, + OUT EFI_STATUS *StatusCode OPTIONAL); + +/** + * + * @brief Find files that match a specified pattern. + * + * + * @param FilePattern Points to a null-terminated shell file path, + * including wildcards. + * @param FileList On return, points to the start of a file list containing + * the names of all matching files or else points to NULL if no matching + * files were found. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_FIND_FILES)( + IN CONST CHAR16 *FilePattern, OUT EFI_SHELL_FILE_INFO **FileList); + +/** + * + * @brief Find all files in a specified directory. + * + * + * @param FileDirHandle Handle of the directory to search. + * @param FileList On return, points to the list of files in the directory + * or NULL if there are no files in the directory. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_FIND_FILES_IN_DIR)( + IN SHELL_FILE_HANDLE FileDirHandle, OUT EFI_SHELL_FILE_INFO **FileList); + +/** + * + * @brief Flushes data back to a device + * + * + * @param FileHandle The handle of the file to flush. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_FLUSH_FILE)(IN SHELL_FILE_HANDLE FileHandle); + +/** + * + * @brief Frees the file list. + * + * + * @param FileList The file list to free. Type EFI_SHELL_FILE_INFO is + * defined in OpenFileList() + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_FREE_FILE_LIST)(IN EFI_SHELL_FILE_INFO **FileList); + +/** + * + * @brief Retrieves a shell command alias. + * + * + * @param Alias Points to the null-terminated alias. If Alias is not NULL, + * this function returns the associated null-terminated command. If Alias + * is NULL, this function returns a ‘;’ delimited list of all the defined + * aliases (e.g. ReturnedData = “md;rd;cp;mfp”) that is null-terminated. + * @param Volatile If the return value is not NULL and Alias is not NULL, + * the Volatile parameter being TRUE indicates that the Alias is stored + * in a volatile fashion. If the return value is not NULL and Alias is + * not NULL, the Volatile parameter being FALSE indicates that the Alias + * is stored in a non-volatile fashion. For all other situations, this + * output parameter must be ignored. + * @return Returns an EFI_STATUS + */ +typedef CONST + CHAR16 *(EFIAPI *EFI_SHELL_GET_ALIAS)(IN CONST CHAR16 *Alias, OUT BOOLEAN *Volatile OPTIONAL); + +/** + * + * @brief Returns the current directory on the specified device. + * + * + * @param FileSystemMapping A pointer to the file system mapping. If NULL, + * then the current working directory is returned. + * @return Returns an EFI_STATUS + */ +typedef CONST CHAR16 *(EFIAPI *EFI_SHELL_GET_CUR_DIR)(IN CONST CHAR16 *FileSystemMapping OPTIONAL); + +/** @brief n/a */ +typedef UINT32 EFI_DEVICE_NAME_FLAGS; +/** @brief n/a */ +#define EFI_DEVICE_NAME_USE_COMPONENT_NAME 0x00000001 +/** @brief n/a */ +#define EFI_DEVICE_NAME_USE_DEVICE_PATH 0x00000002 + +/** + * + * @brief Gets the name of the device specified by the device handle. + * + * + * @param DeviceHandle The handle of the device. + * @param Flags Determines the possible sources of component names. See + * “Related Definitions” below for more information. + * @param Language A pointer to the language specified for the device name, + * in the same format as described in the UEFI specification, Appendix M + * @param BestDeviceName On return, points to the callee-allocated + * null-terminated name of the device. If no device name could be found, + * points to NULL. The name must be freed by the caller. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS (*EFI_SHELL_GET_DEVICE_NAME)( + IN EFI_HANDLE DeviceHandle, + IN EFI_DEVICE_NAME_FLAGS Flags, + IN CHAR8 *Language, + OUT CHAR16 **BestDeviceName); + +/** + * + * @brief Gets the device path from the mapping. + * + * + * @param Mapping A pointer to the mapping. + * @return Returns an EFI_STATUS + */ +typedef CONST EFI_DEVICE_PATH_PROTOCOL *(EFIAPI *EFI_SHELL_GET_DEVICE_PATH_FROM_MAP)( + IN CONST CHAR16 *Mapping); + +/** + * + * @brief Converts a file system style name to a device path. + * + * + * @param Path The pointer to the path. + * @return Returns an EFI_STATUS + */ +typedef EFI_DEVICE_PATH_PROTOCOL *(EFIAPI *EFI_SHELL_GET_DEVICE_PATH_FROM_FILE_PATH)( + IN CONST CHAR16 *Path); + +/** + * + * @brief Gets the environment variable or list of environment variables. + * + * + * @param Name A pointer to the environment variable name. If Name is NULL, + * then the function will return all of the defined shell environment + * variables. In the case where multiple environment variables are being + * returned, each variable will be terminated by a NULL,and the list will + * be terminated by a double NULL. + * @return Returns an EFI_STATUS + */ +typedef CONST CHAR16 *(EFIAPI *EFI_SHELL_GET_ENV)(IN CONST CHAR16 *Name); + +/** + * + * @brief Gets the environment variable and Attributes, or list of + * environment variables. Can be used instead of GetEnv(). + * + * + * @param Name A pointer to the environment variable name. If Name is NULL, + * then the function will return all of the defined shell environment + * variables. In the case where multiple environment variables are being + * returned, each variable will be terminated by a NULL, and the list + * will be terminated by a double NULL. + * @param Attributes If not NULL, a pointer to the returned attributes + * bitmask for the environment variable. In the case where Name is NULL, + * and multiple environment variables are being returned, Attributes is + * undefined. + * @return Returns an EFI_STATUS + */ +typedef CONST + CHAR16 *(EFIAPI *EFI_SHELL_GET_ENV_EX)(IN CONST CHAR16 *Name, OUT UINT32 *Attributes OPTIONAL); + +/** + * + * @brief Gets the file information from an open file handle. + * + * + * @param FileHandle A file handle + * @return Returns an EFI_STATUS + */ +typedef EFI_FILE_INFO *(EFIAPI *EFI_SHELL_GET_FILE_INFO)(IN SHELL_FILE_HANDLE FileHandle); + +/** + * + * @brief Converts a device path to a file system-style path. + * + * + * @param Path The pointer to the device path. + * @return Returns an EFI_STATUS + */ +typedef CHAR16 *(EFIAPI *EFI_SHELL_GET_FILE_PATH_FROM_DEVICE_PATH)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Path); + +/** + * + * @brief Gets a file’s current position + * + * + * @param FileHandle The file handle on which to get the current position. + * @param Position Byte position from the start of the file + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_GET_FILE_POSITION)( + IN SHELL_FILE_HANDLE FileHandle, OUT UINT64 *Position); + +/** + * + * @brief Gets the size of a file. + * + * + * @param FileHandle The handle of the file. + * @param Size The size of this file. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_GET_FILE_SIZE)( + IN SHELL_FILE_HANDLE FileHandle, OUT UINT64 *Size); + +/** + * + * @brief Get the GUID value from a human readable name. + * + * + * @param GuidName A pointer to the localized name for the GUID being queried. + * @param Guid A pointer to the GUID structure to be filled in. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_GET_GUID_FROM_NAME)( + IN CONST CHAR16 *GuidName, OUT EFI_GUID *Guid); + +/** + * + * @brief Get the human readable name for a GUID from the value. + * + * + * @param Guid A pointer to the GUID being queried. + * @param GuidName A pointer to a pointer the localized to name for the GUID + * being requested. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_GET_GUID_NAME)( + IN CONST EFI_GUID *Guid, OUT CONST CHAR16 **GuidName); + +/** + * + * @brief Return help information about a specific command. + * + * + * @param Command Points to the null-terminated UEFI Shell command name. + * @param Sections Points to the null-terminated comma-delimited section + * names to return. If NULL, then all sections will be returned. + * @param HelpText On return, points to a callee-allocated buffer containing + * all specified help text. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_GET_HELP_TEXT)( + IN CONST CHAR16 *Command, IN CONST CHAR16 *Sections, OUT CHAR16 **HelpText); + +/** + * + * @brief Gets one or more mapping entries that most closely matches the + * device path. + * + * + * @param DevicePath On entry, points to a device path pointer. On exit, + * updates the pointer to point to the portion of the device path after + * the mapping. + * @return Returns an EFI_STATUS + */ +typedef CONST CHAR16 *(EFIAPI *EFI_SHELL_GET_MAP_FROM_DEVICE_PATH)( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath); + +/** + * + * @brief Gets the enable status of the page break output mode. + * + * + * @return Returns an EFI_STATUS + */ +typedef BOOLEAN(EFIAPI *EFI_SHELL_GET_PAGE_BREAK)(VOID); + +/** + * + * @brief Judges whether the active shell is the root shell. + * + * + * @return Returns an EFI_STATUS + */ +typedef BOOLEAN(EFIAPI *EFI_SHELL_IS_ROOT_SHELL)(VOID); + +/** + * + * @brief Opens a file or a directory by file name. + * + * + * @param FileName Points to the null-terminated UCS-2 encoded file name. + * @param FileHandle On return, points to the file handle. + * @param OpenMode File open mode. Either EFI_FILE_MODE_READ or + * EFI_FILE_MODE_WRITE from section 12.4 of the UEFI Specification. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_OPEN_FILE_BY_NAME)( + IN CONST CHAR16 *FileName, OUT SHELL_FILE_HANDLE *FileHandle, IN UINT64 OpenMode); + +/** + * + * @brief Opens the files that match the path specified. + * + * + * @param Path A pointer to the path string. + * @param OpenMode Specifies the mode used to open each file, + * EFI_FILE_MODE_READ or EFI_FILE_MODE_WRITE. + * @param FileList Points to the start of a list of files opened. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_OPEN_FILE_LIST)( + IN CHAR16 *Path, IN UINT64 OpenMode, OUT EFI_SHELL_FILE_INFO **FileList); + +/** + * + * @brief Opens the root directory of a device. + * + * + * @param DevicePath Points to the device path corresponding to the device + * where the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL is installed. + * @param FileHandle On exit, points to the file handle corresponding to the + * root directory on the device. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_OPEN_ROOT)( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT SHELL_FILE_HANDLE *FileHandle); + +/** + * + * @brief Opens the root directory of a device on a handle + * + * + * @param DeviceHandle The handle of the device that contains the volume. + * @param FileHandle On exit, points to the file handle corresponding to the + * root directory on the device. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_OPEN_ROOT_BY_HANDLE)( + IN EFI_HANDLE DeviceHandle, OUT SHELL_FILE_HANDLE *FileHandle); + +/** + * + * @brief Reads data from the file. + * + * + * @param FileHandle The opened file handle for read + * @param ReadSize On input, the size of Buffer, in bytes. On output, + * the amount of data read. + * @param Buffer The buffer in which data is read. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_READ_FILE)( + IN SHELL_FILE_HANDLE FileHandle, IN OUT UINTN *ReadSize, OUT VOID *Buffer); + +/** + * + * @brief Register a GUID and a localized human readable name for it. + * + * + * @param Guid A pointer to the GUID being registered. + * @param GuidName A pointer to the localized name for the GUID being + * registered. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_REGISTER_GUID_NAME)( + IN CONST EFI_GUID *Guid, IN CONST CHAR16 *GuidName); + +/** + * + * @brief Deletes the duplicate file names files in the given file list. + * + * + * @param FileList A pointer to the first entry in the file list. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_REMOVE_DUP_IN_FILE_LIST)(IN EFI_SHELL_FILE_INFO **FileList); + +/** + * + * @brief Changes a shell command alias. + * + * + * @param Command Points to the null-terminated shell command or existing + * alias. + * @param Alias Points to the null-terminated alias for the shell command. + * If this is NULL, and Command refers to an alias, that alias will be + * deleted. + * @param Replace If TRUE and the alias already exists, then the existing + * alias will be replaced. If FALSE and the alias already exists, then + * the existing alias is unchanged and EFI_ACCESS_DENIED is returned. + * @param Volatile If TRUE, the Alias being set will be stored in a volatile + * fashion. If FALSE, the Alias will be stored in a nonvolatile fashion. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_SET_ALIAS)( + IN CONST CHAR16 *Command, IN CONST CHAR16 *Alias, IN BOOLEAN Replace, IN BOOLEAN Volatile); + +/** + * + * @brief Changes the current directory on the specified device. + * + * + * @param FileSystem A pointer to the file system’s mapped name. If NULL, + * then the current working directory is changed. + * @param Dir Points to the null-terminated directory on the device + * specified by FileSystem. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_SET_CUR_DIR)( + IN CONST CHAR16 *FileSystem OPTIONAL, IN CONST CHAR16 *Dir); + +/** + * + * @brief Sets the environment variable. + * + * + * @param Name Points to the null-terminated environment variable name. + * @param Value Points to the null-terminated environment variable value. + * If the value is an empty string then the environment variable is deleted. + * @param Volatile Indicates whether the variable is non-volatile (FALSE) + * or volatile (TRUE). + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_SET_ENV)( + IN CONST CHAR16 *Name, IN CONST CHAR16 *Value, IN BOOLEAN Volatile); + +/** + * + * @brief Sets the file information to an opened file handle. + * + * + * @param FileHandle A file handle + * @param FileInfo A file handle + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_SET_FILE_INFO)( + IN SHELL_FILE_HANDLE FileHandle, IN CONST EFI_FILE_INFO *FileInfo); + +/** + * + * @brief Sets a file’s current position + * + * + * @param FileHandle The file handle on which requested position will be set. + * @param Position The file handle on which requested position will be set. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_SET_FILE_POSITION)( + IN SHELL_FILE_HANDLE FileHandle, IN UINT64 Position); + +/** + * + * @brief Changes a shell device mapping. + * + * + * @param DevicePath DevicePath + * @param Mapping Points to the null-terminated mapping for the device path. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_SET_MAP)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CONST CHAR16 *Mapping); + +/** + * + * @brief Writes data to the file. + * + * + * @param FileHandle The opened file handle for writing. + * @param BufferSize On input, size of Buffer. + * @param Buffer The buffer in which data to write. + * @return Returns an EFI_STATUS + */ +typedef EFI_STATUS(EFIAPI *EFI_SHELL_WRITE_FILE)( + IN SHELL_FILE_HANDLE FileHandle, IN OUT UINTN *BufferSize, OUT VOID *Buffer); + +/** + * @struct EFI_SHELL_PROTOCOL + * + * + * @brief Defines the layout of the EFI_SHELL_PROTOCOL struct: + * https://uefi.org/sites/default/files/resources/UEFI_Shell_2_2.pdf + */ +typedef struct _EFI_SHELL_PROTOCOL +{ + /** + * @brief Causes the shell to parse and execute the command line. + */ + EFI_SHELL_EXECUTE Execute; + + /** + * @brief Gets the environment variable. + */ + EFI_SHELL_GET_ENV GetEnv; + + /** + * @brief Changes a specific environment variable. + */ + EFI_SHELL_SET_ENV SetEnv; + + /** + * @brief Retrieves the alias for a specific shell command. + */ + EFI_SHELL_GET_ALIAS GetAlias; + + /** + * @brief Adds or removes the alias for a specific shell command. + */ + EFI_SHELL_SET_ALIAS SetAlias; + + /** + * @brief n/a + */ + EFI_SHELL_GET_HELP_TEXT GetHelpText; + + /** + * @brief Returns the mapping that corresponds to a particular device path. + */ + EFI_SHELL_GET_DEVICE_PATH_FROM_MAP GetDevicePathFromMap; + + /** + * @brief Converts a file path to a device path, where all mappings have + * been replaced with the corresponding device paths. + */ + EFI_SHELL_GET_MAP_FROM_DEVICE_PATH GetMapFromDevicePath; + + /** + * @brief Converts a file path to a device path, where all mappings have + * been replaced with the corresponding device paths. + */ + EFI_SHELL_GET_DEVICE_PATH_FROM_FILE_PATH GetDevicePathFromFilePath; + + /** + * @brief Converts a device path to a file path, where the portion of the + * device path corresponding to one of the mappings is replaced with that + * mapping. + */ + EFI_SHELL_GET_FILE_PATH_FROM_DEVICE_PATH GetFilePathFromDevicePath; + + /** + * @brief Creates, updates or deletes a mapping between a device and a + * device path. + */ + EFI_SHELL_SET_MAP SetMap; + + /** + * @brief Returns the current directory on a device. + */ + EFI_SHELL_GET_CUR_DIR GetCurDir; + + /** + * @brief Changes the current directory on a device. + */ + EFI_SHELL_SET_CUR_DIR SetCurDir; + + /** + * @brief Opens the files that match the path pattern specified. + */ + EFI_SHELL_OPEN_FILE_LIST OpenFileList; + + /** + * @brief Frees the file list that created by OpenFileList(). + */ + EFI_SHELL_FREE_FILE_LIST FreeFileList; + + /** + * @brief Deletes the duplicate files in the given file list. + */ + EFI_SHELL_REMOVE_DUP_IN_FILE_LIST RemoveDupInFileList; + + /** + * @brief Returns whether any script files are currently being processed. + */ + EFI_SHELL_BATCH_IS_ACTIVE BatchIsActive; + + /** + * @brief Judges whether the active Shell is the root shell. + */ + EFI_SHELL_IS_ROOT_SHELL IsRootShell; + + /** + * @brief Enables the page break output mode. + */ + EFI_SHELL_ENABLE_PAGE_BREAK EnablePageBreak; + + /** + * @brief Disables the page break output mode. + */ + EFI_SHELL_DISABLE_PAGE_BREAK DisablePageBreak; + + /** + * @brief Gets the enable status of the page break output mode. + */ + EFI_SHELL_GET_PAGE_BREAK GetPageBreak; + + /** + * @brief Gets the name of the device specified by the device handle. + */ + EFI_SHELL_GET_DEVICE_NAME GetDeviceName; + + /** + * @brief Return information about a specific file handle. + */ + EFI_SHELL_GET_FILE_INFO GetFileInfo; + + /** + * @brief Change information about a specific file handle. + */ + EFI_SHELL_SET_FILE_INFO SetFileInfo; + + /** + * @brief Given a file name, open a file and return a file handle. + */ + EFI_SHELL_OPEN_FILE_BY_NAME OpenFileByName; + + /** + * @brief Close an open file. + */ + EFI_SHELL_CLOSE_FILE CloseFile; + + /** + * @brief Create a new file. + */ + EFI_SHELL_CREATE_FILE CreateFile; + + /** + * @brief Read data from a file. + */ + EFI_SHELL_READ_FILE ReadFile; + + /** + * @brief Write data to a file. + */ + EFI_SHELL_WRITE_FILE WriteFile; + + /** + * @brief Delete a file. + */ + EFI_SHELL_DELETE_FILE DeleteFile; + + /** + * @brief Delete a file by name. + */ + EFI_SHELL_DELETE_FILE_BY_NAME DeleteFileByName; + + /** + * @brief Change the current read/write position within a file. + */ + EFI_SHELL_GET_FILE_POSITION GetFilePosition; + + /** + * @brief Return the current read/write position within a file. + */ + EFI_SHELL_SET_FILE_POSITION SetFilePosition; + + /** + * @brief Write all buffered data to a file. + */ + EFI_SHELL_FLUSH_FILE FlushFile; + + /** + * @brief Return all files that match a pattern in a file list. + */ + EFI_SHELL_FIND_FILES FindFiles; + + /** + * @brief Return all files in a specified directory in a file list. + */ + EFI_SHELL_FIND_FILES_IN_DIR FindFilesInDir; + + /** + * @brief Return the size of a file. + */ + EFI_SHELL_GET_FILE_SIZE GetFileSize; + + /** + * @brief Return the root directory of a file system. + */ + EFI_SHELL_OPEN_ROOT OpenRoot; + + /** + * @brief Return the root directory of a file system on a particular handle. + */ + EFI_SHELL_OPEN_ROOT_BY_HANDLE OpenRootByHandle; + + /** + * @brief Event signaled by the UEFI Shell when the user presses CTRL-C + * to indicate that the current UEFI Shell command execution should be + * interrupted. + */ + EFI_EVENT ExecutionBreak; + + /** + * @brief This field contains the EFI_SHELL_MAJOR_VERSION value referenced + * in the related definitions section. This will define what functions + * are available in the protocol. + */ + UINT32 MajorVersion; + + /** + * @brief This field contains the EFI_SHELL_MINOR_VERSION value referenced + * in the related definitions section. This will define what functions + * are available in the protocol. + */ + UINT32 MinorVersion; + + /** + * @brief Register a GUID and a localized human readable name for it. + */ + EFI_SHELL_REGISTER_GUID_NAME RegisterGuidName; + + /** + * @brief Get the human readable name for a GUID from the value. + */ + EFI_SHELL_GET_GUID_NAME GetGuidName; + + /** + * @brief Get the GUID value from a human readable name. + */ + EFI_SHELL_GET_GUID_FROM_NAME GetGuidFromName; + + /** + * @brief Gets the environment variable and Attributes. + */ + EFI_SHELL_GET_ENV_EX GetEnvEx; + +} EFI_SHELL_PROTOCOL; + +#endif diff --git a/loader/efi/include/efi/efi_simple_file_system_protocol.h b/loader/efi/include/efi/efi_simple_file_system_protocol.h index 91149a61..7f87f121 100644 --- a/loader/efi/include/efi/efi_simple_file_system_protocol.h +++ b/loader/efi/include/efi/efi_simple_file_system_protocol.h @@ -27,9 +27,9 @@ #ifndef EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_H #define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_H -#include "efi_file_protocol.h" -#include "efi_status.h" -#include "efi_types.h" +#include +#include +#include /** @brief defines the GUID for EFI_SIMPLE_FILE_SYSTEM_PROTOCOL */ #define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ diff --git a/loader/efi/include/efi/efi_simple_text_output_protocol.h b/loader/efi/include/efi/efi_simple_text_output_protocol.h index c3052341..15438d37 100644 --- a/loader/efi/include/efi/efi_simple_text_output_protocol.h +++ b/loader/efi/include/efi/efi_simple_text_output_protocol.h @@ -27,9 +27,9 @@ #ifndef EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_H #define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_H -#include "efi_simple_text_output_mode.h" -#include "efi_status.h" -#include "efi_types.h" +#include +#include +#include /** @brief prototype for _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL */ struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; diff --git a/loader/efi/include/efi/efi_status.h b/loader/efi/include/efi/efi_status.h index 3b3de1b3..a23a08e1 100644 --- a/loader/efi/include/efi/efi_status.h +++ b/loader/efi/include/efi/efi_status.h @@ -27,7 +27,7 @@ #ifndef EFI_STATUS_CODES_H #define EFI_STATUS_CODES_H -#include "efi_types.h" +#include /** @brief Status code. Type UINTN. */ typedef UINTN EFI_STATUS; diff --git a/loader/efi/include/efi/efi_system_table.h b/loader/efi/include/efi/efi_system_table.h index 14d6a93f..b36d5b3d 100644 --- a/loader/efi/include/efi/efi_system_table.h +++ b/loader/efi/include/efi/efi_system_table.h @@ -27,13 +27,13 @@ #ifndef EFI_SYSTEM_TABLE_H #define EFI_SYSTEM_TABLE_H -#include "efi_boot_services.h" -#include "efi_configuration_table.h" -#include "efi_runtime_services.h" -#include "efi_simple_text_input_protocol.h" -#include "efi_simple_text_output_protocol.h" -#include "efi_table_header.h" -#include "efi_types.h" +#include +#include +#include +#include +#include +#include +#include /** @brief Defines EFI_SYSTEM_TABLE_SIGNATURE */ #define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249 diff --git a/loader/efi/include/efi/efi_table_header.h b/loader/efi/include/efi/efi_table_header.h index 05a79041..97e94f5c 100644 --- a/loader/efi/include/efi/efi_table_header.h +++ b/loader/efi/include/efi/efi_table_header.h @@ -27,7 +27,7 @@ #ifndef EFI_TABLE_HEADER_H #define EFI_TABLE_HEADER_H -#include "efi_types.h" +#include /** * @struct EFI_TABLE_HEADER diff --git a/loader/efi/include/efi/extened_processor_information.h b/loader/efi/include/efi/extened_processor_information.h index c6cbafa8..acdc2f98 100644 --- a/loader/efi/include/efi/extened_processor_information.h +++ b/loader/efi/include/efi/extened_processor_information.h @@ -27,7 +27,7 @@ #ifndef EXTENDED_PROCESSOR_INFORMATION_H #define EXTENDED_PROCESSOR_INFORMATION_H -#include "efi_cpu_physical_location2.h" +#include /** @brief Defined in EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo() */ #define CPU_V2_EXTENDED_TOPOLOGY BIT24 diff --git a/loader/efi/include/work_on_cpu_callback.h b/loader/efi/include/work_on_cpu_callback.h new file mode 100644 index 00000000..b875a1e4 --- /dev/null +++ b/loader/efi/include/work_on_cpu_callback.h @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef WORK_ON_CPU_CALLBACK_H +#define WORK_ON_CPU_CALLBACK_H + +#include + +/** + * + * @brief This function is called when the user calls platform_on_each_cpu. + * On each iteration of the CPU, this function calls the user provided + * callback with the signature that we perfer. + * + * + * @param ProcedureArgument stores the params needed to execute the callback + */ +void work_on_cpu_callback(void *const ProcedureArgument); + +#endif diff --git a/loader/efi/include/work_on_cpu_callback_args.h b/loader/efi/include/work_on_cpu_callback_args.h index e73b1fd7..feba8ea8 100644 --- a/loader/efi/include/work_on_cpu_callback_args.h +++ b/loader/efi/include/work_on_cpu_callback_args.h @@ -24,8 +24,8 @@ * SOFTWARE. */ -#ifndef PLATFORM_ON_EACH_CPU_CALLBACK_ARGS_H -#define PLATFORM_ON_EACH_CPU_CALLBACK_ARGS_H +#ifndef PLATFORM_WORK_ON_CPU_CALLBACK_ARGS_H +#define PLATFORM_WORK_ON_CPU_CALLBACK_ARGS_H #include #include diff --git a/loader/efi/include/x64/setup_cr0.h b/loader/efi/include/x64/setup_cr0.h new file mode 100644 index 00000000..54d3557e --- /dev/null +++ b/loader/efi/include/x64/setup_cr0.h @@ -0,0 +1,36 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef SETUP_CR0_H +#define SETUP_CR0_H + +/** + * + * @brief Ensures that CR0 is set up properly. + */ +void setup_cr0(void); + +#endif diff --git a/loader/efi/include/x64/setup_cr4.h b/loader/efi/include/x64/setup_cr4.h new file mode 100644 index 00000000..b13dbb0c --- /dev/null +++ b/loader/efi/include/x64/setup_cr4.h @@ -0,0 +1,36 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef SETUP_CR4_H +#define SETUP_CR4_H + +/** + * + * @brief Ensures that CR4 is set up properly. + */ +void setup_cr4(void); + +#endif diff --git a/loader/efi/include/x64/setup_tss.h b/loader/efi/include/x64/setup_tss.h new file mode 100644 index 00000000..493ae901 --- /dev/null +++ b/loader/efi/include/x64/setup_tss.h @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef SETUP_TSS_H +#define SETUP_TSS_H + +#include + +/** + * + * @brief Ensures that TSS is set up properly. + * + * + * @return Returns 0 on success, LOADER_FAILURE otherwise + */ +int64_t setup_tss(); + +#endif diff --git a/loader/efi/src/arm/aarch64/arch_init.c b/loader/efi/src/arm/aarch64/arch_init.c new file mode 100644 index 00000000..d1b631c3 --- /dev/null +++ b/loader/efi/src/arm/aarch64/arch_init.c @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +/** + * + * @brief Sets up the CPU above and beyond what UEFI has provided. + * + * + * @return Returns 0 on success, LOADER_FAILURE otherwise + */ +int64_t +arch_init(void) +{ + return LOADER_SUCCESS; +} diff --git a/loader/efi/src/arm/aarch64/arch_locate_protocols.c b/loader/efi/src/arm/aarch64/arch_locate_protocols.c new file mode 100644 index 00000000..2b242836 --- /dev/null +++ b/loader/efi/src/arm/aarch64/arch_locate_protocols.c @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +/** + * + * @brief Locates all of the protocols that are needed by this architecture + * + * + * @return returns EFI_SUCCESS on success, and a non-EFI_SUCCESS value on + * failure. + */ +EFI_STATUS +arch_locate_protocols(void) +{ + return EFI_SUCCESS; +} diff --git a/loader/efi/src/arm/aarch64/arch_num_online_cpus.c b/loader/efi/src/arm/aarch64/arch_num_online_cpus.c new file mode 100644 index 00000000..1f404ca7 --- /dev/null +++ b/loader/efi/src/arm/aarch64/arch_num_online_cpus.c @@ -0,0 +1,53 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +/** + * + * @brief Returns the total number of online CPUs on this architecture + * (i.e. PPs) + * + * + * @return Returns the total number of online CPUs on this architecture + * (i.e. PPs) + */ +uint32_t +arch_num_online_cpus(void) +{ + /** + * TODO: + * - Implement multicore support on ARM + */ + + /** + * NOTE: + * - See work_on_cpu for more details as to why this is hard coded + * for now. + */ + + return 1; +} diff --git a/loader/efi/src/arm/aarch64/arch_work_on_cpu.c b/loader/efi/src/arm/aarch64/arch_work_on_cpu.c new file mode 100644 index 00000000..9db35628 --- /dev/null +++ b/loader/efi/src/arm/aarch64/arch_work_on_cpu.c @@ -0,0 +1,93 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +/** + * + * @brief This function is called when the user calls platform_on_each_cpu. + * On each iteration of the CPU, this function calls the user provided + * callback with the signature that we perfer. + * + * + * @param ProcedureArgument stores the params needed to execute the callback + */ +static void +work_on_cpu_callback(void *const ProcedureArgument) +{ + struct work_on_cpu_callback_args *args = + ((struct work_on_cpu_callback_args *)ProcedureArgument); + + args->ret = args->func(args->cpu); +} + +/** + * + * @brief Executes a callback on a specific core on this architecture. + * + * + * @param cpu the core to execute the callback on + * @param callback the callback to call + * @param args the arguments for work_on_cpu_callback + */ +void +arch_work_on_cpu( + uint32_t const cpu, void *const callback, struct work_on_cpu_callback_args *const args) +{ + /** + * NOTE: + * - ARMv8 doesn't support INIT/SIPI, and MP services do not seem to be + * implemented in UEFI yet. ServerReady systems will almost certainly + * need some form of MP services (using ACPI maybe?) so this is likely + * a temporary problem. + * - Unlike x86, ARMv8 starts all of the cores all at the same time, and + * it leaves the process of how to bootstrap each core to the firmware. + * This means that right now, there is no standard way to start up + * each core. On the Raspberry Pi 4, when each core starts, they check + * their processor ID. If it is zero, it boots. If it is not zero, it + * enters an endless loop, waiting for a memory location to be written + * to. The OS is supposed to write the address of a function it wishes to + * be executed to memory locations specific to each core that the core + * is waiting on. It will then jump to this address and continue to + * bootstrap using whatever logic you provide. This will work for now, + * but adding more devices will likely require device specific logic + * here until MP services, or something else like it is ready. + * - The lack of decent standardization on ARM is hands down the biggest + * issue with the CPU. Hopefully the ServerReady specs fix this. + */ + + if (cpu == 0U) { + args->ret = args->func(args->cpu); + } + else { + /** + * TODO: + * - Complete + */ + } +} diff --git a/loader/efi/src/arm/aarch64/demote.S b/loader/efi/src/arm/aarch64/demote.S new file mode 100644 index 00000000..0d2c126f --- /dev/null +++ b/loader/efi/src/arm/aarch64/demote.S @@ -0,0 +1,271 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + /** @brief defines the offset of state_save_t.x0 */ + #define SS_OFFSET_X0 0x000 + /** @brief defines the offset of state_save_t.x19 */ + #define SS_OFFSET_X19 0x098 + /** @brief defines the offset of state_save_t.x20 */ + #define SS_OFFSET_X20 0x0A0 + /** @brief defines the offset of state_save_t.x21 */ + #define SS_OFFSET_X21 0x0A8 + /** @brief defines the offset of state_save_t.x22 */ + #define SS_OFFSET_X22 0x0B0 + /** @brief defines the offset of state_save_t.x23 */ + #define SS_OFFSET_X23 0x0B8 + /** @brief defines the offset of state_save_t.x24 */ + #define SS_OFFSET_X24 0x0C0 + /** @brief defines the offset of state_save_t.x25 */ + #define SS_OFFSET_X25 0x0C8 + /** @brief defines the offset of state_save_t.x26 */ + #define SS_OFFSET_X26 0x0D0 + /** @brief defines the offset of state_save_t.x27 */ + #define SS_OFFSET_X27 0x0D8 + /** @brief defines the offset of state_save_t.x28 */ + #define SS_OFFSET_X28 0x0E0 + /** @brief defines the offset of state_save_t.x29 */ + #define SS_OFFSET_X29 0x0E8 + /** @brief defines the offset of state_save_t.x30 */ + #define SS_OFFSET_X30 0x0F0 + /** @brief defines the offset of state_save_t.sp_el2 */ + #define SS_OFFSET_SP_EL2 0x0F8 + /** @brief defines the offset of state_save_t.pc_el2 */ + #define SS_OFFSET_PC_EL2 0x100 + + /** @brief defines the offset of state_save_t.daif */ + #define SS_OFFSET_DAIF 0x108 + /** @brief defines the offset of state_save_t.spsel */ + #define SS_OFFSET_SPSEL 0x110 + + /** @brief defines the offset of state_save_t.vbar_el2 */ + #define SS_OFFSET_VBAR_EL2 0x188 + + /** @brief defines the offset of state_save_t.hcr_el2 */ + #define SS_OFFSET_HCR_EL2 0x190 + /** @brief defines the offset of state_save_t.mair_el2 */ + #define SS_OFFSET_MAIR_EL2 0x198 + /** @brief defines the offset of state_save_t.sctlr_el2 */ + #define SS_OFFSET_SCTLR_EL2 0x1A0 + /** @brief defines the offset of state_save_t.tcr_el2 */ + #define SS_OFFSET_TCR_EL2 0x1A8 + /** @brief defines the offset of state_save_t.ttbr0_el2 */ + #define SS_OFFSET_TTBR0_EL2 0x1B0 + /** @brief defines the offset of state_save_t.tpidr_el2 */ + #define SS_OFFSET_TPIDR_EL2 0x1B8 + + /**************************************************************************/ + /* demote */ + /**************************************************************************/ + + /** + * + * @brief This function executes the microkernel, demoting the current + * OS into a virtual machine. + * + * + * @param mk_args_t the arguments to pass to the microkernel + * @param mk_state the microkernel's state save + * @param root_vp_state the root vp's state save + * @return 0 on success, LOADER_FAILURE on failure. + */ + + .global demote + .align 12 +demote: + + /**************************************************************************/ + /* Report Success On Completion */ + /**************************************************************************/ + + add x11, x2, #SS_OFFSET_X0 + str xzr, [x11] + + /**************************************************************************/ + /* General Purpose Registers (non-volatile) */ + /**************************************************************************/ + + add x12, x2, #SS_OFFSET_X19 + str x19, [x12] + add x12, x2, #SS_OFFSET_X20 + str x20, [x12] + add x12, x2, #SS_OFFSET_X21 + str x21, [x12] + add x12, x2, #SS_OFFSET_X22 + str x22, [x12] + add x12, x2, #SS_OFFSET_X23 + str x23, [x12] + add x12, x2, #SS_OFFSET_X24 + str x24, [x12] + add x12, x2, #SS_OFFSET_X25 + str x25, [x12] + add x12, x2, #SS_OFFSET_X26 + str x26, [x12] + add x12, x2, #SS_OFFSET_X27 + str x27, [x12] + add x12, x2, #SS_OFFSET_X28 + str x28, [x12] + add x12, x2, #SS_OFFSET_X29 + str x29, [x12] + add x12, x2, #SS_OFFSET_X30 + str x30, [x12] + + mov x10, sp + add x12, x2, #SS_OFFSET_SP_EL2 + str x10, [x12] + + adr x10, demotion_return + add x12, x2, #SS_OFFSET_PC_EL2 + str x10, [x12] + + /**************************************************************************/ + /* Setup */ + /**************************************************************************/ + + mov x20, x0 /* args */ + mov x21, x1 /* mk_state */ + mov x22, x2 /* root_vp_state */ + + /**************************************************************************/ + /* Disable Interrupts */ + /**************************************************************************/ + + mrs x10, hcr_el2 + add x12, x22, #SS_OFFSET_HCR_EL2 + str x10, [x12] + add x11, x21, #SS_OFFSET_HCR_EL2 + ldr x10, [x11] + msr hcr_el2, x10 + + /**************************************************************************/ + /* Saved Program Status Registers (SPSR) */ + /**************************************************************************/ + + /** + * TODO: + * - We probably need to store more of these as we support more ARM + * archiectures. Just depends on whether or not we use the feature + * in the microkernel. For now, this is all we need. + */ + + mrs x10, daif + add x12, x22, #SS_OFFSET_DAIF + str x10, [x12] + add x11, x21, #SS_OFFSET_DAIF + ldr x10, [x11] + msr daif, x10 + + mrs x10, spsel + add x12, x22, #SS_OFFSET_SPSEL + str x10, [x12] + add x11, x21, #SS_OFFSET_SPSEL + ldr x10, [x11] + msr spsel, x10 + + /**************************************************************************/ + /* Exceptions */ + /**************************************************************************/ + + mrs x10, vbar_el2 + add x12, x22, #SS_OFFSET_VBAR_EL2 + str x10, [x12] + add x11, x21, #SS_OFFSET_VBAR_EL2 + ldr x10, [x11] + msr vbar_el2, x10 + + /**************************************************************************/ + /* System Registers */ + /**************************************************************************/ + + mrs x10, mair_el2 + add x12, x22, #SS_OFFSET_MAIR_EL2 + str x10, [x12] + add x11, x21, #SS_OFFSET_MAIR_EL2 + ldr x10, [x11] + msr mair_el2, x10 + + mrs x10, sctlr_el2 + add x12, x22, #SS_OFFSET_SCTLR_EL2 + str x10, [x12] + add x11, x21, #SS_OFFSET_SCTLR_EL2 + ldr x10, [x11] + msr sctlr_el2, x10 + + mrs x10, tcr_el2 + add x12, x22, #SS_OFFSET_TCR_EL2 + str x10, [x12] + add x11, x21, #SS_OFFSET_TCR_EL2 + ldr x10, [x11] + msr tcr_el2, x10 + + mrs x10, ttbr0_el2 + add x12, x22, #SS_OFFSET_TTBR0_EL2 + str x10, [x12] + add x11, x21, #SS_OFFSET_TTBR0_EL2 + ldr x10, [x11] + msr ttbr0_el2, x10 + + tlbi alle2 + isb sy + dsb sy + + mrs x10, tpidr_el2 + add x12, x22, #SS_OFFSET_TPIDR_EL2 + str x10, [x12] + add x11, x21, #SS_OFFSET_TPIDR_EL2 + ldr x10, [x11] + msr tpidr_el2, x10 + + /**************************************************************************/ + /* Stack */ + /**************************************************************************/ + + add x11, x21, #SS_OFFSET_SP_EL2 + ldr x10, [x11] + mov sp, x10 + + /**************************************************************************/ + /* Call Microkernel */ + /**************************************************************************/ + + add x11, x21, #SS_OFFSET_PC_EL2 + ldr x10, [x11] + + mov x0, x20 + ret x10 + +demotion_return: + + /** + * NOTE: + * - If demotion is successful, before we return back to the loader, we + * ensure that at least one exit occurs. This is done to properly handle + * errors with the first VMExit. Specifically, if the first VMExit + * generates a failure, it needs to return to loader. The state in + * the root VP, which is what it will use to return is still the same + * at this point, so a return is safe. + */ + + ret diff --git a/loader/efi/src/arm/aarch64/esr.S b/loader/efi/src/arm/aarch64/esr.S new file mode 100644 index 00000000..50aa4a0f --- /dev/null +++ b/loader/efi/src/arm/aarch64/esr.S @@ -0,0 +1,227 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global esr + .align 12 +esr: + + mov x19, x0 + mov x20, x1 + mov x21, x2 + mov x22, x3 + + mov x0, #'\n' + bl serial_write_c + + mov x0, #'\n' + bl serial_write_c + + mov x0, #'\n' + bl serial_write_c + + /** + * NOTE: + * - output: "exception:" + */ + + mov x0, #'e' + bl serial_write_c + + mov x0, #'x' + bl serial_write_c + + mov x0, #'c' + bl serial_write_c + + mov x0, #'e' + bl serial_write_c + + mov x0, #'p' + bl serial_write_c + + mov x0, #'t' + bl serial_write_c + + mov x0, #'i' + bl serial_write_c + + mov x0, #'o' + bl serial_write_c + + mov x0, #'n' + bl serial_write_c + + mov x0, #':' + bl serial_write_c + + mov x0, #'\n' + bl serial_write_c + + /** + * NOTE: + * - output: " - vec: " + */ + + mov x0, #' ' + bl serial_write_c + + mov x0, #'-' + bl serial_write_c + + mov x0, #' ' + bl serial_write_c + + mov x0, #'v' + bl serial_write_c + + mov x0, #'e' + bl serial_write_c + + mov x0, #'c' + bl serial_write_c + + mov x0, #':' + bl serial_write_c + + mov x0, #' ' + bl serial_write_c + + mov x0, x19 + bl serial_write_hex + + mov x0, #'\n' + bl serial_write_c + + /** + * NOTE: + * - output: " - esr: " + */ + + mov x0, #' ' + bl serial_write_c + + mov x0, #'-' + bl serial_write_c + + mov x0, #' ' + bl serial_write_c + + mov x0, #'e' + bl serial_write_c + + mov x0, #'s' + bl serial_write_c + + mov x0, #'r' + bl serial_write_c + + mov x0, #':' + bl serial_write_c + + mov x0, #' ' + bl serial_write_c + + mov x0, x20 + bl serial_write_hex + + mov x0, #'\n' + bl serial_write_c + + /** + * NOTE: + * - output: " - far: " + */ + + mov x0, #' ' + bl serial_write_c + + mov x0, #'-' + bl serial_write_c + + mov x0, #' ' + bl serial_write_c + + mov x0, #'f' + bl serial_write_c + + mov x0, #'a' + bl serial_write_c + + mov x0, #'r' + bl serial_write_c + + mov x0, #':' + bl serial_write_c + + mov x0, #' ' + bl serial_write_c + + mov x0, x21 + bl serial_write_hex + + mov x0, #'\n' + bl serial_write_c + + /** + * NOTE: + * - output: " - spsr: " + */ + + mov x0, #' ' + bl serial_write_c + + mov x0, #'-' + bl serial_write_c + + mov x0, #' ' + bl serial_write_c + + mov x0, #'s' + bl serial_write_c + + mov x0, #'p' + bl serial_write_c + + mov x0, #'s' + bl serial_write_c + + mov x0, #'e' + bl serial_write_c + + mov x0, #':' + bl serial_write_c + + mov x0, #' ' + bl serial_write_c + + mov x0, x22 + bl serial_write_hex + + mov x0, #'\n' + bl serial_write_c + +loop_forever: + b loop_forever diff --git a/loader/efi/src/arm/aarch64/exception_vectors.S b/loader/efi/src/arm/aarch64/exception_vectors.S new file mode 100644 index 00000000..0ab7aa33 --- /dev/null +++ b/loader/efi/src/arm/aarch64/exception_vectors.S @@ -0,0 +1,157 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global exception_vectors + .align 12 +exception_vectors: + + /* current el with sp_el0, synchronous */ + .align 7 + mov x0, #0x000 + mrs x1, esr_el2 + mrs x2, far_el2 + mrs x3, spsr_el2 + b esr + + /* current el with sp_el0, irq or virq */ + .align 7 + mov x0, #0x080 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr + + /* current el with sp_el0, fiq or vfiq */ + .align 7 + mov x0, #0x100 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr + + /* current el with sp_el0, serror or vserror */ + .align 7 + mov x0, #0x180 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr + + /* current el with sp_elx, synchronous */ + .align 7 + mov x0, #0x200 + mrs x1, esr_el2 + mrs x2, far_el2 + mrs x3, spsr_el2 + b esr + + /* current el with sp_elx, irq or virq */ + .align 7 + mov x0, #0x280 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr + + /* current el with sp_elx, fiq or vfiq */ + .align 7 + mov x0, #0x300 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr + + /* current el with sp_elx, serror or vserror */ + .align 7 + mov x0, #0x380 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr + + /* lower el from aarch64, synchronous */ + .align 7 + mov x0, #0x400 + mrs x1, esr_el2 + mrs x2, far_el2 + mrs x3, spsr_el2 + b esr + + /* lower el from aarch64, irq or virq */ + .align 7 + mov x0, #0x480 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr + + /* lower el from aarch64, fiq or vfiq */ + .align 7 + mov x0, #0x500 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr + + /* lower el from aarch64, serror or vserror */ + .align 7 + mov x0, #0x580 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr + + /* lower el from aarch32, synchronous */ + .align 7 + mov x0, #0x600 + mrs x1, esr_el2 + mrs x2, far_el2 + mrs x3, spsr_el2 + b esr + + /* lower el from aarch32, irq or virq */ + .align 7 + mov x0, #0x680 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr + + /* lower el from aarch32, fiq or vfiq */ + .align 7 + mov x0, #0x700 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr + + /* lower el from aarch32, serror or vserror */ + .align 7 + mov x0, #0x780 + mov x1, xzr + mov x2, xzr + mrs x3, spsr_el2 + b esr diff --git a/loader/efi/src/arm/aarch64/flush_cache.S b/loader/efi/src/arm/aarch64/flush_cache.S new file mode 100644 index 00000000..fe2c9c34 --- /dev/null +++ b/loader/efi/src/arm/aarch64/flush_cache.S @@ -0,0 +1,33 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global flush_cache +flush_cache: + + dc civac, x0 + dsb sy + + ret diff --git a/loader/efi/src/arm/aarch64/memcpy.S b/loader/efi/src/arm/aarch64/memcpy.S new file mode 100644 index 00000000..90519f0c --- /dev/null +++ b/loader/efi/src/arm/aarch64/memcpy.S @@ -0,0 +1,239 @@ +/* + * memcpy - copy memory area + * + * Copyright (c) 2012-2020, Arm Limited. + * SPDX-License-Identifier: MIT + */ + +/* Assumptions: + * + * ARMv8-a, AArch64, unaligned accesses. + * + */ + +#define L(l) .L ## l + +#define dstin x0 +#define src x1 +#define count x2 +#define dst x3 +#define srcend x4 +#define dstend x5 +#define A_l x6 +#define A_lw w6 +#define A_h x7 +#define B_l x8 +#define B_lw w8 +#define B_h x9 +#define C_l x10 +#define C_lw w10 +#define C_h x11 +#define D_l x12 +#define D_h x13 +#define E_l x14 +#define E_h x15 +#define F_l x16 +#define F_h x17 +#define G_l count +#define G_h dst +#define H_l src +#define H_h srcend +#define tmp1 x14 + +/* This implementation handles overlaps and supports both memcpy and memmove + from a single entry point. It uses unaligned accesses and branchless + sequences to keep the code small, simple and improve performance. + + Copies are split into 3 main cases: small copies of up to 32 bytes, medium + copies of up to 128 bytes, and large copies. The overhead of the overlap + check is negligible since it is only required for large copies. + + Large copies use a software pipelined loop processing 64 bytes per iteration. + The destination pointer is 16-byte aligned to minimize unaligned accesses. + The loop tail is handled by always copying 64 bytes from the end. +*/ + + .global memcpy + .align 6 +memcpy: + + add srcend, src, count + add dstend, dstin, count + cmp count, 128 + b.hi L(copy_long) + cmp count, 32 + b.hi L(copy32_128) + + /* Small copies: 0..32 bytes. */ + cmp count, 16 + b.lo L(copy16) + ldp A_l, A_h, [src] + ldp D_l, D_h, [srcend, -16] + stp A_l, A_h, [dstin] + stp D_l, D_h, [dstend, -16] + ret + + /* Copy 8-15 bytes. */ +L(copy16): + tbz count, 3, L(copy8) + ldr A_l, [src] + ldr A_h, [srcend, -8] + str A_l, [dstin] + str A_h, [dstend, -8] + ret + + .p2align 3 + /* Copy 4-7 bytes. */ +L(copy8): + tbz count, 2, L(copy4) + ldr A_lw, [src] + ldr B_lw, [srcend, -4] + str A_lw, [dstin] + str B_lw, [dstend, -4] + ret + + /* Copy 0..3 bytes using a branchless sequence. */ +L(copy4): + cbz count, L(copy0) + lsr tmp1, count, 1 + ldrb A_lw, [src] + ldrb C_lw, [srcend, -1] + ldrb B_lw, [src, tmp1] + strb A_lw, [dstin] + strb B_lw, [dstin, tmp1] + strb C_lw, [dstend, -1] +L(copy0): + ret + + .p2align 4 + /* Medium copies: 33..128 bytes. */ +L(copy32_128): + ldp A_l, A_h, [src] + ldp B_l, B_h, [src, 16] + ldp C_l, C_h, [srcend, -32] + ldp D_l, D_h, [srcend, -16] + cmp count, 64 + b.hi L(copy128) + stp A_l, A_h, [dstin] + stp B_l, B_h, [dstin, 16] + stp C_l, C_h, [dstend, -32] + stp D_l, D_h, [dstend, -16] + ret + + .p2align 4 + /* Copy 65..128 bytes. */ +L(copy128): + ldp E_l, E_h, [src, 32] + ldp F_l, F_h, [src, 48] + cmp count, 96 + b.ls L(copy96) + ldp G_l, G_h, [srcend, -64] + ldp H_l, H_h, [srcend, -48] + stp G_l, G_h, [dstend, -64] + stp H_l, H_h, [dstend, -48] +L(copy96): + stp A_l, A_h, [dstin] + stp B_l, B_h, [dstin, 16] + stp E_l, E_h, [dstin, 32] + stp F_l, F_h, [dstin, 48] + stp C_l, C_h, [dstend, -32] + stp D_l, D_h, [dstend, -16] + ret + + .p2align 4 + /* Copy more than 128 bytes. */ +L(copy_long): + /* Use backwards copy if there is an overlap. */ + sub tmp1, dstin, src + cbz tmp1, L(copy0) + cmp tmp1, count + b.lo L(copy_long_backwards) + + /* Copy 16 bytes and then align dst to 16-byte alignment. */ + + ldp D_l, D_h, [src] + and tmp1, dstin, 15 + bic dst, dstin, 15 + sub src, src, tmp1 + add count, count, tmp1 /* Count is now 16 too large. */ + ldp A_l, A_h, [src, 16] + stp D_l, D_h, [dstin] + ldp B_l, B_h, [src, 32] + ldp C_l, C_h, [src, 48] + ldp D_l, D_h, [src, 64]! + subs count, count, 128 + 16 /* Test and readjust count. */ + b.ls L(copy64_from_end) + +L(loop64): + stp A_l, A_h, [dst, 16] + ldp A_l, A_h, [src, 16] + stp B_l, B_h, [dst, 32] + ldp B_l, B_h, [src, 32] + stp C_l, C_h, [dst, 48] + ldp C_l, C_h, [src, 48] + stp D_l, D_h, [dst, 64]! + ldp D_l, D_h, [src, 64]! + subs count, count, 64 + b.hi L(loop64) + + /* Write the last iteration and copy 64 bytes from the end. */ +L(copy64_from_end): + ldp E_l, E_h, [srcend, -64] + stp A_l, A_h, [dst, 16] + ldp A_l, A_h, [srcend, -48] + stp B_l, B_h, [dst, 32] + ldp B_l, B_h, [srcend, -32] + stp C_l, C_h, [dst, 48] + ldp C_l, C_h, [srcend, -16] + stp D_l, D_h, [dst, 64] + stp E_l, E_h, [dstend, -64] + stp A_l, A_h, [dstend, -48] + stp B_l, B_h, [dstend, -32] + stp C_l, C_h, [dstend, -16] + ret + + .p2align 4 + + /* Large backwards copy for overlapping copies. + Copy 16 bytes and then align dst to 16-byte alignment. */ +L(copy_long_backwards): + ldp D_l, D_h, [srcend, -16] + and tmp1, dstend, 15 + sub srcend, srcend, tmp1 + sub count, count, tmp1 + ldp A_l, A_h, [srcend, -16] + stp D_l, D_h, [dstend, -16] + ldp B_l, B_h, [srcend, -32] + ldp C_l, C_h, [srcend, -48] + ldp D_l, D_h, [srcend, -64]! + sub dstend, dstend, tmp1 + subs count, count, 128 + b.ls L(copy64_from_start) + +L(loop64_backwards): + stp A_l, A_h, [dstend, -16] + ldp A_l, A_h, [srcend, -16] + stp B_l, B_h, [dstend, -32] + ldp B_l, B_h, [srcend, -32] + stp C_l, C_h, [dstend, -48] + ldp C_l, C_h, [srcend, -48] + stp D_l, D_h, [dstend, -64]! + ldp D_l, D_h, [srcend, -64]! + subs count, count, 64 + b.hi L(loop64_backwards) + + /* Write the last iteration and copy 64 bytes from the start. */ +L(copy64_from_start): + ldp G_l, G_h, [src, 48] + stp A_l, A_h, [dstend, -16] + ldp A_l, A_h, [src, 32] + stp B_l, B_h, [dstend, -32] + ldp B_l, B_h, [src, 16] + stp C_l, C_h, [dstend, -48] + ldp C_l, C_h, [src] + stp D_l, D_h, [dstend, -64] + stp G_l, G_h, [dstin, 48] + stp A_l, A_h, [dstin, 32] + stp B_l, B_h, [dstin, 16] + stp C_l, C_h, [dstin] + ret diff --git a/loader/efi/src/arm/aarch64/memset.S b/loader/efi/src/arm/aarch64/memset.S new file mode 100644 index 00000000..1358765d --- /dev/null +++ b/loader/efi/src/arm/aarch64/memset.S @@ -0,0 +1,179 @@ +/* + * memset - fill memory with a constant byte + * + * Copyright (c) 2012, Arm Limited. + * SPDX-License-Identifier: MIT + */ + +/* Assumptions: + * + * ARMv8-a, AArch64, unaligned accesses + * + */ + +#define L(l) .L ## l + +#define dstin x0 +#define val x1 +#define valw w1 +#define count x2 +#define dst x3 +#define dstend x4 +#define tmp1 x5 +#define tmp1w w5 +#define tmp2 x6 +#define tmp2w w6 +#define zva_len x7 +#define zva_lenw w7 + + .global memset + .align 6 +memset: + + dup v0.16B, valw + add dstend, dstin, count + + cmp count, 96 + b.hi L(set_long) + cmp count, 16 + b.hs L(set_medium) + mov val, v0.D[0] + + /* Set 0..15 bytes. */ + tbz count, 3, 1f + str val, [dstin] + str val, [dstend, -8] + ret + nop +1: tbz count, 2, 2f + str valw, [dstin] + str valw, [dstend, -4] + ret +2: cbz count, 3f + strb valw, [dstin] + tbz count, 1, 3f + strh valw, [dstend, -2] +3: ret + + /* Set 17..96 bytes. */ +L(set_medium): + str q0, [dstin] + tbnz count, 6, L(set96) + str q0, [dstend, -16] + tbz count, 5, 1f + str q0, [dstin, 16] + str q0, [dstend, -32] +1: ret + + .p2align 4 + /* Set 64..96 bytes. Write 64 bytes from the start and + 32 bytes from the end. */ +L(set96): + str q0, [dstin, 16] + stp q0, q0, [dstin, 32] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 + nop +L(set_long): + and valw, valw, 255 + bic dst, dstin, 15 + str q0, [dstin] + cmp count, 256 + ccmp valw, 0, 0, cs + b.eq L(try_zva) +L(no_zva): + sub count, dstend, dst /* Count is 16 too large. */ + add dst, dst, 16 + sub count, count, 64 + 16 /* Adjust count and bias for loop. */ +1: stp q0, q0, [dst], 64 + stp q0, q0, [dst, -32] +L(tail64): + subs count, count, 64 + b.hi 1b +2: stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 +L(try_zva): + mrs tmp1, dczid_el0 + tbnz tmp1w, 4, L(no_zva) + and tmp1w, tmp1w, 15 + cmp tmp1w, 4 /* ZVA size is 64 bytes. */ + b.ne L(zva_128) + + /* Write the first and last 64 byte aligned block using stp rather + than using DC ZVA. This is faster on some cores. + */ +L(zva_64): + str q0, [dst, 16] + stp q0, q0, [dst, 32] + bic dst, dst, 63 + stp q0, q0, [dst, 64] + stp q0, q0, [dst, 96] + sub count, dstend, dst /* Count is now 128 too large. */ + sub count, count, 128+64+64 /* Adjust count and bias for loop. */ + add dst, dst, 128 + nop +1: dc zva, dst + add dst, dst, 64 + subs count, count, 64 + b.hi 1b + stp q0, q0, [dst, 0] + stp q0, q0, [dst, 32] + stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 +L(zva_128): + cmp tmp1w, 5 /* ZVA size is 128 bytes. */ + b.ne L(zva_other) + + str q0, [dst, 16] + stp q0, q0, [dst, 32] + stp q0, q0, [dst, 64] + stp q0, q0, [dst, 96] + bic dst, dst, 127 + sub count, dstend, dst /* Count is now 128 too large. */ + sub count, count, 128+128 /* Adjust count and bias for loop. */ + add dst, dst, 128 +1: dc zva, dst + add dst, dst, 128 + subs count, count, 128 + b.hi 1b + stp q0, q0, [dstend, -128] + stp q0, q0, [dstend, -96] + stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + +L(zva_other): + mov tmp2w, 4 + lsl zva_lenw, tmp2w, tmp1w + add tmp1, zva_len, 64 /* Max alignment bytes written. */ + cmp count, tmp1 + blo L(no_zva) + + sub tmp2, zva_len, 1 + add tmp1, dst, zva_len + add dst, dst, 16 + subs count, tmp1, dst /* Actual alignment bytes to write. */ + bic tmp1, tmp1, tmp2 /* Aligned dc zva start address. */ + beq 2f +1: stp q0, q0, [dst], 64 + stp q0, q0, [dst, -32] + subs count, count, 64 + b.hi 1b +2: mov dst, tmp1 + sub count, dstend, tmp1 /* Remaining bytes to write. */ + subs count, count, zva_len + b.lo 4f +3: dc zva, dst + add dst, dst, zva_len + subs count, count, zva_len + b.hs 3b +4: add count, count, zva_len + b L(tail64) diff --git a/loader/efi/src/arm/aarch64/promote.S b/loader/efi/src/arm/aarch64/promote.S new file mode 100644 index 00000000..1b8c538a --- /dev/null +++ b/loader/efi/src/arm/aarch64/promote.S @@ -0,0 +1,189 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + /** @brief defines the offset of state_save_t.x0 */ + #define SS_OFFSET_X0 0x000 + /** @brief defines the offset of state_save_t.x19 */ + #define SS_OFFSET_X19 0x098 + /** @brief defines the offset of state_save_t.x20 */ + #define SS_OFFSET_X20 0x0A0 + /** @brief defines the offset of state_save_t.x21 */ + #define SS_OFFSET_X21 0x0A8 + /** @brief defines the offset of state_save_t.x22 */ + #define SS_OFFSET_X22 0x0B0 + /** @brief defines the offset of state_save_t.x23 */ + #define SS_OFFSET_X23 0x0B8 + /** @brief defines the offset of state_save_t.x24 */ + #define SS_OFFSET_X24 0x0C0 + /** @brief defines the offset of state_save_t.x25 */ + #define SS_OFFSET_X25 0x0C8 + /** @brief defines the offset of state_save_t.x26 */ + #define SS_OFFSET_X26 0x0D0 + /** @brief defines the offset of state_save_t.x27 */ + #define SS_OFFSET_X27 0x0D8 + /** @brief defines the offset of state_save_t.x28 */ + #define SS_OFFSET_X28 0x0E0 + /** @brief defines the offset of state_save_t.x29 */ + #define SS_OFFSET_X29 0x0E8 + /** @brief defines the offset of state_save_t.x30 */ + #define SS_OFFSET_X30 0x0F0 + /** @brief defines the offset of state_save_t.sp_el2 */ + #define SS_OFFSET_SP_EL2 0x0F8 + /** @brief defines the offset of state_save_t.pc_el2 */ + #define SS_OFFSET_PC_EL2 0x100 + + /** @brief defines the offset of state_save_t.daif */ + #define SS_OFFSET_DAIF 0x108 + /** @brief defines the offset of state_save_t.spsel */ + #define SS_OFFSET_SPSEL 0x110 + + /** @brief defines the offset of state_save_t.vbar_el2 */ + #define SS_OFFSET_VBAR_EL2 0x188 + + /** @brief defines the offset of state_save_t.hcr_el2 */ + #define SS_OFFSET_HCR_EL2 0x190 + /** @brief defines the offset of state_save_t.mair_el2 */ + #define SS_OFFSET_MAIR_EL2 0x198 + /** @brief defines the offset of state_save_t.sctlr_el2 */ + #define SS_OFFSET_SCTLR_EL2 0x1A0 + /** @brief defines the offset of state_save_t.tcr_el2 */ + #define SS_OFFSET_TCR_EL2 0x1A8 + /** @brief defines the offset of state_save_t.ttbr0_el2 */ + #define SS_OFFSET_TTBR0_EL2 0x1B0 + /** @brief defines the offset of state_save_t.tpidr_el2 */ + #define SS_OFFSET_TPIDR_EL2 0x1B8 + + .global promote + .align 12 +promote: + + /**************************************************************************/ + /* Stack */ + /**************************************************************************/ + + add x12, x2, #SS_OFFSET_SP_EL2 + ldr x10, [x12] + mov sp, x10 + + /**************************************************************************/ + /* System Registers */ + /**************************************************************************/ + + add x12, x2, #SS_OFFSET_TPIDR_EL2 + ldr x10, [x12] + msr tpidr_el2, x10 + + add x12, x2, #SS_OFFSET_TTBR0_EL2 + ldr x10, [x12] + msr ttbr0_el2, x10 + + tlbi alle2 + isb sy + dsb sy + + add x12, x2, #SS_OFFSET_TCR_EL2 + ldr x10, [x12] + msr tcr_el2, x10 + + add x12, x2, #SS_OFFSET_SCTLR_EL2 + ldr x10, [x12] + msr sctlr_el2, x10 + + add x12, x2, #SS_OFFSET_MAIR_EL2 + ldr x10, [x12] + msr mair_el2, x10 + + /**************************************************************************/ + /* Exceptions */ + /**************************************************************************/ + + add x12, x2, #SS_OFFSET_VBAR_EL2 + ldr x10, [x12] + msr vbar_el2, x10 + + /**************************************************************************/ + /* Saved Program Status Registers (SPSR) */ + /**************************************************************************/ + + /** + * TODO: + * - We probably need to restore more of these as we support more ARM + * archiectures. Just depends on whether or not we use the feature + * in the microkernel. For now, this is all we need. + */ + + add x12, x2, #SS_OFFSET_DAIF + ldr x10, [x12] + msr daif, x10 + + add x12, x2, #SS_OFFSET_SPSEL + ldr x10, [x12] + msr spsel, x10 + + /**************************************************************************/ + /* Enable Interrupts */ + /**************************************************************************/ + + add x12, x2, #SS_OFFSET_HCR_EL2 + ldr x10, [x12] + msr hcr_el2, x10 + + /**************************************************************************/ + /* General Purpose Registers (non-volatile) */ + /**************************************************************************/ + + add x12, x2, #SS_OFFSET_PC_EL2 + ldr x10, [x12] + + add x12, x2, #SS_OFFSET_X30 + ldr x30, [x12] + add x12, x2, #SS_OFFSET_X29 + ldr x29, [x12] + add x12, x2, #SS_OFFSET_X28 + ldr x28, [x12] + add x12, x2, #SS_OFFSET_X27 + ldr x27, [x12] + add x12, x2, #SS_OFFSET_X26 + ldr x26, [x12] + add x12, x2, #SS_OFFSET_X25 + ldr x25, [x12] + add x12, x2, #SS_OFFSET_X24 + ldr x24, [x12] + add x12, x2, #SS_OFFSET_X23 + ldr x23, [x12] + add x12, x2, #SS_OFFSET_X22 + ldr x22, [x12] + add x12, x2, #SS_OFFSET_X21 + ldr x21, [x12] + add x12, x2, #SS_OFFSET_X20 + ldr x20, [x12] + add x12, x2, #SS_OFFSET_X19 + ldr x19, [x12] + + add x12, x2, #SS_OFFSET_X0 + ldr x0, [x12] + + ret x10 diff --git a/loader/efi/src/arm/aarch64/read_currentel.S b/loader/efi/src/arm/aarch64/read_currentel.S new file mode 100644 index 00000000..53c35cb2 --- /dev/null +++ b/loader/efi/src/arm/aarch64/read_currentel.S @@ -0,0 +1,31 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global read_currentel +read_currentel: + + mrs x0, CurrentEL + ret diff --git a/loader/efi/src/arm/aarch64/read_daif.S b/loader/efi/src/arm/aarch64/read_daif.S new file mode 100644 index 00000000..6dd3abde --- /dev/null +++ b/loader/efi/src/arm/aarch64/read_daif.S @@ -0,0 +1,31 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global read_daif +read_daif: + + mrs x0, daif + ret diff --git a/loader/efi/src/arm/aarch64/read_hcr_el2.S b/loader/efi/src/arm/aarch64/read_hcr_el2.S new file mode 100644 index 00000000..8ec0a134 --- /dev/null +++ b/loader/efi/src/arm/aarch64/read_hcr_el2.S @@ -0,0 +1,31 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global read_hcr_el2 +read_hcr_el2: + + mrs x0, hcr_el2 + ret diff --git a/loader/efi/src/arm/aarch64/read_mair_el2.S b/loader/efi/src/arm/aarch64/read_mair_el2.S new file mode 100644 index 00000000..08ae44e6 --- /dev/null +++ b/loader/efi/src/arm/aarch64/read_mair_el2.S @@ -0,0 +1,31 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global read_mair_el2 +read_mair_el2: + + mrs x0, mair_el2 + ret diff --git a/loader/efi/src/arm/aarch64/read_sctlr_el2.S b/loader/efi/src/arm/aarch64/read_sctlr_el2.S new file mode 100644 index 00000000..17a02dbd --- /dev/null +++ b/loader/efi/src/arm/aarch64/read_sctlr_el2.S @@ -0,0 +1,31 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global read_sctlr_el2 +read_sctlr_el2: + + mrs x0, sctlr_el2 + ret diff --git a/loader/efi/src/arm/aarch64/read_spsel.S b/loader/efi/src/arm/aarch64/read_spsel.S new file mode 100644 index 00000000..0b28533d --- /dev/null +++ b/loader/efi/src/arm/aarch64/read_spsel.S @@ -0,0 +1,31 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global read_spsel +read_spsel: + + mrs x0, spsel + ret diff --git a/loader/efi/src/arm/aarch64/read_tcr_el2.S b/loader/efi/src/arm/aarch64/read_tcr_el2.S new file mode 100644 index 00000000..855c68f6 --- /dev/null +++ b/loader/efi/src/arm/aarch64/read_tcr_el2.S @@ -0,0 +1,31 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global read_tcr_el2 +read_tcr_el2: + + mrs x0, tcr_el2 + ret diff --git a/loader/efi/src/arm/aarch64/read_ttbr0_el2.S b/loader/efi/src/arm/aarch64/read_ttbr0_el2.S new file mode 100644 index 00000000..b5c47db8 --- /dev/null +++ b/loader/efi/src/arm/aarch64/read_ttbr0_el2.S @@ -0,0 +1,31 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global read_ttbr0_el2 +read_ttbr0_el2: + + mrs x0, ttbr0_el2 + ret diff --git a/loader/efi/src/arm/aarch64/read_vbar_el2.S b/loader/efi/src/arm/aarch64/read_vbar_el2.S new file mode 100644 index 00000000..65e67e6a --- /dev/null +++ b/loader/efi/src/arm/aarch64/read_vbar_el2.S @@ -0,0 +1,31 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global read_vbar_el2 +read_vbar_el2: + + mrs x0, vbar_el2 + ret diff --git a/loader/efi/src/arm/aarch64/serial_write_c.S b/loader/efi/src/arm/aarch64/serial_write_c.S new file mode 100644 index 00000000..7ae420ca --- /dev/null +++ b/loader/efi/src/arm/aarch64/serial_write_c.S @@ -0,0 +1,49 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define ASSEMBLY +#include + + .global serial_write_c + .align 12 +serial_write_c: + stp x0, x1, [sp, #-0x10]! + +wait_for_ffio_empty: + movz x1, #HYPERVISOR_SERIAL_PORTL + movk x1, #HYPERVISOR_SERIAL_PORTH, LSL #16 + add x1, x1, #0x18 + ldr x1, [x1] + + and x1, x1, #0x20 + cbnz x1, wait_for_ffio_empty + + movz x1, #HYPERVISOR_SERIAL_PORTL + movk x1, #HYPERVISOR_SERIAL_PORTH, LSL #16 + str x0, [x1] + + ldp x0, x1, [sp], #0x10 + ret diff --git a/loader/efi/src/arm/aarch64/serial_write_hex.S b/loader/efi/src/arm/aarch64/serial_write_hex.S new file mode 100644 index 00000000..65ae8846 --- /dev/null +++ b/loader/efi/src/arm/aarch64/serial_write_hex.S @@ -0,0 +1,114 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .global serial_write_hex + .align 12 +serial_write_hex: + stp x29, x30, [sp, #-0x10]! + stp x19, x20, [sp, #-0x10]! + stp x0, x1, [sp, #-0x10]! + + mov x19, x0 + mov x20, #0xF + + mov x0, #0x30 + bl serial_write_c + + mov x0, #0x78 + bl serial_write_c + + and x0, x20, x19, LSR #60 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #56 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #52 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #48 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #44 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #40 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #36 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #32 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #28 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #24 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #20 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #16 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #12 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #8 + bl serial_write_hex_digit + + and x0, x20, x19, LSR #4 + bl serial_write_hex_digit + + and x0, x20, x19 + bl serial_write_hex_digit + + ldp x0, x1, [sp], #0x10 + ldp x19, x20, [sp], #0x10 + ldp x29, x30, [sp], #0x10 + ret + +serial_write_hex_digit: + stp x29, x30, [sp, #-0x10]! + + cmp x0, #9 + bgt serial_write_hex_digit_a_to_f + + add x0, x0, #0x30 + bl serial_write_c + + ldp x29, x30, [sp], #0x10 + ret + +serial_write_hex_digit_a_to_f: + + add x0, x0, #0x37 + bl serial_write_c + + ldp x29, x30, [sp], #0x10 + ret diff --git a/loader/efi/src/entry.c b/loader/efi/src/entry.c index d920f791..1291dfcb 100644 --- a/loader/efi/src/entry.c +++ b/loader/efi/src/entry.c @@ -24,26 +24,35 @@ * SOFTWARE. */ +#include #include -#include +#include +#include #include #include #include #include #include +#include #include #include #include #include +/** + * NOTE: + * - We always return EFI_SUCCESS, even on failure as on some systems, + * returning something else will cause the system to halt. + */ + /** @brief defines the global pointer to the EFI_SYSTEM_TABLE */ EFI_SYSTEM_TABLE *g_st = NULL; -/** @brief defines the global pointer to the EFI_MP_SERVICES_PROTOCOL */ -EFI_MP_SERVICES_PROTOCOL *g_mp_services_protocol = NULL; +/** @brief defines the global pointer to the EFI_SHELL_PROTOCOL */ +EFI_SHELL_PROTOCOL *g_shell_protocol = NULL; /** @brief defines the global pointer to the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL */ -EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *g_simple_file_system = NULL; +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *g_simple_file_system_protocol = NULL; /** * @@ -123,12 +132,12 @@ EFI_STATUS read_file(EFI_FILE_PROTOCOL *const file_protocol, CHAR16 *const filename, struct span_t *const file) { EFI_STATUS status = EFI_SUCCESS; - EFI_FILE_PROTOCOL *hndl = NULL; + SHELL_FILE_HANDLE hndl = NULL; - status = file_protocol->Open(file_protocol, &hndl, filename, EFI_FILE_MODE_READ, EFI_FILE_NONE); + status = g_shell_protocol->OpenFileByName(filename, &hndl, EFI_FILE_MODE_READ); if (EFI_ERROR(status)) { - bferror_x64("Open failed", status); - goto open_failed; + bferror_x64("OpenFileByName failed", status); + goto get_file_size_failed; } status = get_file_size(file_protocol, hndl, &file->size); @@ -177,18 +186,24 @@ EFI_STATUS locate_protocols(void) { EFI_STATUS status = EFI_SUCCESS; - EFI_GUID efi_mp_services_protocol_guid = EFI_MP_SERVICES_PROTOCOL_GUID; + EFI_GUID efi_shell_protocol_guid = EFI_SHELL_PROTOCOL_GUID; EFI_GUID efi_simple_file_system_protocol_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; - status = g_st->BootServices->LocateProtocol( - &efi_mp_services_protocol_guid, NULL, (VOID **)&g_mp_services_protocol); + status = arch_locate_protocols(); if (EFI_ERROR(status)) { - bferror_x64("LocateProtocol EFI_MP_SERVICES_PROTOCOL failed", status); + bferror_x64("arch_locate_protocols failed", status); return status; } status = g_st->BootServices->LocateProtocol( - &efi_simple_file_system_protocol_guid, NULL, (VOID **)&g_simple_file_system); + &efi_shell_protocol_guid, NULL, (VOID **)&g_shell_protocol); + if (EFI_ERROR(status)) { + bferror_x64("LocateProtocol EFI_SHELL_PROTOCOL failed", status); + return status; + } + + status = g_st->BootServices->LocateProtocol( + &efi_simple_file_system_protocol_guid, NULL, (VOID **)&g_simple_file_system_protocol); if (EFI_ERROR(status)) { bferror_x64("LocateProtocol EFI_SIMPLE_FILE_SYSTEM_PROTOCOL failed", status); return status; @@ -212,19 +227,21 @@ load_images_and_start(void) EFI_FILE_PROTOCOL *file_protocol = NULL; struct start_vmm_args_t start_args = {0}; - status = g_simple_file_system->OpenVolume(g_simple_file_system, &file_protocol); + status = + g_simple_file_system_protocol->OpenVolume(g_simple_file_system_protocol, &file_protocol); if (EFI_ERROR(status)) { bferror_x64("OpenVolume failed", status); return status; } - status = read_file(file_protocol, L"bareflank_kernel", &start_args.mk_elf_file); + status = read_file(file_protocol, L"fs0:\\bareflank_kernel", &start_args.mk_elf_file); if (EFI_ERROR(status)) { bferror_x64("open_kernel failed", status); return status; } - status = read_file(file_protocol, L"bareflank_extension0", &(start_args.ext_elf_files[0])); + status = + read_file(file_protocol, L"fs0:\\bareflank_extension0", &(start_args.ext_elf_files[0])); if (EFI_ERROR(status)) { bferror_x64("open_extensions failed", status); return status; @@ -241,6 +258,8 @@ load_images_and_start(void) return EFI_SUCCESS; } +void serial_write_hex(uint64_t const val); + /** * * @brief Defines the main EFI entry pointer @@ -266,69 +285,31 @@ efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) g_st = SystemTable; if (g_st->Hdr.Revision < EFI_1_10_SYSTEM_TABLE_REVISION) { g_st->ConOut->OutputString(g_st->ConOut, L"EFI version not supported\r\n"); - return EFI_UNSUPPORTED; + return EFI_SUCCESS; } serial_init(); - /** - * TODO: - * - Need to process the command line arguments so that we can load - * an image that the user provides. - * - Also need to add a CMAKE var for where to load the UEFI stuff. - */ - - if (loader_init()) { - bferror("loader_init failed"); - return EFI_LOAD_ERROR; - } - status = locate_protocols(); if (EFI_ERROR(status)) { bferror_x64("locate_protocols failed", status); - return status; + return EFI_SUCCESS; + } + + if (loader_init()) { + bferror("loader_init failed"); + return EFI_SUCCESS; } status = load_images_and_start(); if (EFI_ERROR(status)) { bferror_x64("load_images_and_start failed", status); - return status; + platform_dump_vmm(); + return EFI_SUCCESS; } + platform_dump_vmm(); + g_st->ConOut->OutputString(g_st->ConOut, L"bareflank successfully started\r\n"); return EFI_SUCCESS; } - -/** - * - * @brief Same as std::memcpy. - * - * - * @param dst a pointer to the memory to copy to - * @param src a pointer to the memory to copy from - * @param count the total number of bytes to copy - * @return Returns the same result as std::memcpy. - */ -void * -memcpy(void *const dst, void const *const src, uint64_t const count) -{ - g_st->BootServices->CopyMem(dst, ((VOID *)src), count); - return dst; -} - -/** - * - * @brief Same as std::memset. - * - * - * @param dst a pointer to the memory to set - * @param ch the value to set the memory to - * @param num the total number of bytes to set - * @return Returns the same result as std::memset. - */ -void * -memset(void *const dst, char const ch, uint64_t const num) -{ - g_st->BootServices->SetMem(dst, num, ((UINT8)ch)); - return dst; -} diff --git a/loader/efi/src/platform.c b/loader/efi/src/platform.c index 988b821b..b8e0f46f 100644 --- a/loader/efi/src/platform.c +++ b/loader/efi/src/platform.c @@ -24,14 +24,17 @@ * SOFTWARE. */ +#include +#include +#include #include #include -#include #include #include #include +#include #include -#include +#include /** * @@ -91,30 +94,9 @@ platform_alloc(uint64_t size) * Returns a nullptr on failure. */ void * -platform_alloc_contiguous(uint64_t size) +platform_alloc_contiguous(uint64_t const size) { - EFI_STATUS status = EFI_SUCCESS; - EFI_PHYSICAL_ADDRESS ret = ((EFI_PHYSICAL_ADDRESS)0); - - if (((uint64_t)0) == size) { - bferror("invalid number of bytes (i.e., size)"); - return NULL; - } - - if (((uint64_t)0) != (size & (HYPERVISOR_PAGE_SIZE - ((uint64_t)1)))) { - size += HYPERVISOR_PAGE_SIZE; - size &= ~(HYPERVISOR_PAGE_SIZE - ((uint64_t)1)); - } - - status = g_st->BootServices->AllocatePages( - AllocateAnyPages, EfiRuntimeServicesData, size / HYPERVISOR_PAGE_SIZE, &ret); - if (EFI_ERROR(status)) { - bferror_x64("AllocatePages failed", status); - return NULL; - } - - g_st->BootServices->SetMem((void *)ret, size, ((UINT8)0)); - return (void *)ret; + return platform_alloc(size); } /** @@ -130,12 +112,15 @@ platform_alloc_contiguous(uint64_t size) * may or may not be ignored depending on the platform. */ void -platform_free(void const *const ptr, uint64_t const size) +platform_free(void const *const ptr, uint64_t size) { - (void)size; + if (((uint64_t)0) != (size & (HYPERVISOR_PAGE_SIZE - ((uint64_t)1)))) { + size += HYPERVISOR_PAGE_SIZE; + size &= ~(HYPERVISOR_PAGE_SIZE - ((uint64_t)1)); + } if (NULL != ptr) { - g_st->BootServices->FreePool((VOID *)ptr); + g_st->BootServices->FreePages((EFI_PHYSICAL_ADDRESS)ptr, size / HYPERVISOR_PAGE_SIZE); } } @@ -154,11 +139,7 @@ platform_free(void const *const ptr, uint64_t const size) void platform_free_contiguous(void const *const ptr, uint64_t const size) { - (void)size; - - if (NULL != ptr) { - g_st->BootServices->FreePool((VOID *)ptr); - } + platform_free(ptr, size); } /** @@ -234,14 +215,14 @@ platform_memcpy(void *const dst, void const *const src, uint64_t const num) /** * * @brief Copies "num" bytes from "src" to "dst". If "src" or "dst" are - * NULL, returns FAILURE, otherwise returns 0. Note that this function can + * NULL, returns LOADER_FAILURE, otherwise returns 0. Note that this function can * be used to copy memory from userspace via an IOCTL. * * * @param dst a pointer to the memory to copy to * @param src a pointer to the memory to copy from * @param num the number of bytes to copy - * @return If "src" or "dst" are NULL, returns FAILURE, otherwise + * @return If "src" or "dst" are NULL, returns LOADER_FAILURE, otherwise * returns 0. */ int64_t @@ -264,14 +245,14 @@ platform_copy_from_user(void *const dst, void const *const src, uint64_t const n /** * * @brief Copies "num" bytes from "src" to "dst". If "src" or "dst" are - * NULL, returns FAILURE, otherwise returns 0. Note that this function can + * NULL, returns LOADER_FAILURE, otherwise returns 0. Note that this function can * be used to copy memory to userspace via an IOCTL. * * * @param dst a pointer to the memory to copy to * @param src a pointer to the memory to copy from * @param num the number of bytes to copy - * @return If "src" or "dst" are NULL, returns FAILURE, otherwise + * @return If "src" or "dst" are NULL, returns LOADER_FAILURE, otherwise * returns 0. */ int64_t @@ -301,36 +282,7 @@ platform_copy_to_user(void *const dst, void const *const src, uint64_t const num uint32_t platform_num_online_cpus(void) { - EFI_STATUS status = EFI_SUCCESS; - UINTN NumberOfProcessors; - UINTN NumberOfEnabledProcessors; - - status = g_mp_services_protocol->GetNumberOfProcessors( - g_mp_services_protocol, &NumberOfProcessors, &NumberOfEnabledProcessors); - if (EFI_ERROR(status)) { - bferror_x64("GetNumberOfProcessors failed", status); - return ((uint32_t)0); - } - - return (uint32_t)NumberOfProcessors; -} - -/** - * - * @brief This function is called when the user calls platform_on_each_cpu. - * On each iteration of the CPU, this function calls the user provided - * callback with the signature that we perfer. - * - * - * @param ProcedureArgument stores the params needed to execute the callback - */ -static void -work_on_cpu_callback(void *const ProcedureArgument) -{ - struct work_on_cpu_callback_args *args = - ((struct work_on_cpu_callback_args *)ProcedureArgument); - - args->ret = args->func(args->cpu); + return arch_num_online_cpus(); } /** @@ -345,18 +297,7 @@ work_on_cpu_callback(void *const ProcedureArgument) void work_on_cpu(uint32_t const cpu, void *const callback, struct work_on_cpu_callback_args *const args) { - if (cpu == 0U) { - args->ret = args->func(args->cpu); - } - else { - EFI_STATUS status = g_mp_services_protocol->StartupThisAP( - g_mp_services_protocol, callback, cpu, NULL, 0, args, NULL); - - if (EFI_ERROR(status)) { - bferror_x64("StartupThisAP failed", status); - args->ret = LOADER_FAILURE; - } - } + arch_work_on_cpu(cpu, callback, args); } /** @@ -421,3 +362,49 @@ platform_on_each_cpu(platform_per_cpu_func const func, uint32_t const order) return ret; } + +/** + * + * @brief Dumps the contents of the VMM's ring buffer. + */ +void +platform_dump_vmm(void) +{ + uint64_t epos = g_mk_debug_ring->epos; + uint64_t spos = g_mk_debug_ring->spos; + + if (!(HYPERVISOR_DEBUG_RING_SIZE > epos)) { + epos = ((uint64_t)0); + } + + if (spos == epos) { + console_write("no debug data to dump\r\n"); + return; + } + + while (spos != epos) { + if (!(HYPERVISOR_DEBUG_RING_SIZE > spos)) { + spos = ((uint64_t)0); + } + + console_write_c(g_mk_debug_ring->buf[spos]); + ++spos; + } + + console_write("\r\n"); +} + +/** + * + * @brief Initializes the archiecture. Some platforms might need per CPU + * initialization logic to get the CPU set up. Most platforms ignore + * calls to this function + * + * + * @return Returns 0 on success, LOADER_FAILURE otherwise + */ +int64_t +platform_arch_init(void) +{ + return arch_init(); +} diff --git a/loader/efi/src/work_on_cpu_callback.c b/loader/efi/src/work_on_cpu_callback.c new file mode 100644 index 00000000..a93d8018 --- /dev/null +++ b/loader/efi/src/work_on_cpu_callback.c @@ -0,0 +1,46 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +/** + * + * @brief This function is called when the user calls platform_on_each_cpu. + * On each iteration of the CPU, this function calls the user provided + * callback with the signature that we perfer. + * + * + * @param ProcedureArgument stores the params needed to execute the callback + */ +void +work_on_cpu_callback(void *const ProcedureArgument) +{ + struct work_on_cpu_callback_args *args = + ((struct work_on_cpu_callback_args *)ProcedureArgument); + + args->ret = args->func(args->cpu); +} diff --git a/loader/efi/src/x64/amd/setup_cr0.c b/loader/efi/src/x64/amd/setup_cr0.c new file mode 100644 index 00000000..f5570d02 --- /dev/null +++ b/loader/efi/src/x64/amd/setup_cr0.c @@ -0,0 +1,33 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * + * @brief Ensures that CR0 is set up properly. + */ +void +setup_cr0(void) +{} diff --git a/loader/efi/src/x64/amd/setup_cr4.c b/loader/efi/src/x64/amd/setup_cr4.c new file mode 100644 index 00000000..81f3315e --- /dev/null +++ b/loader/efi/src/x64/amd/setup_cr4.c @@ -0,0 +1,33 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * + * @brief Ensures that CR4 is set up properly. + */ +void +setup_cr4(void) +{} diff --git a/loader/efi/src/x64/arch_init.c b/loader/efi/src/x64/arch_init.c new file mode 100644 index 00000000..5c3d5291 --- /dev/null +++ b/loader/efi/src/x64/arch_init.c @@ -0,0 +1,60 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + +/** + * + * @brief Sets up the CPU above and beyond what UEFI has provided. + * + * + * @return Returns 0 on success, LOADER_FAILURE otherwise + */ +int64_t +arch_init(void) +{ + /** + * TODO: + * - The arch_init() logic needs an additional function to enable as many + * hardward security features as possible. For example, SMEP/SMAP. Right + * now all it does is ensure that CR0/CR4 are configured to support + * virtualization. The values that UEFI sets up however are what the + * microkernel will inherit and use so the UEFI loader needs to turn as + * many of these features on as possible so that the microkernel can + * use them. Once virtualization is started, the root OS can configure + * itself however it wants, which will not affect the microkernel unless + * the feature is outside of the control of the VMCS/VMCB, in which + * case it will be up to the extension to deal with. + */ + + setup_cr0(); + setup_cr4(); + + return setup_tss(); +} diff --git a/loader/efi/src/x64/arch_locate_protocols.c b/loader/efi/src/x64/arch_locate_protocols.c new file mode 100644 index 00000000..28726908 --- /dev/null +++ b/loader/efi/src/x64/arch_locate_protocols.c @@ -0,0 +1,58 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +/** @brief defines the global pointer to the EFI_MP_SERVICES_PROTOCOL */ +EFI_MP_SERVICES_PROTOCOL *g_mp_services_protocol = NULL; + +/** + * + * @brief Locates all of the protocols that are needed by this architecture + * + * + * @return returns EFI_SUCCESS on success, and a non-EFI_SUCCESS value on + * failure. + */ +EFI_STATUS +arch_locate_protocols(void) +{ + EFI_STATUS status = EFI_SUCCESS; + EFI_GUID efi_mp_services_protocol_guid = EFI_MP_SERVICES_PROTOCOL_GUID; + + status = g_st->BootServices->LocateProtocol( + &efi_mp_services_protocol_guid, NULL, (VOID **)&g_mp_services_protocol); + if (EFI_ERROR(status)) { + bferror_x64("LocateProtocol EFI_MP_SERVICES_PROTOCOL failed", status); + return status; + } + + return EFI_SUCCESS; +} diff --git a/loader/efi/src/x64/arch_num_online_cpus.c b/loader/efi/src/x64/arch_num_online_cpus.c new file mode 100644 index 00000000..7b23a7a3 --- /dev/null +++ b/loader/efi/src/x64/arch_num_online_cpus.c @@ -0,0 +1,57 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +/** + * + * @brief Returns the total number of online CPUs on this architecture + * (i.e. PPs) + * + * + * @return Returns the total number of online CPUs on this architecture + * (i.e. PPs) + */ +uint32_t +arch_num_online_cpus(void) +{ + EFI_STATUS status = EFI_SUCCESS; + UINTN NumberOfProcessors; + UINTN NumberOfEnabledProcessors; + + status = g_mp_services_protocol->GetNumberOfProcessors( + g_mp_services_protocol, &NumberOfProcessors, &NumberOfEnabledProcessors); + if (EFI_ERROR(status)) { + bferror_x64("GetNumberOfProcessors failed", status); + return ((uint32_t)0); + } + + return (uint32_t)NumberOfProcessors; +} diff --git a/loader/efi/src/x64/arch_work_on_cpu.c b/loader/efi/src/x64/arch_work_on_cpu.c new file mode 100644 index 00000000..6257ba3c --- /dev/null +++ b/loader/efi/src/x64/arch_work_on_cpu.c @@ -0,0 +1,58 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +/** + * + * @brief Executes a callback on a specific core on this architecture. + * + * + * @param cpu the core to execute the callback on + * @param callback the callback to call + * @param args the arguments for work_on_cpu_callback + */ +void +arch_work_on_cpu( + uint32_t const cpu, void *const callback, struct work_on_cpu_callback_args *const args) +{ + if (cpu == 0U) { + args->ret = args->func(args->cpu); + } + else { + EFI_STATUS status = g_mp_services_protocol->StartupThisAP( + g_mp_services_protocol, callback, cpu, NULL, 0, args, NULL); + + if (EFI_ERROR(status)) { + bferror_x64("StartupThisAP failed", status); + args->ret = LOADER_FAILURE; + } + } +} diff --git a/loader/efi/src/x64/demote.S b/loader/efi/src/x64/demote.S index c72e74fc..ac146e2d 100644 --- a/loader/efi/src/x64/demote.S +++ b/loader/efi/src/x64/demote.S @@ -24,6 +24,128 @@ * SOFTWARE. */ + /** @brief defines the offset of state_save_t.rax */ + #define SS_OFFSET_RAX 0x000 + /** @brief defines the offset of state_save_t.rbx */ + #define SS_OFFSET_RBX 0x008 + /** @brief defines the offset of state_save_t.rcx */ + #define SS_OFFSET_RCX 0x010 + /** @brief defines the offset of state_save_t.rdx */ + #define SS_OFFSET_RDX 0x018 + /** @brief defines the offset of state_save_t.rbp */ + #define SS_OFFSET_RBP 0x020 + /** @brief defines the offset of state_save_t.rsi */ + #define SS_OFFSET_RSI 0x028 + /** @brief defines the offset of state_save_t.rdi */ + #define SS_OFFSET_RDI 0x030 + /** @brief defines the offset of state_save_t.r8 */ + #define SS_OFFSET_R8 0x038 + /** @brief defines the offset of state_save_t.r9 */ + #define SS_OFFSET_R9 0x040 + /** @brief defines the offset of state_save_t.r10 */ + #define SS_OFFSET_R10 0x048 + /** @brief defines the offset of state_save_t.r11 */ + #define SS_OFFSET_R11 0x050 + /** @brief defines the offset of state_save_t.r12 */ + #define SS_OFFSET_R12 0x058 + /** @brief defines the offset of state_save_t.r13 */ + #define SS_OFFSET_R13 0x060 + /** @brief defines the offset of state_save_t.r14 */ + #define SS_OFFSET_R14 0x068 + /** @brief defines the offset of state_save_t.r15 */ + #define SS_OFFSET_R15 0x070 + /** @brief defines the offset of state_save_t.rip */ + #define SS_OFFSET_RIP 0x078 + /** @brief defines the offset of state_save_t.rsp */ + #define SS_OFFSET_RSP 0x080 + /** @brief defines the offset of state_save_t.rflags */ + #define SS_OFFSET_RFLAGS 0x088 + /** @brief defines the offset of state_save_t.gdtr */ + #define SS_OFFSET_GDTR 0x0A0 + /** @brief defines the offset of state_save_t.idtr */ + #define SS_OFFSET_IDTR 0x0B0 + /** @brief defines the offset of state_save_t.es_selector */ + #define SS_OFFSET_ES_SELECTOR 0x0C0 + /** @brief defines the offset of state_save_t.cs_selector */ + #define SS_OFFSET_CS_SELECTOR 0x0D0 + /** @brief defines the offset of state_save_t.ss_selector */ + #define SS_OFFSET_SS_SELECTOR 0x0E0 + /** @brief defines the offset of state_save_t.ds_selector */ + #define SS_OFFSET_DS_SELECTOR 0x0F0 + /** @brief defines the offset of state_save_t.fs_selector */ + #define SS_OFFSET_FS_SELECTOR 0x100 + /** @brief defines the offset of state_save_t.gs_selector */ + #define SS_OFFSET_GS_SELECTOR 0x110 + /** @brief defines the offset of state_save_t.ldtr_selector */ + #define SS_OFFSET_LDTR_SELECTOR 0x120 + /** @brief defines the offset of state_save_t.tr_selector */ + #define SS_OFFSET_TR_SELECTOR 0x130 + /** @brief defines the offset of state_save_t.cr0 */ + #define SS_OFFSET_CR0 0x140 + /** @brief defines the offset of state_save_t.cr2 */ + #define SS_OFFSET_CR2 0x150 + /** @brief defines the offset of state_save_t.cr3 */ + #define SS_OFFSET_CR3 0x158 + /** @brief defines the offset of state_save_t.cr4 */ + #define SS_OFFSET_CR4 0x160 + /** @brief defines the offset of state_save_t.dr6 */ + #define SS_OFFSET_DR6 0x1F0 + /** @brief defines the offset of state_save_t.dr7 */ + #define SS_OFFSET_DR7 0x1F8 + /** @brief defines the offset of state_save_t.ia32_efer */ + #define SS_OFFSET_IA32_EFER 0x240 + /** @brief defines the offset of state_save_t.ia32_star */ + #define SS_OFFSET_IA32_STAR 0x248 + /** @brief defines the offset of state_save_t.ia32_lstar */ + #define SS_OFFSET_IA32_LSTAR 0x250 + /** @brief defines the offset of state_save_t.ia32_cstar */ + #define SS_OFFSET_IA32_CSTAR 0x258 + /** @brief defines the offset of state_save_t.ia32_fmask */ + #define SS_OFFSET_IA32_FMASK 0x260 + /** @brief defines the offset of state_save_t.ia32_fs_base */ + #define SS_OFFSET_IA32_FS_BASE 0x268 + /** @brief defines the offset of state_save_t.ia32_gs_base */ + #define SS_OFFSET_IA32_GS_BASE 0x270 + /** @brief defines the offset of state_save_t.ia32_kernel_gs_base */ + #define SS_OFFSET_IA32_KERNEL_GS_BASE 0x278 + /** @brief defines the offset of state_save_t.ia32_sysenter_cs */ + #define SS_OFFSET_IA32_SYSENTER_CS 0x280 + /** @brief defines the offset of state_save_t.ia32_sysenter_esp */ + #define SS_OFFSET_IA32_SYSENTER_ESP 0x288 + /** @brief defines the offset of state_save_t.ia32_sysenter_eip */ + #define SS_OFFSET_IA32_SYSENTER_EIP 0x290 + /** @brief defines the offset of state_save_t.ia32_pat */ + #define SS_OFFSET_IA32_PAT 0x298 + /** @brief defines the offset of state_save_t.ia32_debugctl */ + #define SS_OFFSET_IA32_DEBUGCTL 0x2A0 + + /** @brief defines MSR_IA32_SYSENTER_CS */ + #define MSR_IA32_SYSENTER_CS 0x00000174 + /** @brief defines MSR_IA32_SYSENTER_ESP */ + #define MSR_IA32_SYSENTER_ESP 0x00000175 + /** @brief defines MSR_IA32_SYSENTER_EIP */ + #define MSR_IA32_SYSENTER_EIP 0x00000176 + /** @brief defines MSR_IA32_DEBUGCTL */ + #define MSR_IA32_DEBUGCTL 0x000001D9 + /** @brief defines MSR_IA32_PAT */ + #define MSR_IA32_PAT 0x00000277 + /** @brief defines MSR_IA32_EFER */ + #define MSR_IA32_EFER 0xC0000080 + /** @brief defines MSR_IA32_STAR */ + #define MSR_IA32_STAR 0xC0000081 + /** @brief defines MSR_IA32_LSTAR */ + #define MSR_IA32_LSTAR 0xC0000082 + /** @brief defines MSR_IA32_CSTAR */ + #define MSR_IA32_CSTAR 0xC0000083 + /** @brief defines MSR_IA32_FMASK */ + #define MSR_IA32_FMASK 0xC0000084 + /** @brief defines MSR_IA32_FS_BASE */ + #define MSR_IA32_FS_BASE 0xC0000100 + /** @brief defines MSR_IA32_GS_BASE */ + #define MSR_IA32_GS_BASE 0xC0000101 + /** @brief defines MSR_IA32_KERNEL_GS_BASE */ + #define MSR_IA32_KERNEL_GS_BASE 0xC0000102 + .code64 .intel_syntax noprefix @@ -31,29 +153,35 @@ .align 0x1000 demote: + /**************************************************************************/ + /* Report Success On Completion */ + /**************************************************************************/ + + xor rax, rax + /**************************************************************************/ /* General Purpose Registers */ /**************************************************************************/ - mov [r8 + 0x000], rax - mov [r8 + 0x008], rbx - mov [r8 + 0x010], rcx - mov [r8 + 0x018], rdx - mov [r8 + 0x020], rbp - mov [r8 + 0x028], rsi - mov [r8 + 0x030], rdi - mov [r8 + 0x038], r8 - mov [r8 + 0x040], r9 - mov [r8 + 0x048], r10 - mov [r8 + 0x050], r11 - mov [r8 + 0x058], r12 - mov [r8 + 0x060], r13 - mov [r8 + 0x068], r14 - mov [r8 + 0x070], r15 + mov [r8 + SS_OFFSET_RAX], rax + mov [r8 + SS_OFFSET_RBX], rbx + mov [r8 + SS_OFFSET_RCX], rcx + mov [r8 + SS_OFFSET_RDX], rdx + mov [r8 + SS_OFFSET_RBP], rbp + mov [r8 + SS_OFFSET_RSI], rsi + mov [r8 + SS_OFFSET_RDI], rdi + mov [r8 + SS_OFFSET_R8], r8 + mov [r8 + SS_OFFSET_R9], r9 + mov [r8 + SS_OFFSET_R10], r10 + mov [r8 + SS_OFFSET_R11], r11 + mov [r8 + SS_OFFSET_R12], r12 + mov [r8 + SS_OFFSET_R13], r13 + mov [r8 + SS_OFFSET_R14], r14 + mov [r8 + SS_OFFSET_R15], r15 - lea rax, [rip + demotion_success] - mov [r8 + 0x078], rax - mov [r8 + 0x080], rsp + lea rax, [rip + demotion_return] + mov [r8 + SS_OFFSET_RIP], rax + mov [r8 + SS_OFFSET_RSP], rsp /**************************************************************************/ @@ -68,10 +196,10 @@ demote: /* Flags */ /**************************************************************************/ - pushf - pop qword ptr[r15 + 0x088] - push [r14 + 0x088] - popf + pushfq + pop qword ptr[r15 + SS_OFFSET_RFLAGS] + push qword ptr[r14 + SS_OFFSET_RFLAGS] + popfq /**************************************************************************/ /* IDT */ @@ -79,168 +207,162 @@ demote: call disable_interrupts - sidt [r15 + 0x0B0] - lidt [r14 + 0x0B0] + sidt [r15 + SS_OFFSET_IDTR] + lidt [r14 + SS_OFFSET_IDTR] /**************************************************************************/ /* MSRs */ /**************************************************************************/ - mov ecx, 0xC0000080 /* EFER */ + mov ecx, MSR_IA32_EFER rdmsr - mov [r15 + 0x240], eax - mov [r15 + 0x244], edx - mov eax, [r14 + 0x240] - mov edx, [r14 + 0x244] + mov [r15 + SS_OFFSET_IA32_EFER + 0x0], eax + mov [r15 + SS_OFFSET_IA32_EFER + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_EFER + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_EFER + 0x4] wrmsr - mov ecx, 0xC0000081 /* STAR */ + mov ecx, MSR_IA32_STAR rdmsr - mov [r15 + 0x248], eax - mov [r15 + 0x24C], edx - mov eax, [r14 + 0x248] - mov edx, [r14 + 0x24C] + mov [r15 + SS_OFFSET_IA32_STAR + 0x0], eax + mov [r15 + SS_OFFSET_IA32_STAR + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_STAR + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_STAR + 0x4] wrmsr - mov ecx, 0xC0000082 /* LSTAR */ + mov ecx, MSR_IA32_LSTAR rdmsr - mov [r15 + 0x250], eax - mov [r15 + 0x254], edx - mov eax, [r14 + 0x250] - mov edx, [r14 + 0x254] + mov [r15 + SS_OFFSET_IA32_LSTAR + 0x0], eax + mov [r15 + SS_OFFSET_IA32_LSTAR + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_LSTAR + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_LSTAR + 0x4] wrmsr - mov ecx, 0xC0000083 /* CSTAR */ + mov ecx, MSR_IA32_CSTAR rdmsr - mov [r15 + 0x258], eax - mov [r15 + 0x25C], edx - mov eax, [r14 + 0x258] - mov edx, [r14 + 0x25C] + mov [r15 + SS_OFFSET_IA32_CSTAR + 0x0], eax + mov [r15 + SS_OFFSET_IA32_CSTAR + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_CSTAR + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_CSTAR + 0x4] wrmsr - mov ecx, 0xC0000084 /* FMASK */ + mov ecx, MSR_IA32_FMASK rdmsr - mov [r15 + 0x260], eax - mov [r15 + 0x264], edx - mov eax, [r14 + 0x260] - mov edx, [r14 + 0x264] + mov [r15 + SS_OFFSET_IA32_FMASK + 0x0], eax + mov [r15 + SS_OFFSET_IA32_FMASK + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_FMASK + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_FMASK + 0x4] wrmsr - mov ecx, 0xC0000100 /* FS Base */ + mov ecx, MSR_IA32_FS_BASE rdmsr - mov [r15 + 0x268], eax - mov [r15 + 0x26C], edx - mov eax, [r14 + 0x268] - mov edx, [r14 + 0x26C] + mov [r15 + SS_OFFSET_IA32_FS_BASE + 0x0], eax + mov [r15 + SS_OFFSET_IA32_FS_BASE + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_FS_BASE + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_FS_BASE + 0x4] wrmsr - mov ecx, 0xC0000101 /* GS Base */ + mov ecx, MSR_IA32_GS_BASE rdmsr - mov [r15 + 0x270], eax - mov [r15 + 0x274], edx - mov eax, [r14 + 0x270] - mov edx, [r14 + 0x274] + mov [r15 + SS_OFFSET_IA32_GS_BASE + 0x0], eax + mov [r15 + SS_OFFSET_IA32_GS_BASE + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_GS_BASE + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_GS_BASE + 0x4] wrmsr - mov ecx, 0xC0000102 /* Kernel GS Base */ + mov ecx, MSR_IA32_KERNEL_GS_BASE rdmsr - mov [r15 + 0x278], eax - mov [r15 + 0x27C], edx - mov eax, [r14 + 0x278] - mov edx, [r14 + 0x27C] + mov [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x0], eax + mov [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x4] wrmsr - mov ecx, 0x00000174 /* SYSENTER_CS */ + mov ecx, MSR_IA32_SYSENTER_CS rdmsr - mov [r15 + 0x280], eax - mov [r15 + 0x284], edx - mov eax, [r14 + 0x280] - mov edx, [r14 + 0x284] + mov [r15 + SS_OFFSET_IA32_SYSENTER_CS + 0x0], eax + mov [r15 + SS_OFFSET_IA32_SYSENTER_CS + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_SYSENTER_CS + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_SYSENTER_CS + 0x4] wrmsr - mov ecx, 0x00000175 /* SYSENTER_ESP */ + mov ecx, MSR_IA32_SYSENTER_ESP rdmsr - mov [r15 + 0x288], eax - mov [r15 + 0x28C], edx - mov eax, [r14 + 0x288] - mov edx, [r14 + 0x28C] + mov [r15 + SS_OFFSET_IA32_SYSENTER_ESP + 0x0], eax + mov [r15 + SS_OFFSET_IA32_SYSENTER_ESP + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_SYSENTER_ESP + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_SYSENTER_ESP + 0x4] wrmsr - mov ecx, 0x00000176 /* SYSENTER_EIP */ + mov ecx, MSR_IA32_SYSENTER_EIP rdmsr - mov [r15 + 0x290], eax - mov [r15 + 0x294], edx - mov eax, [r14 + 0x290] - mov edx, [r14 + 0x294] + mov [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x0], eax + mov [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_SYSENTER_EIP + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_SYSENTER_EIP + 0x4] wrmsr - mov ecx, 0x00000277 /* PAT */ + mov ecx, MSR_IA32_PAT rdmsr - mov [r15 + 0x298], eax - mov [r15 + 0x29C], edx - mov eax, [r14 + 0x298] - mov edx, [r14 + 0x29C] + mov [r15 + SS_OFFSET_IA32_PAT + 0x0], eax + mov [r15 + SS_OFFSET_IA32_PAT + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_PAT + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_PAT + 0x4] wrmsr - mov ecx, 0x000001D9 /* DEBUGCTL */ + mov ecx, MSR_IA32_DEBUGCTL rdmsr - mov [r15 + 0x2A0], eax - mov [r15 + 0x2A4], edx - mov eax, [r14 + 0x2A0] - mov edx, [r14 + 0x2A4] + mov [r15 + SS_OFFSET_IA32_DEBUGCTL + 0x0], eax + mov [r15 + SS_OFFSET_IA32_DEBUGCTL + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_DEBUGCTL + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_DEBUGCTL + 0x4] wrmsr /**************************************************************************/ /* GDT */ /*************************************************************************/ - sgdt qword ptr [r15 + 0x0A0] - lgdt qword ptr [r14 + 0x0A0] + sgdt [r15 + SS_OFFSET_GDTR] + lgdt [r14 + SS_OFFSET_GDTR] mov dx, es - mov [r15 + 0x0C0], dx - mov dx, [r14 + 0x0C0] + mov [r15 + SS_OFFSET_ES_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_ES_SELECTOR] mov es, dx mov dx, cs - mov [r15 + 0x0D0], dx - mov ax, [r14 + 0x0D0] + mov [r15 + SS_OFFSET_CS_SELECTOR], dx + mov ax, [r14 + SS_OFFSET_CS_SELECTOR] push rax mov dx, ss - mov [r15 + 0x0E0], dx - mov dx, [r14 + 0x0E0] + mov [r15 + SS_OFFSET_SS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_SS_SELECTOR] mov ss, dx mov dx, ds - mov [r15 + 0x0F0], dx - mov dx, [r14 + 0x0F0] + mov [r15 + SS_OFFSET_DS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_DS_SELECTOR] mov ds, dx mov dx, fs - mov [r15 + 0x100], dx - mov dx, [r14 + 0x100] + mov [r15 + SS_OFFSET_FS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_FS_SELECTOR] mov fs, dx mov dx, gs - mov [r15 + 0x110], dx - mov dx, [r14 + 0x110] + mov [r15 + SS_OFFSET_GS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_GS_SELECTOR] mov gs, dx - mov ecx, 0x000001D9 - xor rax, rax - xor rdx, rdx - mov ax, [r14 + 0x110] - wrmsr - sldt dx - mov [r15 + 0x120], dx - mov dx, [r14 + 0x120] + mov [r15 + SS_OFFSET_LDTR_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_LDTR_SELECTOR] lldt dx str dx - mov [r15 + 0x130], dx - mov dx, [r14 + 0x130] + mov [r15 + SS_OFFSET_TR_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_TR_SELECTOR] ltr dx lea rax, [rip + gdt_and_cs_loaded] @@ -255,39 +377,43 @@ gdt_and_cs_loaded: /**************************************************************************/ mov rax, cr0 - mov [r15 + 0x140], rax - mov rax, [r14 + 0x140] + mov [r15 + SS_OFFSET_CR0], rax + mov rax, [r14 + SS_OFFSET_CR0] mov cr0, rax mov rax, cr2 - mov [r15 + 0x150], rax - mov rax, [r14 + 0x150] + mov [r15 + SS_OFFSET_CR2], rax + mov rax, [r14 + SS_OFFSET_CR2] mov cr2, rax mov rax, cr4 - mov [r15 + 0x160], rax - mov rax, [r14 + 0x160] + mov [r15 + SS_OFFSET_CR4], rax + mov rax, [r14 + SS_OFFSET_CR4] mov cr4, rax mov rax, cr3 - mov [r15 + 0x158], rax - mov rax, [r14 + 0x158] + mov [r15 + SS_OFFSET_CR3], rax + mov rax, [r14 + SS_OFFSET_CR3] mov cr3, rax - mov rsp, [r14 + 0x080] + /**************************************************************************/ + /* Stack */ + /**************************************************************************/ + + mov rsp, [r14 + SS_OFFSET_RSP] /**************************************************************************/ /* Debug Registers */ /**************************************************************************/ mov rax, dr6 - mov [r15 + 0x1F0], rax - mov rax, [r14 + 0x1F0] + mov [r15 + SS_OFFSET_DR6], rax + mov rax, [r14 + SS_OFFSET_DR6] mov dr6, rax mov rax, dr7 - mov [r15 + 0x1F8], rax - mov rax, [r14 + 0x1F8] + mov [r15 + SS_OFFSET_DR7], rax + mov rax, [r14 + SS_OFFSET_DR7] mov dr7, rax /**************************************************************************/ @@ -295,11 +421,11 @@ gdt_and_cs_loaded: /**************************************************************************/ mov rdi, r13 - push [r14 + 0x078] + push qword ptr[r14 + SS_OFFSET_RIP] ret int 3 -demotion_success: +demotion_return: /** * NOTE: diff --git a/loader/efi/src/x64/esr_default.S b/loader/efi/src/x64/esr_default.S index b432f549..bb15d797 100644 --- a/loader/efi/src/x64/esr_default.S +++ b/loader/efi/src/x64/esr_default.S @@ -31,20 +31,41 @@ .align 0x1000 esr_default: - mov rdx, 0x03F8 - mov rax, 0x45 - out dx, al + mov rcx, 'e' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x53 - out dx, al + mov rcx, 's' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x52 - out dx, al + mov rcx, 'r' + call serial_write_c + + mov rcx, '_' + call serial_write_c + + mov rcx, 'd' + call serial_write_c + + mov rcx, 'e' + call serial_write_c + + mov rcx, 'f' + call serial_write_c + + mov rcx, 'a' + call serial_write_c + + mov rcx, 'u' + call serial_write_c + + mov rcx, 'l' + call serial_write_c + + mov rcx, 't' + call serial_write_c + + mov rcx, '\n' + call serial_write_c cli hlt - - ret - int 3 diff --git a/loader/efi/src/x64/esr_df.S b/loader/efi/src/x64/esr_df.S index 9e7065ba..2c6b6c9f 100644 --- a/loader/efi/src/x64/esr_df.S +++ b/loader/efi/src/x64/esr_df.S @@ -31,32 +31,26 @@ .align 0x1000 esr_df: - mov rdx, 0x03F8 - mov rax, 0x45 - out dx, al + mov rcx, 'e' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x53 - out dx, al + mov rcx, 's' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x52 - out dx, al + mov rcx, 'r' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x20 - out dx, al + mov rcx, '_' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x44 - out dx, al + mov rcx, 'd' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x46 - out dx, al + mov rcx, 'f' + call serial_write_c + + mov rcx, '\n' + call serial_write_c cli hlt - - ret - int 3 diff --git a/loader/efi/src/x64/esr_gpf.S b/loader/efi/src/x64/esr_gpf.S index 7932d00a..7bed9538 100644 --- a/loader/efi/src/x64/esr_gpf.S +++ b/loader/efi/src/x64/esr_gpf.S @@ -31,36 +31,29 @@ .align 0x1000 esr_gpf: - mov rdx, 0x03F8 - mov rax, 0x45 - out dx, al + mov rcx, 'e' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x53 - out dx, al + mov rcx, 's' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x52 - out dx, al + mov rcx, 'r' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x20 - out dx, al + mov rcx, '_' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x47 - out dx, al + mov rcx, 'g' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x50 - out dx, al + mov rcx, 'p' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x46 - out dx, al + mov rcx, 'f' + call serial_write_c + + mov rcx, '\n' + call serial_write_c cli hlt - - ret - int 3 diff --git a/loader/efi/src/x64/esr_nmi.S b/loader/efi/src/x64/esr_nmi.S index 6c236dc1..32e4ed29 100644 --- a/loader/efi/src/x64/esr_nmi.S +++ b/loader/efi/src/x64/esr_nmi.S @@ -24,6 +24,9 @@ * SOFTWARE. */ + /** @brief defines the offset of state_save_t.ia32_debugctl */ + #define SS_OFFSET_NMI 0x318 + .code64 .intel_syntax noprefix @@ -42,7 +45,7 @@ esr_nmi: push rdx mov rax, 0x1 - mov [r15 + 0x318], rax + mov [r15 + SS_OFFSET_NMI], rax pop rdx pop rax diff --git a/loader/efi/src/x64/esr_pf.S b/loader/efi/src/x64/esr_pf.S index 7b3a1873..e25380c2 100644 --- a/loader/efi/src/x64/esr_pf.S +++ b/loader/efi/src/x64/esr_pf.S @@ -31,29 +31,26 @@ .align 0x1000 esr_pf: - mov rdx, 0x03F8 - mov rax, 0x45 - out dx, al + mov rcx, 'e' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x53 - out dx, al + mov rcx, 's' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x52 - out dx, al + mov rcx, 'r' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x20 - out dx, al + mov rcx, '_' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x50 - out dx, al + mov rcx, 'p' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x46 - out dx, al + mov rcx, 'f' + call serial_write_c + + mov rcx, '\n' + call serial_write_c cli hlt diff --git a/loader/efi/src/x64/flush_cache.S b/loader/efi/src/x64/flush_cache.S new file mode 100644 index 00000000..daea7eb1 --- /dev/null +++ b/loader/efi/src/x64/flush_cache.S @@ -0,0 +1,35 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .global flush_cache +flush_cache: + + clflush [rdi] + ret + int 3 diff --git a/loader/efi/src/x64/intel/setup_cr0.c b/loader/efi/src/x64/intel/setup_cr0.c new file mode 100644 index 00000000..644350b6 --- /dev/null +++ b/loader/efi/src/x64/intel/setup_cr0.c @@ -0,0 +1,53 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +/** @brief defines the MSR_VMX_CR0_FIXED0 MSR */ +#define MSR_VMX_CR0_FIXED0 ((uint32_t)0x00000486) +/** @brief defines the MSR_VMX_CR0_FIXED1 MSR */ +#define MSR_VMX_CR0_FIXED1 ((uint32_t)0x00000487) + +/** + * + * @brief Ensures that CR0 is set up properly. + */ +void +setup_cr0(void) +{ + uint64_t cr0 = intrinsic_scr0(); + uint64_t ia32_vmx_cr0_fixed0 = intrinsic_rdmsr(MSR_VMX_CR0_FIXED0); + uint64_t ia32_vmx_cr0_fixed1 = intrinsic_rdmsr(MSR_VMX_CR0_FIXED1); + + cr0 |= ia32_vmx_cr0_fixed0; + cr0 &= ia32_vmx_cr0_fixed1; + + intrinsic_lcr0(cr0); +} diff --git a/loader/efi/src/x64/intel/setup_cr4.c b/loader/efi/src/x64/intel/setup_cr4.c new file mode 100644 index 00000000..214f1d94 --- /dev/null +++ b/loader/efi/src/x64/intel/setup_cr4.c @@ -0,0 +1,56 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +/** @brief defines the MSR_VMX_CR4_FIXED0 MSR */ +#define MSR_VMX_CR4_FIXED0 ((uint32_t)0x00000488) +/** @brief defines the MSR_VMX_CR4_FIXED1 MSR */ +#define MSR_VMX_CR4_FIXED1 ((uint32_t)0x00000489) + +/** @brief defines the VME CR4 field */ +#define CR4_VMXE (((uint64_t)1) << ((uint64_t)13)) + +/** + * + * @brief Ensures that CR4 is set up properly. + */ +void +setup_cr4(void) +{ + uint64_t cr4 = intrinsic_scr4(); + uint64_t ia32_vmx_cr4_fixed0 = intrinsic_rdmsr(MSR_VMX_CR4_FIXED0); + uint64_t ia32_vmx_cr4_fixed1 = intrinsic_rdmsr(MSR_VMX_CR4_FIXED1); + + cr4 |= ia32_vmx_cr4_fixed0; + cr4 &= ia32_vmx_cr4_fixed1; + + intrinsic_lcr4(cr4 & (~CR4_VMXE)); +} diff --git a/loader/efi/src/x64/intrinsic_lcr0.S b/loader/efi/src/x64/intrinsic_lcr0.S new file mode 100644 index 00000000..f07d0f61 --- /dev/null +++ b/loader/efi/src/x64/intrinsic_lcr0.S @@ -0,0 +1,36 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl intrinsic_lcr0 +intrinsic_lcr0: + + mov cr0, rcx + + ret + int 3 diff --git a/loader/efi/src/x64/intrinsic_lgdt.S b/loader/efi/src/x64/intrinsic_lgdt.S new file mode 100644 index 00000000..ff48c9d1 --- /dev/null +++ b/loader/efi/src/x64/intrinsic_lgdt.S @@ -0,0 +1,36 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl intrinsic_lgdt +intrinsic_lgdt: + + lgdt [rcx] + + ret + int 3 diff --git a/loader/efi/src/x64/intrinsic_ltr.S b/loader/efi/src/x64/intrinsic_ltr.S new file mode 100644 index 00000000..412b61e4 --- /dev/null +++ b/loader/efi/src/x64/intrinsic_ltr.S @@ -0,0 +1,36 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl intrinsic_ltr +intrinsic_ltr: + + ltr cx + + ret + int 3 diff --git a/kernel/src/x64/serial_write.S b/loader/efi/src/x64/memops.S similarity index 80% rename from kernel/src/x64/serial_write.S rename to loader/efi/src/x64/memops.S index 02294701..d5c91deb 100644 --- a/kernel/src/x64/serial_write.S +++ b/loader/efi/src/x64/memops.S @@ -27,30 +27,29 @@ .code64 .intel_syntax noprefix - .globl serial_in - .type serial_in, @function -serial_in: + .globl memcpy +memcpy: - xor rax, rax - mov rdx, rdi - in al, dx + mov rdi, rcx + mov rsi, rdx + mov rax, rcx + mov rcx, r8 + rep movsb ret int 3 - .size serial_in, .-serial_in + .globl memset +memset: - .globl serial_out - .type serial_out, @function -serial_out: - - mov rdx, rdi - mov rax, rsi - out dx, al + mov r10, rcx + mov rdi, rcx + mov rax, rdx + mov rcx, r8 + rep stosb + mov rax, r10 ret int 3 - - .size serial_out, .-serial_out diff --git a/loader/efi/src/x64/promote.S b/loader/efi/src/x64/promote.S index cebe127c..74f87daf 100644 --- a/loader/efi/src/x64/promote.S +++ b/loader/efi/src/x64/promote.S @@ -24,6 +24,130 @@ * SOFTWARE. */ + /** @brief defines the offset of state_save_t.rax */ + #define SS_OFFSET_RAX 0x000 + /** @brief defines the offset of state_save_t.rbx */ + #define SS_OFFSET_RBX 0x008 + /** @brief defines the offset of state_save_t.rcx */ + #define SS_OFFSET_RCX 0x010 + /** @brief defines the offset of state_save_t.rdx */ + #define SS_OFFSET_RDX 0x018 + /** @brief defines the offset of state_save_t.rbp */ + #define SS_OFFSET_RBP 0x020 + /** @brief defines the offset of state_save_t.rsi */ + #define SS_OFFSET_RSI 0x028 + /** @brief defines the offset of state_save_t.rdi */ + #define SS_OFFSET_RDI 0x030 + /** @brief defines the offset of state_save_t.r8 */ + #define SS_OFFSET_R8 0x038 + /** @brief defines the offset of state_save_t.r9 */ + #define SS_OFFSET_R9 0x040 + /** @brief defines the offset of state_save_t.r10 */ + #define SS_OFFSET_R10 0x048 + /** @brief defines the offset of state_save_t.r11 */ + #define SS_OFFSET_R11 0x050 + /** @brief defines the offset of state_save_t.r12 */ + #define SS_OFFSET_R12 0x058 + /** @brief defines the offset of state_save_t.r13 */ + #define SS_OFFSET_R13 0x060 + /** @brief defines the offset of state_save_t.r14 */ + #define SS_OFFSET_R14 0x068 + /** @brief defines the offset of state_save_t.r15 */ + #define SS_OFFSET_R15 0x070 + /** @brief defines the offset of state_save_t.rip */ + #define SS_OFFSET_RIP 0x078 + /** @brief defines the offset of state_save_t.rsp */ + #define SS_OFFSET_RSP 0x080 + /** @brief defines the offset of state_save_t.rflags */ + #define SS_OFFSET_RFLAGS 0x088 + /** @brief defines the offset of state_save_t.gdtr */ + #define SS_OFFSET_GDTR 0x0A0 + /** @brief defines the offset of state_save_t.idtr */ + #define SS_OFFSET_IDTR 0x0B0 + /** @brief defines the offset of state_save_t.es_selector */ + #define SS_OFFSET_ES_SELECTOR 0x0C0 + /** @brief defines the offset of state_save_t.cs_selector */ + #define SS_OFFSET_CS_SELECTOR 0x0D0 + /** @brief defines the offset of state_save_t.ss_selector */ + #define SS_OFFSET_SS_SELECTOR 0x0E0 + /** @brief defines the offset of state_save_t.ds_selector */ + #define SS_OFFSET_DS_SELECTOR 0x0F0 + /** @brief defines the offset of state_save_t.fs_selector */ + #define SS_OFFSET_FS_SELECTOR 0x100 + /** @brief defines the offset of state_save_t.gs_selector */ + #define SS_OFFSET_GS_SELECTOR 0x110 + /** @brief defines the offset of state_save_t.ldtr_selector */ + #define SS_OFFSET_LDTR_SELECTOR 0x120 + /** @brief defines the offset of state_save_t.tr_selector */ + #define SS_OFFSET_TR_SELECTOR 0x130 + /** @brief defines the offset of state_save_t.cr0 */ + #define SS_OFFSET_CR0 0x140 + /** @brief defines the offset of state_save_t.cr2 */ + #define SS_OFFSET_CR2 0x150 + /** @brief defines the offset of state_save_t.cr3 */ + #define SS_OFFSET_CR3 0x158 + /** @brief defines the offset of state_save_t.cr4 */ + #define SS_OFFSET_CR4 0x160 + /** @brief defines the offset of state_save_t.dr6 */ + #define SS_OFFSET_DR6 0x1F0 + /** @brief defines the offset of state_save_t.dr7 */ + #define SS_OFFSET_DR7 0x1F8 + /** @brief defines the offset of state_save_t.ia32_efer */ + #define SS_OFFSET_IA32_EFER 0x240 + /** @brief defines the offset of state_save_t.ia32_star */ + #define SS_OFFSET_IA32_STAR 0x248 + /** @brief defines the offset of state_save_t.ia32_lstar */ + #define SS_OFFSET_IA32_LSTAR 0x250 + /** @brief defines the offset of state_save_t.ia32_cstar */ + #define SS_OFFSET_IA32_CSTAR 0x258 + /** @brief defines the offset of state_save_t.ia32_fmask */ + #define SS_OFFSET_IA32_FMASK 0x260 + /** @brief defines the offset of state_save_t.ia32_fs_base */ + #define SS_OFFSET_IA32_FS_BASE 0x268 + /** @brief defines the offset of state_save_t.ia32_gs_base */ + #define SS_OFFSET_IA32_GS_BASE 0x270 + /** @brief defines the offset of state_save_t.ia32_kernel_gs_base */ + #define SS_OFFSET_IA32_KERNEL_GS_BASE 0x278 + /** @brief defines the offset of state_save_t.ia32_sysenter_cs */ + #define SS_OFFSET_IA32_SYSENTER_CS 0x280 + /** @brief defines the offset of state_save_t.ia32_sysenter_esp */ + #define SS_OFFSET_IA32_SYSENTER_ESP 0x288 + /** @brief defines the offset of state_save_t.ia32_sysenter_eip */ + #define SS_OFFSET_IA32_SYSENTER_EIP 0x290 + /** @brief defines the offset of state_save_t.ia32_pat */ + #define SS_OFFSET_IA32_PAT 0x298 + /** @brief defines the offset of state_save_t.ia32_debugctl */ + #define SS_OFFSET_IA32_DEBUGCTL 0x2A0 + /** @brief defines the offset of state_save_t.nmi */ + #define SS_OFFSET_NMI 0x318 + + /** @brief defines MSR_IA32_SYSENTER_CS */ + #define MSR_IA32_SYSENTER_CS 0x00000174 + /** @brief defines MSR_IA32_SYSENTER_ESP */ + #define MSR_IA32_SYSENTER_ESP 0x00000175 + /** @brief defines MSR_IA32_SYSENTER_EIP */ + #define MSR_IA32_SYSENTER_EIP 0x00000176 + /** @brief defines MSR_IA32_DEBUGCTL */ + #define MSR_IA32_DEBUGCTL 0x000001D9 + /** @brief defines MSR_IA32_PAT */ + #define MSR_IA32_PAT 0x00000277 + /** @brief defines MSR_IA32_EFER */ + #define MSR_IA32_EFER 0xC0000080 + /** @brief defines MSR_IA32_STAR */ + #define MSR_IA32_STAR 0xC0000081 + /** @brief defines MSR_IA32_LSTAR */ + #define MSR_IA32_LSTAR 0xC0000082 + /** @brief defines MSR_IA32_CSTAR */ + #define MSR_IA32_CSTAR 0xC0000083 + /** @brief defines MSR_IA32_FMASK */ + #define MSR_IA32_FMASK 0xC0000084 + /** @brief defines MSR_IA32_FS_BASE */ + #define MSR_IA32_FS_BASE 0xC0000100 + /** @brief defines MSR_IA32_GS_BASE */ + #define MSR_IA32_GS_BASE 0xC0000101 + /** @brief defines MSR_IA32_KERNEL_GS_BASE */ + #define MSR_IA32_KERNEL_GS_BASE 0xC0000102 + .code64 .intel_syntax noprefix @@ -35,10 +159,10 @@ promote: /* Debug Registers */ /**************************************************************************/ - mov rax, [r15 + 0x1F8] + mov rax, [r15 + SS_OFFSET_DR7] mov dr7, rax - mov rax, [r15 + 0x1F0] + mov rax, [r15 + SS_OFFSET_DR6] mov dr6, rax /**************************************************************************/ @@ -58,27 +182,51 @@ promote: * CR3 so that we can push/pop as needed */ - mov rax, [r15 + 0x158] + mov rax, [r15 + SS_OFFSET_CR3] and rax, 0xFFFFFFFFFFFFF000 mov cr3, rax - mov rax, [r15 + 0x160] + mov rax, [r15 + SS_OFFSET_CR4] and rax, 0xFFFFFFFFFFFFFF7F mov cr4, rax - mov rax, [r15 + 0x158] + mov rax, [r15 + SS_OFFSET_CR3] mov cr3, rax - mov rax, [r15 + 0x160] + mov rax, [r15 + SS_OFFSET_CR4] mov cr4, rax - mov rax, [r15 + 0x150] + mov rax, [r15 + SS_OFFSET_CR2] mov cr2, rax - mov rax, [r15 + 0x140] + mov rax, [r15 + SS_OFFSET_CR0] mov cr0, rax - mov rsp, [r15 + 0x080] + /**************************************************************************/ + /* Stack */ + /**************************************************************************/ + + mov rsp, [r15 + SS_OFFSET_RSP] + + /**************************************************************************/ + /* Clear TSS Busy */ + /**************************************************************************/ + + /** + * NOTE: + * - The TR in the GDT used by the root OS is marked as busy, and as + * a result, cannot be loaded without first marking it as available. + */ + + mov rdx, [r15 + 0x0A2] + + xor rax, rax + mov ax, [r15 + 0x130] + + add rdx, rax + + mov rax, 0xFFFFFDFFFFFFFFFF + and [rdx], rax /**************************************************************************/ /* GDT */ @@ -99,38 +247,31 @@ promote: * this code needs to execute. */ - lgdt [r15 + 0x0A0] + lgdt [r15 + SS_OFFSET_GDTR] - mov dx, [r15 + 0x0C0] + mov dx, [r15 + SS_OFFSET_ES_SELECTOR] mov es, dx - mov ax, [r15 + 0x0D0] + mov ax, [r15 + SS_OFFSET_CS_SELECTOR] push rax - mov dx, [r15 + 0x0E0] + mov dx, [r15 + SS_OFFSET_SS_SELECTOR] mov ss, dx - mov dx, [r15 + 0x0F0] + mov dx, [r15 + SS_OFFSET_DS_SELECTOR] mov ds, dx - mov dx, [r15 + 0x100] + mov dx, [r15 + SS_OFFSET_FS_SELECTOR] mov fs, dx - mov dx, [r15 + 0x110] + mov dx, [r15 + SS_OFFSET_GS_SELECTOR] mov gs, dx - mov dx, [r15 + 0x120] + mov dx, [r15 + SS_OFFSET_LDTR_SELECTOR] lldt dx - /** - * NOTE: - * - UEFI doesn't load the TR register with a valid value, and therefore - * the selector is NULL. For this reason, we can leave the TR register - * with garbage data as it is never used. - */ - - /** mov dx, [r15 + 0x130] */ - /** ltr dx */ + mov dx, [r15 + SS_OFFSET_TR_SELECTOR] + ltr dx lea rax, [rip + gdt_and_cs_loaded] push rax @@ -143,82 +284,82 @@ gdt_and_cs_loaded: /* MSRs */ /**************************************************************************/ - mov ecx, 0x000001D9 /* DEBUGCTL */ - mov eax, [r15 + 0x2A0] - mov edx, [r15 + 0x2A4] + mov ecx, MSR_IA32_DEBUGCTL + mov eax, [r15 + SS_OFFSET_IA32_DEBUGCTL + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_DEBUGCTL + 0x4] wrmsr - mov ecx, 0x00000277 /* PAT */ - mov eax, [r15 + 0x298] - mov edx, [r15 + 0x29C] + mov ecx, MSR_IA32_PAT + mov eax, [r15 + SS_OFFSET_IA32_PAT + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_PAT + 0x4] wrmsr - mov ecx, 0x00000176 /* SYSENTER_EIP */ - mov eax, [r15 + 0x290] - mov edx, [r15 + 0x294] + mov ecx, MSR_IA32_SYSENTER_EIP + mov eax, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x4] wrmsr - mov ecx, 0x00000175 /* SYSENTER_ESP */ - mov eax, [r15 + 0x288] - mov edx, [r15 + 0x28C] + mov ecx, MSR_IA32_SYSENTER_EIP + mov eax, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x4] wrmsr - mov ecx, 0x00000174 /* SYSENTER_CS */ - mov eax, [r15 + 0x280] - mov edx, [r15 + 0x284] + mov ecx, MSR_IA32_SYSENTER_CS + mov eax, [r15 + SS_OFFSET_IA32_SYSENTER_CS + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_SYSENTER_CS + 0x4] wrmsr - mov ecx, 0xC0000102 /* Kernel GS Base */ - mov eax, [r15 + 0x278] - mov edx, [r15 + 0x27C] + mov ecx, MSR_IA32_KERNEL_GS_BASE + mov eax, [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x4] wrmsr - mov ecx, 0xC0000101 /* GS Base */ - mov eax, [r15 + 0x270] - mov edx, [r15 + 0x274] + mov ecx, MSR_IA32_GS_BASE + mov eax, [r15 + SS_OFFSET_IA32_GS_BASE + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_GS_BASE + 0x4] wrmsr - mov ecx, 0xC0000100 /* FS Base */ - mov eax, [r15 + 0x268] - mov edx, [r15 + 0x26C] + mov ecx, MSR_IA32_FS_BASE + mov eax, [r15 + SS_OFFSET_IA32_FS_BASE + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_FS_BASE + 0x4] wrmsr - mov ecx, 0xC0000084 /* FMASK */ - mov eax, [r15 + 0x260] - mov edx, [r15 + 0x264] + mov ecx, MSR_IA32_FMASK + mov eax, [r15 + SS_OFFSET_IA32_FMASK + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_FMASK + 0x4] wrmsr - mov ecx, 0xC0000083 /* CSTAR */ - mov eax, [r15 + 0x258] - mov edx, [r15 + 0x25C] + mov ecx, MSR_IA32_CSTAR + mov eax, [r15 + SS_OFFSET_IA32_CSTAR + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_CSTAR + 0x4] wrmsr - mov ecx, 0xC0000082 /* LSTAR */ - mov eax, [r15 + 0x250] - mov edx, [r15 + 0x254] + mov ecx, MSR_IA32_LSTAR + mov eax, [r15 + SS_OFFSET_IA32_LSTAR + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_LSTAR + 0x4] wrmsr - mov ecx, 0xC0000081 /* STAR */ - mov eax, [r15 + 0x248] - mov edx, [r15 + 0x24C] + mov ecx, MSR_IA32_STAR + mov eax, [r15 + SS_OFFSET_IA32_STAR + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_STAR + 0x4] wrmsr - mov ecx, 0xC0000080 /* EFER */ - mov eax, [r15 + 0x240] - mov edx, [r15 + 0x244] + mov ecx, MSR_IA32_EFER + mov eax, [r15 + SS_OFFSET_IA32_EFER + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_EFER + 0x4] wrmsr /**************************************************************************/ /* IDT */ /**************************************************************************/ - lidt [r15 + 0x0B0] + lidt [r15 + SS_OFFSET_IDTR] /**************************************************************************/ /* NMIs */ /**************************************************************************/ - mov rax, [r15 + 0x318] + mov rax, [r15 + SS_OFFSET_NMI] cmp rax, 0x1 jne nmis_complete @@ -230,32 +371,32 @@ nmis_complete: /* Flags */ /**************************************************************************/ - push [r15 + 0x088] - popf + push qword ptr[r15 + SS_OFFSET_RFLAGS] + popfq /**************************************************************************/ /* General Purpose Registers */ /**************************************************************************/ - mov rax, [r15 + 0x078] + mov rax, [r15 + SS_OFFSET_RIP] push rax - mov r14, [r15 + 0x068] - mov r13, [r15 + 0x060] - mov r12, [r15 + 0x058] - mov r11, [r15 + 0x050] - mov r10, [r15 + 0x048] - mov r9, [r15 + 0x040] - mov r8, [r15 + 0x038] - mov rdi, [r15 + 0x030] - mov rsi, [r15 + 0x028] - mov rbp, [r15 + 0x020] - mov rdx, [r15 + 0x018] - mov rcx, [r15 + 0x010] - mov rbx, [r15 + 0x008] - mov rax, [r15 + 0x000] + mov r14, [r15 + SS_OFFSET_R14] + mov r13, [r15 + SS_OFFSET_R13] + mov r12, [r15 + SS_OFFSET_R12] + mov r11, [r15 + SS_OFFSET_R11] + mov r10, [r15 + SS_OFFSET_R10] + mov r9, [r15 + SS_OFFSET_R9] + mov r8, [r15 + SS_OFFSET_R8] + mov rdi, [r15 + SS_OFFSET_RDI] + mov rsi, [r15 + SS_OFFSET_RSI] + mov rbp, [r15 + SS_OFFSET_RBP] + mov rdx, [r15 + SS_OFFSET_RDX] + mov rcx, [r15 + SS_OFFSET_RCX] + mov rbx, [r15 + SS_OFFSET_RBX] + mov rax, [r15 + SS_OFFSET_RAX] - mov r15, [r15 + 0x070] + mov r15, [r15 + SS_OFFSET_R15] call enable_interrupts ret diff --git a/loader/efi/src/x64/serial_write_c.S b/loader/efi/src/x64/serial_write_c.S new file mode 100644 index 00000000..9e37d4d1 --- /dev/null +++ b/loader/efi/src/x64/serial_write_c.S @@ -0,0 +1,55 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define ASSEMBLY +#include + + .code64 + .intel_syntax noprefix + + .globl serial_write_c + .align 0x1000 +serial_write_c: + push rax + push rdx + +wait_for_ffio_empty: + mov rdx, HYPERVISOR_SERIAL_PORT + add rdx, 5 + in al, dx + + and al, 0x20 + cmp al, 0x0 + jz wait_for_ffio_empty + + mov rdx, HYPERVISOR_SERIAL_PORT + mov rax, rcx + out dx, al + + pop rdx + pop rax + ret + int 3 diff --git a/loader/efi/src/x64/serial_write_hex.S b/loader/efi/src/x64/serial_write_hex.S new file mode 100644 index 00000000..9ea37170 --- /dev/null +++ b/loader/efi/src/x64/serial_write_hex.S @@ -0,0 +1,143 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl serial_write_hex + .align 0x1000 +serial_write_hex: + push rdx + + mov rdx, rcx + + mov rcx, 0x30 + call serial_write_c + + mov rcx, 0x78 + call serial_write_c + + mov rcx, rdx + shr rcx, 60 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 56 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 52 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 48 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 44 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 40 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 36 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 32 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 28 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 24 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 20 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 16 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 12 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 8 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 4 + and rcx, 0xFF + call serial_write_hex_digit + + mov rcx, rdx + and rcx, 0xFF + call serial_write_hex_digit + + pop rdx + ret + int 3 + +serial_write_hex_digit: + + cmp rcx, 9 + jg serial_write_hex_digit_a_to_f + + add rcx, 0x30 + call serial_write_c + + ret + int 3 + +serial_write_hex_digit_a_to_f: + + add rcx, 0x37 + call serial_write_c + + ret + int 3 diff --git a/loader/efi/src/x64/setup_tss.c b/loader/efi/src/x64/setup_tss.c new file mode 100644 index 00000000..35c4902d --- /dev/null +++ b/loader/efi/src/x64/setup_tss.c @@ -0,0 +1,181 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @brief defines our custom TR attributes */ +#define UEFI_TR_ATTRIB ((uint16_t)0x00000089) +/** @brief defines our custom TR limit */ +#define UEFI_TR_LIMIT ((uint32_t)(sizeof(struct tss_t) - ((uint64_t)1))) + +/** @brief stores the old GDT that UEFI will use */ +struct global_descriptor_table_register_t g_old_gdtr = {0}; + +/** + * + * @brief Ensures that the TSS is set up properly. + * + * + * @return Returns 0 on success, LOADER_FAILURE otherwise + */ +int64_t +setup_tss(void) +{ + int64_t ret; + + /** + * NOTE: + * - UEFI doesn't seem to set the TR segment. This causes a number of + * issues with our code so we create a new GDT that is the same as + * the current GDT, but with TR added. + * - This seems to be an issue on both AMD and Intel, and also seems to + * be an issue on multiple systems from different vendors. + * - One issue is that on Intel, you cannot start a VM with TR set to 0. + * Any attempt to do so will cause a VM entry failure. + * - Another issue is that when you attempt to return (i.e. promote) from + * the microkernel, the promote logic doesn't have a TR to flip the + * TSS busy bit for. As a result, it has to leave the TR set to the + * microkernel's TR which leaks it's resources. + * - UEFI also seems to copy the GDT from one core to another as it starts + * each AP. This means that we need to cache the original GDT so that + * we can use it for reference. Otherwise, on other cores, you would + * get the GDT you created on the BSP, which already has a TSS and it + * cannot be shared (due to the TSS busy bit). + */ + + struct tss_t *tss; + struct global_descriptor_table_register_t gdtr; + + if (intrinsic_str() != ((uint16_t)0)) { + + /** + * NOTE: + * - Based on testing, I don't think this specific branch will + * actually be taken, but just in case there is a TR set, we don't + * need to actually execute this code. + */ + + return LOADER_SUCCESS; + } + + if (((void *)0) == g_old_gdtr.base) { + intrinsic_sgdt(&g_old_gdtr); + g_old_gdtr.limit += ((uint16_t)1); + } + + if (g_old_gdtr.limit > ((uint16_t)0xFF0)) { + bferror("system unsupported. existing GDT is too large"); + return LOADER_FAILURE; + } + + /** + * NOTE: + * - Allocate the new GDT and the new TSS. The TR will be set to the + * current GDT's limit. This ensures that the TR uses the first + * available entry in the old GDT. + */ + + gdtr.base = (uint64_t *)platform_alloc(HYPERVISOR_PAGE_SIZE); + if (((void *)0) == gdtr.base) { + bferror("platform_alloc failed"); + goto platform_alloc_gdt_failed; + } + + gdtr.limit = (uint16_t)(HYPERVISOR_PAGE_SIZE - ((uint64_t)1)); + + /** + * TODO: + * - There is an issue here. If an interrupt or exception fires, we might + * have a problem if UEFI's IDT is set up to use the IST when an + * interrupt first. Since the TR is not set, it is likely that the IDT + * is set up to use the stack, in which case the IST is never used, + * and this TSS configuration is fine. We should veryify this on + * different systems to prove that this will work. Otherwise, using + * other UEFI functions that need interrupts might fail if UEFI tries + * to add a TR to their GDT but ours is loaded and the TSS's do not + * match. + */ + + tss = (struct tss_t *)platform_alloc(HYPERVISOR_PAGE_SIZE); + if (((void *)0) == tss) { + bferror("platform_alloc failed"); + goto platform_alloc_tss_failed; + } + + tss->iomap = ((uint16_t)sizeof(struct tss_t)); + + /** + * NOTE: + * - Set up the new GDT. To do this, all we need to do is copy over the + * old GDT and then add the TSS. + */ + + g_st->BootServices->CopyMem(gdtr.base, g_old_gdtr.base, g_old_gdtr.limit); + + ret = set_gdt_descriptor( // -- + &gdtr, // -- + g_old_gdtr.limit, // -- + (uint64_t)tss, // -- + UEFI_TR_LIMIT, // -- + UEFI_TR_ATTRIB); + + if (ret) { + bferror("set_gdt_descriptor failed"); + goto set_descriptor_failed; + } + + /** + * NOTE: + * - Now that the new GDT is set up, we can load it as well as the TR + * segment which should fixes the above identified issues. Note that + * we do not need to load any other segment registers are they are + * all identical. + */ + + intrinsic_lgdt(&gdtr); + intrinsic_ltr(g_old_gdtr.limit); + + return LOADER_SUCCESS; + +set_descriptor_failed: + platform_free(tss, HYPERVISOR_PAGE_SIZE); +platform_alloc_tss_failed: + platform_free(gdtr.base, HYPERVISOR_PAGE_SIZE); +platform_alloc_gdt_failed: + + return LOADER_FAILURE; +} diff --git a/loader/include/x64/alloc_and_copy_mk_code_aliases.h b/loader/include/alloc_and_copy_mk_code_aliases.h similarity index 95% rename from loader/include/x64/alloc_and_copy_mk_code_aliases.h rename to loader/include/alloc_and_copy_mk_code_aliases.h index 57431ccc..b37ccd14 100644 --- a/loader/include/x64/alloc_and_copy_mk_code_aliases.h +++ b/loader/include/alloc_and_copy_mk_code_aliases.h @@ -35,7 +35,7 @@ * @brief The function's main purpose is allocate pages for all of the * executable code that is currently linked into the kernel module, and * copy this code into the newly allocated pages so that they can be - * mapped into the microkernel's root page tables, creating an alias. + * mapped into the microkernel's page tables, creating an alias. * The following diagram is what we are doing here: * * |-------> physical address (OS kernel) @@ -59,7 +59,7 @@ * is actually garbage. You can only get the physical address of * memory that is allocated using vmalloc(), which is why we need to * create the aliases, as we need the physical address of the code so - * that we can map it into the microkernel's root page tables. + * that we can map it into the microkernel's page tables. * * * @param a a pointer to a code_aliases_t that will store the diff --git a/loader/include/x64/alloc_and_copy_mk_state.h b/loader/include/alloc_and_copy_mk_state.h similarity index 94% rename from loader/include/x64/alloc_and_copy_mk_state.h rename to loader/include/alloc_and_copy_mk_state.h index 1861b012..6b9f1e0f 100644 --- a/loader/include/x64/alloc_and_copy_mk_state.h +++ b/loader/include/alloc_and_copy_mk_state.h @@ -27,7 +27,7 @@ #ifndef ALLOC_AND_COPY_MK_STATE_H #define ALLOC_AND_COPY_MK_STATE_H -#include +#include #include #include #include @@ -38,7 +38,7 @@ * microkernel. * * - * @param pml4t the mkcrokernel's root page table + * @param rpt the mkcrokernel's root page table * @param mk_elf_file the microkernel's ELF file * @param mk_stack the microkernel's stack * @param mk_stack_virt the microkernel's virtual address of the stack @@ -46,7 +46,7 @@ * @return 0 on success, LOADER_FAILURE on failure. */ int64_t alloc_and_copy_mk_state( - struct pml4t_t const *const pml4t, + root_page_table_t const *const rpt, struct span_t const *const mk_elf_file, struct span_t const *const mk_stack, uint64_t const mk_stack_virt, diff --git a/loader/include/x64/alloc_and_copy_root_vp_state.h b/loader/include/alloc_and_copy_root_vp_state.h similarity index 100% rename from loader/include/x64/alloc_and_copy_root_vp_state.h rename to loader/include/alloc_and_copy_root_vp_state.h diff --git a/loader/include/x64/alloc_mk_root_page_table.h b/loader/include/alloc_mk_root_page_table.h similarity index 90% rename from loader/include/x64/alloc_mk_root_page_table.h rename to loader/include/alloc_mk_root_page_table.h index d99fba5e..2ca56e94 100644 --- a/loader/include/x64/alloc_mk_root_page_table.h +++ b/loader/include/alloc_mk_root_page_table.h @@ -27,7 +27,7 @@ #ifndef ALLOC_MK_ROOT_PAGE_TABLE_H #define ALLOC_MK_ROOT_PAGE_TABLE_H -#include +#include #include /** @@ -35,9 +35,9 @@ * @brief This function allocates the root page table * * - * @param pml4t where to return the resulting root page table + * @param rpt where to return the resulting root page table * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t alloc_mk_root_page_table(struct pml4t_t **const pml4t); +int64_t alloc_mk_root_page_table(root_page_table_t **const rpt); #endif diff --git a/loader/include/arm/aarch64/alloc_l1t.h b/loader/include/arm/aarch64/alloc_l1t.h new file mode 100644 index 00000000..d6d6e841 --- /dev/null +++ b/loader/include/arm/aarch64/alloc_l1t.h @@ -0,0 +1,48 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ALLOC_L1T_H +#define ALLOC_L1T_H + +#include +#include +#include + +/** + * + * @brief Given a l0t_t and a virtual address, this function allocates a + * l1t_t and adds it to the l0t_t. If an l1t_t has already been allocated, + * this function will fail. + * + * + * @param l0 the l0t_t to add the newly allocated l1t_t to + * @param virt the virtual address to get the l0t_t offset from. + * @return a pointer to the newly allocated l1t_t on success, ((void *)0) + * otherwise. + */ +struct l1t_t *alloc_l1t(struct l0t_t *const l0, uint64_t const virt); + +#endif diff --git a/loader/include/arm/aarch64/alloc_l2t.h b/loader/include/arm/aarch64/alloc_l2t.h new file mode 100644 index 00000000..1ebf8924 --- /dev/null +++ b/loader/include/arm/aarch64/alloc_l2t.h @@ -0,0 +1,48 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ALLOC_L2T_H +#define ALLOC_L2T_H + +#include +#include +#include + +/** + * + * @brief Given a l1t_t and a virtual address, this function allocates a + * l2t_t and adds it to the l1t_t. If an l2t_t has already been allocated, + * this function will fail. + * + * + * @param l1 the l1t_t to add the newly allocated l2t_t to + * @param virt the virtual address to get the l1t_t offset from. + * @return a pointer to the newly allocated l2t_t on success, ((void *)0) + * otherwise. + */ +struct l2t_t *alloc_l2t(struct l1t_t *const l1, uint64_t const virt); + +#endif diff --git a/loader/include/arm/aarch64/alloc_l3t.h b/loader/include/arm/aarch64/alloc_l3t.h new file mode 100644 index 00000000..9840b1dc --- /dev/null +++ b/loader/include/arm/aarch64/alloc_l3t.h @@ -0,0 +1,48 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ALLOC_L3T_H +#define ALLOC_L3T_H + +#include +#include +#include + +/** + * + * @brief Given a l2t_t and a virtual address, this function allocates a + * l3t_t and adds it to the l2t_t. If an l3t_t has already been allocated, + * this function will fail. + * + * + * @param l2 the l2t_t to add the newly allocated l3t_t to + * @param virt the virtual address to get the l2t_t offset from. + * @return a pointer to the newly allocated l3t_t on success, ((void *)0) + * otherwise. + */ +struct l3t_t *alloc_l3t(struct l2t_t *const l2, uint64_t const virt); + +#endif diff --git a/loader/include/arm/aarch64/code_aliases_t.h b/loader/include/arm/aarch64/code_aliases_t.h new file mode 100644 index 00000000..53701a97 --- /dev/null +++ b/loader/include/arm/aarch64/code_aliases_t.h @@ -0,0 +1,56 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef CODE_ALIASES_T_H +#define CODE_ALIASES_T_H + +#pragma pack(push, 1) + +/** + * @struct code_aliases_t + * + * + * @brief Stores pointers to memory that is allocated for executable + * code that is compiled into the kernel, that must be mapped into the + * microkernel's root page tables. Some operating systems will not + * provide the physical address of a page that is mapped into the + * executable portion of a kernel module (e.g., Linux). To overcome this + * the executable code is copied into an alias page. When the function + * is executed using the kernel module's page tables, nothing changes, but + * when the code is executed from the microkernel's page tables, the + * pages stored here provide the page that stores the executable code + * instead, ensuring we have a means to get a physical address of a page + * that has the code we want. + */ +struct code_aliases_t +{ + /** @brief unused */ + void *ignored; +}; + +#pragma pack(pop) + +#endif diff --git a/loader/include/arm/aarch64/esr.h b/loader/include/arm/aarch64/esr.h new file mode 100644 index 00000000..2e9adca5 --- /dev/null +++ b/loader/include/arm/aarch64/esr.h @@ -0,0 +1,45 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ESR +#define ESR + +#include + +/** + * + * @brief Defines the exception service routine + * + * + * @param vec the esr's vector # + * @param esr_el2 the value of esr_el2 + * @param far_el2 the value of far_el2 + * @param spsr_el2 the value of spsr_el2 + */ +void +esr(uint64_t const vec, uint64_t const esr_el2, uint64_t const far_el2, uint64_t const spsr_el2); + +#endif diff --git a/loader/include/arm/aarch64/exception_vectors.h b/loader/include/arm/aarch64/exception_vectors.h new file mode 100644 index 00000000..c2bd787b --- /dev/null +++ b/loader/include/arm/aarch64/exception_vectors.h @@ -0,0 +1,36 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef EXCEPTION_VECTORS +#define EXCEPTION_VECTORS + +/** + * + * @brief Defines the location of the exception vectors + */ +void exception_vectors(); + +#endif diff --git a/loader/include/arm/aarch64/free_l0t.h b/loader/include/arm/aarch64/free_l0t.h new file mode 100644 index 00000000..dd650335 --- /dev/null +++ b/loader/include/arm/aarch64/free_l0t.h @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef FREE_L0T_H +#define FREE_L0T_H + +#include + +/** + * + * @brief Given a l0t_t, this function will free any previously allocated + * tables. + * + * + * @param l0 the l0t_t to free + */ +void free_l0t(struct l0t_t *const l0); + +#endif diff --git a/loader/include/arm/aarch64/free_l1t.h b/loader/include/arm/aarch64/free_l1t.h new file mode 100644 index 00000000..bb71abad --- /dev/null +++ b/loader/include/arm/aarch64/free_l1t.h @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef FREE_L1T_H +#define FREE_L1T_H + +#include + +/** + * + * @brief Given a l1t_t, this function will free any previously allocated + * tables. + * + * + * @param l1 the l1t_t to free + */ +void free_l1t(struct l1t_t *const l1); + +#endif diff --git a/loader/include/arm/aarch64/free_l2t.h b/loader/include/arm/aarch64/free_l2t.h new file mode 100644 index 00000000..0174ade2 --- /dev/null +++ b/loader/include/arm/aarch64/free_l2t.h @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef FREE_L2T_H +#define FREE_L2T_H + +#include + +/** + * + * @brief Given a l2t_t, this function will free any previously allocated + * tables. + * + * + * @param l2 the l2t_t to free + */ +void free_l2t(struct l2t_t *const l2); + +#endif diff --git a/loader/include/arm/aarch64/l0t_t.h b/loader/include/arm/aarch64/l0t_t.h new file mode 100644 index 00000000..302a5fd0 --- /dev/null +++ b/loader/include/arm/aarch64/l0t_t.h @@ -0,0 +1,55 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L0T_T_H +#define L0T_T_H + +#include +#include +#include + +#pragma pack(push, 1) + +/** @brief defines total number of entries in the L0T */ +#define LOADER_NUM_L0T_ENTRIES ((uint64_t)512) + +/** + * @struct l0t_t + * + * + * @brief Defines the layout of a level-0 table (L0T). + */ +struct l0t_t +{ + /** @brief stores the entries for this page table */ + struct l0te_t entires[LOADER_NUM_L0T_ENTRIES]; + /** @brief stores pointers to child tables */ + struct l1t_t *tables[LOADER_NUM_L0T_ENTRIES]; +}; + +#pragma pack(pop) + +#endif diff --git a/loader/include/arm/aarch64/l0te_t.h b/loader/include/arm/aarch64/l0te_t.h new file mode 100644 index 00000000..bafab9dd --- /dev/null +++ b/loader/include/arm/aarch64/l0te_t.h @@ -0,0 +1,66 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L0TE_T +#define L0TE_T + +#include + +#pragma pack(push, 1) + +/** + * @struct l0te_t + * + * + * @brief Defines the layout of a level-0 table entry (L0TE). + */ +struct l0te_t +{ + /** @brief defines the "present" field in the page */ + uint64_t p : ((uint64_t)1); + /** @brief defines the "block/table" field in the page */ + uint64_t bt : ((uint64_t)1); + /** @brief defines our "aliased" field in the page */ + uint64_t alias : ((uint64_t)1); + /** @brief defines the "available to software" field in the page */ + uint64_t available1 : ((uint64_t)9); + /** @brief defines the "physical address" field in the page */ + uint64_t phys : ((uint64_t)40); + /** @brief defines the "available to software" field in the page */ + uint64_t available2 : ((uint64_t)7); + /** @brief defines the "PXNTable" field in the page */ + uint64_t pxntable : ((uint64_t)1); + /** @brief defines the "XNTable" field in the page */ + uint64_t xntable : ((uint64_t)1); + /** @brief defines the "APTable" field in the page */ + uint64_t aptable : ((uint64_t)2); + /** @brief defines the "NSTable" field in the page */ + uint64_t nstable : ((uint64_t)1); +}; + +#pragma pack(pop) + +#endif diff --git a/loader/include/arm/aarch64/l0to.h b/loader/include/arm/aarch64/l0to.h new file mode 100644 index 00000000..8078dd85 --- /dev/null +++ b/loader/include/arm/aarch64/l0to.h @@ -0,0 +1,52 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L0TO_H +#define L0TO_H + +#include + +/** @brief defines the mask used for the L0T offset */ +#define L0T_OFFSET_MASK ((uint64_t)0x1FF) +/** @brief defines the bit location of the L0T offset */ +#define L0T_OFFSET_SHIFT ((uint64_t)39) + +/** + * + * @brief Returns the level-0 table (L0T) offset given a + * virtual address. + * + * + * @param virt the virtual address to get the L0T offset from. + * @return the L0T offset from the virtual address + */ +static inline uint64_t +l0to(uint64_t const virt) +{ + return ((virt >> L0T_OFFSET_SHIFT) & L0T_OFFSET_MASK); +} + +#endif diff --git a/loader/include/arm/aarch64/l1t_t.h b/loader/include/arm/aarch64/l1t_t.h new file mode 100644 index 00000000..6d888136 --- /dev/null +++ b/loader/include/arm/aarch64/l1t_t.h @@ -0,0 +1,55 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L1T_T_H +#define L1T_T_H + +#include +#include +#include + +#pragma pack(push, 1) + +/** @brief defines total number of entries in the L1T */ +#define LOADER_NUM_L1T_ENTRIES ((uint64_t)512) + +/** + * @struct l1t_t + * + * + * @brief Defines the layout of a level-1 table (L1T). + */ +struct l1t_t +{ + /** @brief stores the entries for this page table */ + struct l1te_t entires[LOADER_NUM_L1T_ENTRIES]; + /** @brief stores pointers to child tables */ + struct l2t_t *tables[LOADER_NUM_L1T_ENTRIES]; +}; + +#pragma pack(pop) + +#endif diff --git a/loader/include/arm/aarch64/l1te_t.h b/loader/include/arm/aarch64/l1te_t.h new file mode 100644 index 00000000..c75ee5d7 --- /dev/null +++ b/loader/include/arm/aarch64/l1te_t.h @@ -0,0 +1,64 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L1TE_T +#define L1TE_T + +#include + +#pragma pack(push, 1) + +/** + * @struct l1te_t + * + * + * @brief Defines the layout of a level-1 table entry (L1TE). + */ +struct l1te_t +{ + /** @brief defines the "present" field in the page */ + uint64_t p : ((uint64_t)1); + /** @brief defines the "block/table" field in the page */ + uint64_t bt : ((uint64_t)1); + /** @brief defines the "available to software" field in the page */ + uint64_t available1 : ((uint64_t)10); + /** @brief defines the "physical address" field in the page */ + uint64_t phys : ((uint64_t)40); + /** @brief defines the "available to software" field in the page */ + uint64_t available2 : ((uint64_t)7); + /** @brief defines the "PXNTable" field in the page */ + uint64_t pxntable : ((uint64_t)1); + /** @brief defines the "XNTable" field in the page */ + uint64_t xntable : ((uint64_t)1); + /** @brief defines the "APTable" field in the page */ + uint64_t aptable : ((uint64_t)2); + /** @brief defines the "NSTable" field in the page */ + uint64_t nstable : ((uint64_t)1); +}; + +#pragma pack(pop) + +#endif diff --git a/loader/include/arm/aarch64/l1to.h b/loader/include/arm/aarch64/l1to.h new file mode 100644 index 00000000..79148c3e --- /dev/null +++ b/loader/include/arm/aarch64/l1to.h @@ -0,0 +1,52 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L1TO_H +#define L1TO_H + +#include + +/** @brief defines the mask used for the L1T offset */ +#define L1T_OFFSET_MASK ((uint64_t)0x1FF) +/** @brief defines the bit location of the L1T offset */ +#define L1T_OFFSET_SHIFT ((uint64_t)30) + +/** + * + * @brief Returns the level-1 table (L1T) offset given a + * virtual address. + * + * + * @param virt the virtual address to get the L1T offset from. + * @return the L1T offset from the virtual address + */ +static inline uint64_t +l1to(uint64_t const virt) +{ + return ((virt >> L1T_OFFSET_SHIFT) & L1T_OFFSET_MASK); +} + +#endif diff --git a/loader/include/arm/aarch64/l2t_t.h b/loader/include/arm/aarch64/l2t_t.h new file mode 100644 index 00000000..dda74525 --- /dev/null +++ b/loader/include/arm/aarch64/l2t_t.h @@ -0,0 +1,55 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L2T_T_H +#define L2T_T_H + +#include +#include +#include + +#pragma pack(push, 1) + +/** @brief defines total number of entries in the L2T */ +#define LOADER_NUM_L2T_ENTRIES ((uint64_t)512) + +/** + * @struct l2t_t + * + * + * @brief Defines the layout of a level-2 table (L2T). + */ +struct l2t_t +{ + /** @brief stores the entries for this page table */ + struct l2te_t entires[LOADER_NUM_L2T_ENTRIES]; + /** @brief stores pointers to child tables */ + struct l3t_t *tables[LOADER_NUM_L2T_ENTRIES]; +}; + +#pragma pack(pop) + +#endif diff --git a/loader/include/arm/aarch64/l2te_t.h b/loader/include/arm/aarch64/l2te_t.h new file mode 100644 index 00000000..31a324da --- /dev/null +++ b/loader/include/arm/aarch64/l2te_t.h @@ -0,0 +1,64 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L2TE_T +#define L2TE_T + +#include + +#pragma pack(push, 1) + +/** + * @struct l2te_t + * + * + * @brief Defines the layout of a level-2 table entry (L2TE). + */ +struct l2te_t +{ + /** @brief defines the "present" field in the page */ + uint64_t p : ((uint64_t)1); + /** @brief defines the "block/table" field in the page */ + uint64_t bt : ((uint64_t)1); + /** @brief defines the "available to software" field in the page */ + uint64_t available1 : ((uint64_t)10); + /** @brief defines the "physical address" field in the page */ + uint64_t phys : ((uint64_t)40); + /** @brief defines the "available to software" field in the page */ + uint64_t available2 : ((uint64_t)7); + /** @brief defines the "PXNTable" field in the page */ + uint64_t pxntable : ((uint64_t)1); + /** @brief defines the "XNTable" field in the page */ + uint64_t xntable : ((uint64_t)1); + /** @brief defines the "APTable" field in the page */ + uint64_t aptable : ((uint64_t)2); + /** @brief defines the "NSTable" field in the page */ + uint64_t nstable : ((uint64_t)1); +}; + +#pragma pack(pop) + +#endif diff --git a/loader/include/arm/aarch64/l2to.h b/loader/include/arm/aarch64/l2to.h new file mode 100644 index 00000000..0bda686f --- /dev/null +++ b/loader/include/arm/aarch64/l2to.h @@ -0,0 +1,52 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L2TO_H +#define L2TO_H + +#include + +/** @brief defines the mask used for the L2T offset */ +#define L2T_OFFSET_MASK ((uint64_t)0x1FF) +/** @brief defines the bit location of the L2T offset */ +#define L2T_OFFSET_SHIFT ((uint64_t)21) + +/** + * + * @brief Returns the level-2 table (L2T) offset given a + * virtual address. + * + * + * @param virt the virtual address to get the L2T offset from. + * @return the L2T offset from the virtual address + */ +static inline uint64_t +l2to(uint64_t const virt) +{ + return ((virt >> L2T_OFFSET_SHIFT) & L2T_OFFSET_MASK); +} + +#endif diff --git a/loader/include/arm/aarch64/l3t_t.h b/loader/include/arm/aarch64/l3t_t.h new file mode 100644 index 00000000..e5bd5eb7 --- /dev/null +++ b/loader/include/arm/aarch64/l3t_t.h @@ -0,0 +1,52 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L3T_T_H +#define L3T_T_H + +#include +#include + +#pragma pack(push, 1) + +/** @brief defines total number of entries in the L3T */ +#define LOADER_NUM_L3T_ENTRIES ((uint64_t)512) + +/** + * @struct l3t_t + * + * + * @brief Defines the layout of a level-3 table (L3T). + */ +struct l3t_t +{ + /** @brief stores the entries for this page table */ + struct l3te_t entires[LOADER_NUM_L3T_ENTRIES]; +}; + +#pragma pack(pop) + +#endif diff --git a/loader/include/arm/aarch64/l3te_t.h b/loader/include/arm/aarch64/l3te_t.h new file mode 100644 index 00000000..a1071205 --- /dev/null +++ b/loader/include/arm/aarch64/l3te_t.h @@ -0,0 +1,85 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L3TE_T +#define L3TE_T + +#include + +#pragma pack(push, 1) + +/** @brief used to signal that the page should be non-cached */ +#define bfelf_pf_nc ((uint32_t)0x01000000U) + +/** + * @struct l3te_t + * + * + * @brief Defines the layout of a level-3 table entry (L3TE). + */ +struct l3te_t +{ + /** @brief defines the "present" field in the page */ + uint64_t p : ((uint64_t)1); + /** @brief defines the "page" field in the page */ + uint64_t page : ((uint64_t)1); + /** @brief defines the "AttrIndx" field in the page */ + uint64_t attr_indx : ((uint64_t)3); + /** @brief defines the "NS" field in the page */ + uint64_t ns : ((uint64_t)1); + /** @brief defines the "AP" field in the page */ + uint64_t ap : ((uint64_t)2); + /** @brief defines the "SH" field in the page */ + uint64_t sh : ((uint64_t)2); + /** @brief defines the "AF" field in the page */ + uint64_t af : ((uint64_t)1); + /** @brief defines the "nG" field in the page */ + uint64_t ng : ((uint64_t)1); + /** @brief defines the "physical address" field in the page */ + uint64_t phys : ((uint64_t)38); + /** @brief defines the "GP" field in the page */ + uint64_t gp : ((uint64_t)1); + /** @brief defines the "DBM" field in the page */ + uint64_t dbm : ((uint64_t)1); + /** @brief defines the "Contiguous" field in the page */ + uint64_t contiguous : ((uint64_t)1); + /** @brief defines the "PXN" field in the page */ + uint64_t pxn : ((uint64_t)1); + /** @brief defines the "UXN or XN" field in the page */ + uint64_t xn : ((uint64_t)1); + /** @brief defines our "auto_release" field in the page */ + uint64_t auto_release : ((uint64_t)3); + /** @brief defines the "available to software" field in the page */ + uint64_t available1 : ((uint64_t)1); + /** @brief defines the "PBHA" field in the page */ + uint64_t pbha : ((uint64_t)4); + /** @brief defines the "available to software" field in the page */ + uint64_t available2 : ((uint64_t)1); +}; + +#pragma pack(pop) + +#endif diff --git a/loader/include/arm/aarch64/l3to.h b/loader/include/arm/aarch64/l3to.h new file mode 100644 index 00000000..525a826d --- /dev/null +++ b/loader/include/arm/aarch64/l3to.h @@ -0,0 +1,52 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef L3TO_H +#define L3TO_H + +#include + +/** @brief defines the mask used for the L3T offset */ +#define L3T_OFFSET_MASK ((uint64_t)0x1FF) +/** @brief defines the bit location of the L3T offset */ +#define L3T_OFFSET_SHIFT ((uint64_t)12) + +/** + * + * @brief Returns the level-3 table (L3T) offset given a + * virtual address. + * + * + * @param virt the virtual address to get the L3T offset from. + * @return the L3T offset from the virtual address + */ +static inline uint64_t +l3to(uint64_t const virt) +{ + return ((virt >> L3T_OFFSET_SHIFT) & L3T_OFFSET_MASK); +} + +#endif diff --git a/loader/include/arm/aarch64/read_currentel.h b/loader/include/arm/aarch64/read_currentel.h new file mode 100644 index 00000000..c76c4fe1 --- /dev/null +++ b/loader/include/arm/aarch64/read_currentel.h @@ -0,0 +1,42 @@ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef READ_CURRENTEL_H +#define READ_CURRENTEL_H + +#include + +/** + * + * @brief Returns the value of CurrentEL + * + * + * @return Returns the value of CurrentEL + */ +uint64_t read_currentel(); + +#endif diff --git a/loader/include/arm/aarch64/read_daif.h b/loader/include/arm/aarch64/read_daif.h new file mode 100644 index 00000000..0164edda --- /dev/null +++ b/loader/include/arm/aarch64/read_daif.h @@ -0,0 +1,42 @@ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef READ_DAIF_H +#define READ_DAIF_H + +#include + +/** + * + * @brief Returns the value of DAIF + * + * + * @return Returns the value of DAIF + */ +uint64_t read_daif(); + +#endif diff --git a/loader/include/arm/aarch64/read_hcr_el2.h b/loader/include/arm/aarch64/read_hcr_el2.h new file mode 100644 index 00000000..28aa7c51 --- /dev/null +++ b/loader/include/arm/aarch64/read_hcr_el2.h @@ -0,0 +1,42 @@ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef READ_HCR_EL2_H +#define READ_HCR_EL2_H + +#include + +/** + * + * @brief Returns the value of HCR_EL2 + * + * + * @return Returns the value of HCR_EL2 + */ +uint64_t read_hcr_el2(); + +#endif diff --git a/loader/include/arm/aarch64/read_mair_el2.h b/loader/include/arm/aarch64/read_mair_el2.h new file mode 100644 index 00000000..3edd3220 --- /dev/null +++ b/loader/include/arm/aarch64/read_mair_el2.h @@ -0,0 +1,42 @@ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef READ_MAIR_EL2_H +#define READ_MAIR_EL2_H + +#include + +/** + * + * @brief Returns the value of MAIR_EL2 + * + * + * @return Returns the value of MAIR_EL2 + */ +uint64_t read_mair_el2(); + +#endif diff --git a/loader/include/arm/aarch64/read_sctlr_el2.h b/loader/include/arm/aarch64/read_sctlr_el2.h new file mode 100644 index 00000000..7f213831 --- /dev/null +++ b/loader/include/arm/aarch64/read_sctlr_el2.h @@ -0,0 +1,42 @@ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef READ_SCTLR_EL2_H +#define READ_SCTLR_EL2_H + +#include + +/** + * + * @brief Returns the value of SCTLR_EL2 + * + * + * @return Returns the value of SCTLR_EL2 + */ +uint64_t read_sctlr_el2(); + +#endif diff --git a/loader/include/arm/aarch64/read_spsel.h b/loader/include/arm/aarch64/read_spsel.h new file mode 100644 index 00000000..a5e733f0 --- /dev/null +++ b/loader/include/arm/aarch64/read_spsel.h @@ -0,0 +1,42 @@ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef READ_SPSEL_H +#define READ_SPSEL_H + +#include + +/** + * + * @brief Returns the value of SPSEL + * + * + * @return Returns the value of SPSEL + */ +uint64_t read_spsel(); + +#endif diff --git a/loader/include/arm/aarch64/read_tcr_el2.h b/loader/include/arm/aarch64/read_tcr_el2.h new file mode 100644 index 00000000..7a86ab6a --- /dev/null +++ b/loader/include/arm/aarch64/read_tcr_el2.h @@ -0,0 +1,42 @@ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef READ_TCR_EL2_H +#define READ_TCR_EL2_H + +#include + +/** + * + * @brief Returns the value of TCR_EL2 + * + * + * @return Returns the value of TCR_EL2 + */ +uint64_t read_tcr_el2(); + +#endif diff --git a/loader/include/arm/aarch64/read_ttbr0_el2.h b/loader/include/arm/aarch64/read_ttbr0_el2.h new file mode 100644 index 00000000..443021a4 --- /dev/null +++ b/loader/include/arm/aarch64/read_ttbr0_el2.h @@ -0,0 +1,42 @@ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef READ_TTBR0_EL2_H +#define READ_TTBR0_EL2_H + +#include + +/** + * + * @brief Returns the value of TTBR0_EL2 + * + * + * @return Returns the value of TTBR0_EL2 + */ +uint64_t read_ttbr0_el2(); + +#endif diff --git a/loader/include/arm/aarch64/read_vbar_el2.h b/loader/include/arm/aarch64/read_vbar_el2.h new file mode 100644 index 00000000..96f7d626 --- /dev/null +++ b/loader/include/arm/aarch64/read_vbar_el2.h @@ -0,0 +1,42 @@ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef READ_VBAR_EL2_H +#define READ_VBAR_EL2_H + +#include + +/** + * + * @brief Returns the value of VBAR_EL2 + * + * + * @return Returns the value of VBAR_EL2 + */ +uint64_t read_vbar_el2(); + +#endif diff --git a/loader/include/arm/aarch64/root_page_table_t.h b/loader/include/arm/aarch64/root_page_table_t.h new file mode 100644 index 00000000..8e55051a --- /dev/null +++ b/loader/include/arm/aarch64/root_page_table_t.h @@ -0,0 +1,33 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ROOT_PAGE_TABLE_T_H +#define ROOT_PAGE_TABLE_T_H + +/** @brief defines the type for the root page tables for this arch */ +typedef struct l0t_t root_page_table_t; + +#endif diff --git a/loader/include/interface/c/bfelf/bfelf_elf64_ehdr_t.h b/loader/include/bfelf/bfelf_elf64_ehdr_t.h similarity index 95% rename from loader/include/interface/c/bfelf/bfelf_elf64_ehdr_t.h rename to loader/include/bfelf/bfelf_elf64_ehdr_t.h index 52ad4788..54ee128c 100644 --- a/loader/include/interface/c/bfelf/bfelf_elf64_ehdr_t.h +++ b/loader/include/bfelf/bfelf_elf64_ehdr_t.h @@ -27,8 +27,7 @@ #ifndef BFELF_ELF64_EHDR_T_H #define BFELF_ELF64_EHDR_T_H -#include "bfelf_types.h" - +#include #include #pragma pack(push, 1) @@ -198,15 +197,6 @@ validate_elf64_ehdr(uint8_t const *const file) return BFELF_INVALID_OSABI; } - /** - * TODO: - * - Eventually we can remove this requirement. For now, this ELF - * loader only supports statically linked, non-PIE executables. - * Once this ELF loader is capable of support relocations likes - * its previous version, we can remove this requirement as we - * will then be able to handle both dynamic libraries and binaries. - */ - if (to_ehdr(file)->e_type != bfelf_et_exec) { bferror_x64("invalid e_type", to_ehdr(file)->e_type); return BFELF_INVALID_TYPE; diff --git a/loader/include/interface/c/bfelf/bfelf_elf64_phdr_t.h b/loader/include/bfelf/bfelf_elf64_phdr_t.h similarity index 98% rename from loader/include/interface/c/bfelf/bfelf_elf64_phdr_t.h rename to loader/include/bfelf/bfelf_elf64_phdr_t.h index 539d2c80..0a985786 100644 --- a/loader/include/interface/c/bfelf/bfelf_elf64_phdr_t.h +++ b/loader/include/bfelf/bfelf_elf64_phdr_t.h @@ -27,8 +27,8 @@ #ifndef BFELF_ELF64_PHDR_T_H #define BFELF_ELF64_PHDR_T_H -#include "bfelf_elf64_ehdr_t.h" -#include "bfelf_types.h" +#include +#include #pragma pack(push, 1) diff --git a/loader/include/interface/c/bfelf/bfelf_types.h b/loader/include/bfelf/bfelf_types.h similarity index 100% rename from loader/include/interface/c/bfelf/bfelf_types.h rename to loader/include/bfelf/bfelf_types.h diff --git a/loader/include/x64/check_for_hve_support.h b/loader/include/check_cpu_configuration.h similarity index 85% rename from loader/include/x64/check_for_hve_support.h rename to loader/include/check_cpu_configuration.h index 2fee19e8..ea228fde 100644 --- a/loader/include/x64/check_for_hve_support.h +++ b/loader/include/check_cpu_configuration.h @@ -24,19 +24,19 @@ * SOFTWARE. */ -#ifndef CHECK_FOR_HVE_SUPPORT_H -#define CHECK_FOR_HVE_SUPPORT_H +#ifndef CHECK_CPU_CONFIGURATION_H +#define CHECK_CPU_CONFIGURATION_H #include /** * - * @brief This function checks to see if Intel VT-x support is available on - * the currently running CPU + * @brief This function checks to see if the CPU is supported as well as + * it's system configuration. * * * @return Returns 0 on success */ -int64_t check_for_hve_support(void); +int64_t check_cpu_configuration(void); #endif diff --git a/loader/include/x64/demote.h b/loader/include/demote.h similarity index 100% rename from loader/include/x64/demote.h rename to loader/include/demote.h diff --git a/loader/include/dump_ext_elf_files.h b/loader/include/dump_ext_elf_files.h index be4ba3e3..87ce324e 100644 --- a/loader/include/dump_ext_elf_files.h +++ b/loader/include/dump_ext_elf_files.h @@ -36,7 +36,6 @@ * * * @param files the array of extension ELF files to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_ext_elf_files(struct span_t *const files); diff --git a/loader/include/dump_mk_args.h b/loader/include/dump_mk_args.h index e80162c7..978a6932 100644 --- a/loader/include/dump_mk_args.h +++ b/loader/include/dump_mk_args.h @@ -37,7 +37,6 @@ * * @param args the mk args to output * @param cpu the CPU that this mk args belongs to - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_args(struct mk_args_t *const args, uint32_t const cpu); diff --git a/loader/include/x64/dump_mk_code_aliases.h b/loader/include/dump_mk_code_aliases.h similarity index 96% rename from loader/include/x64/dump_mk_code_aliases.h rename to loader/include/dump_mk_code_aliases.h index 404624c0..be0d780c 100644 --- a/loader/include/x64/dump_mk_code_aliases.h +++ b/loader/include/dump_mk_code_aliases.h @@ -36,7 +36,6 @@ * * * @param a the code_aliases_t to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_code_aliases(struct code_aliases_t *const a); diff --git a/loader/include/dump_mk_debug_ring.h b/loader/include/dump_mk_debug_ring.h index a9ffffb3..790ec60e 100644 --- a/loader/include/dump_mk_debug_ring.h +++ b/loader/include/dump_mk_debug_ring.h @@ -36,7 +36,6 @@ * * * @param debug_ring the mk debug ring to output information about - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_debug_ring(struct debug_ring_t *const debug_ring); diff --git a/loader/include/dump_mk_elf_file.h b/loader/include/dump_mk_elf_file.h index ae605eac..a18554b6 100644 --- a/loader/include/dump_mk_elf_file.h +++ b/loader/include/dump_mk_elf_file.h @@ -36,7 +36,6 @@ * * * @param file the mk elf file to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_elf_file(struct span_t *const file); diff --git a/loader/include/dump_mk_elf_segments.h b/loader/include/dump_mk_elf_segments.h index f17b3887..e3dd550e 100644 --- a/loader/include/dump_mk_elf_segments.h +++ b/loader/include/dump_mk_elf_segments.h @@ -36,7 +36,6 @@ * * * @param segments the array of mk ELF segments to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_elf_segments(struct elf_segment_t *const segments); diff --git a/loader/include/dump_mk_huge_pool.h b/loader/include/dump_mk_huge_pool.h index bfb6a229..4fce84ec 100644 --- a/loader/include/dump_mk_huge_pool.h +++ b/loader/include/dump_mk_huge_pool.h @@ -36,7 +36,6 @@ * * * @param huge_pool the mk huge pool to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_huge_pool(struct mutable_span_t *const huge_pool); diff --git a/loader/include/dump_mk_page_pool.h b/loader/include/dump_mk_page_pool.h index d95145a8..0290f23f 100644 --- a/loader/include/dump_mk_page_pool.h +++ b/loader/include/dump_mk_page_pool.h @@ -36,7 +36,6 @@ * * * @param page_pool the mk page pool to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_page_pool(struct mutable_span_t *const page_pool); diff --git a/loader/include/x64/dump_mk_root_page_table.h b/loader/include/dump_mk_root_page_table.h similarity index 88% rename from loader/include/x64/dump_mk_root_page_table.h rename to loader/include/dump_mk_root_page_table.h index 19f4ba36..46b7bd21 100644 --- a/loader/include/x64/dump_mk_root_page_table.h +++ b/loader/include/dump_mk_root_page_table.h @@ -27,7 +27,7 @@ #ifndef DUMP_MK_ROOT_PAGE_TABLE_H #define DUMP_MK_ROOT_PAGE_TABLE_H -#include +#include #include /** @@ -35,9 +35,8 @@ * @brief Outputs the address of a provided mk root page table. * * - * @param pml4t the mk root page table to output - * @return 0 on success, LOADER_FAILURE on failure. + * @param rpt the mk root page table to output */ -void dump_mk_root_page_table(struct pml4t_t *const pml4t); +void dump_mk_root_page_table(root_page_table_t *const rpt); #endif diff --git a/loader/include/dump_mk_stack.h b/loader/include/dump_mk_stack.h index 8895c8c2..3f36de0e 100644 --- a/loader/include/dump_mk_stack.h +++ b/loader/include/dump_mk_stack.h @@ -37,7 +37,6 @@ * * @param stack the mk stack to output * @param cpu the CPU that this mk stack belongs to - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_stack(struct span_t *const stack, uint32_t const cpu); diff --git a/loader/include/x64/dump_mk_state.h b/loader/include/dump_mk_state.h similarity index 96% rename from loader/include/x64/dump_mk_state.h rename to loader/include/dump_mk_state.h index f00bef7c..b848497e 100644 --- a/loader/include/x64/dump_mk_state.h +++ b/loader/include/dump_mk_state.h @@ -37,7 +37,6 @@ * * @param state the mk state to output * @param cpu the CPU that this mk state belongs to - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_state(struct state_save_t *const state, uint32_t const cpu); diff --git a/loader/include/x64/dump_root_vp_state.h b/loader/include/dump_root_vp_state.h similarity index 96% rename from loader/include/x64/dump_root_vp_state.h rename to loader/include/dump_root_vp_state.h index 12d81d76..ffd4c450 100644 --- a/loader/include/x64/dump_root_vp_state.h +++ b/loader/include/dump_root_vp_state.h @@ -37,7 +37,6 @@ * * @param state the root vp state to output * @param cpu the CPU that this root vp state belongs to - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_root_vp_state(struct state_save_t *const state, uint32_t const cpu); diff --git a/loader/include/dump_vmm_on_error_if_needed.h b/loader/include/dump_vmm_on_error_if_needed.h new file mode 100644 index 00000000..aaadd94a --- /dev/null +++ b/loader/include/dump_vmm_on_error_if_needed.h @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef DUMP_VMM_ON_ERROR_IF_NEEDED_H +#define DUMP_VMM_ON_ERROR_IF_NEEDED_H + +/** + * + * @brief Dumps the contents of the ring buffer in the event of the + * VMM failing to boot. This is only needed on platforms that do not + * have a separate dump capability like UEFI + */ +void dump_vmm_on_error_if_needed(void); + +#endif diff --git a/loader/include/flush_cache.h b/loader/include/flush_cache.h new file mode 100644 index 00000000..79a595f1 --- /dev/null +++ b/loader/include/flush_cache.h @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef FLUSH_CACHE_H +#define FLUSH_CACHE_H + +/** + * + * @brief Flushes the cache line associated with the provided virtual + * address (i.e., ptr) + * + * + * @param ptr the virtual address whose cache line should be flushed + */ +void flush_cache(void const *const ptr); + +#endif diff --git a/loader/include/x64/free_mk_code_aliases.h b/loader/include/free_mk_code_aliases.h similarity index 100% rename from loader/include/x64/free_mk_code_aliases.h rename to loader/include/free_mk_code_aliases.h diff --git a/loader/include/x64/free_mk_root_page_table.h b/loader/include/free_mk_root_page_table.h similarity index 83% rename from loader/include/x64/free_mk_root_page_table.h rename to loader/include/free_mk_root_page_table.h index 5891ac35..0f5549c8 100644 --- a/loader/include/x64/free_mk_root_page_table.h +++ b/loader/include/free_mk_root_page_table.h @@ -27,17 +27,17 @@ #ifndef FREE_MK_ROOT_PAGE_TABLE_H #define FREE_MK_ROOT_PAGE_TABLE_H -#include +#include #include /** * - * @brief Releases a previously allocated pml4t_t that was allocated - * using the alloc_mk_root_page_table function. + * @brief Releases a previously allocated root_page_table_t that was + * allocated using the alloc_mk_root_page_table function. * * - * @param pml4t the pml4t_t to free. + * @param rpt the root_page_table_t to free. */ -void free_mk_root_page_table(struct pml4t_t **const pml4t); +void free_mk_root_page_table(root_page_table_t **const rpt); #endif diff --git a/loader/include/x64/free_mk_state.h b/loader/include/free_mk_state.h similarity index 100% rename from loader/include/x64/free_mk_state.h rename to loader/include/free_mk_state.h diff --git a/loader/include/x64/free_root_vp_state.h b/loader/include/free_root_vp_state.h similarity index 100% rename from loader/include/x64/free_root_vp_state.h rename to loader/include/free_root_vp_state.h diff --git a/loader/include/g_cpu_status.h b/loader/include/g_cpu_status.h new file mode 100644 index 00000000..a5b491ca --- /dev/null +++ b/loader/include/g_cpu_status.h @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef CPU_STATUS_H +#define CPU_STATUS_H + +#include +#include + +/** @brief defines when the CPU is stopped */ +#define CPU_STATUS_STOPPED 0U +/** @brief defines when the CPU is running */ +#define CPU_STATUS_RUNNING 1U +/** @brief defines when the CPU is corrupt */ +#define CPU_STATUS_CORRUPT 2U + +/** @brief stores the current state of each CPU */ +extern uint32_t g_cpu_status[HYPERVISOR_MAX_PPS]; + +#endif diff --git a/loader/include/g_mk_args.h b/loader/include/g_mk_args.h index 6086878d..fe38725b 100644 --- a/loader/include/g_mk_args.h +++ b/loader/include/g_mk_args.h @@ -31,6 +31,6 @@ #include /** @brief stores the microkernel's _start args */ -extern struct mk_args_t *g_mk_args[HYPERVISOR_MAX_VPS_PER_VM]; +extern struct mk_args_t *g_mk_args[HYPERVISOR_MAX_PPS]; #endif diff --git a/loader/include/x64/g_mk_code_aliases.h b/loader/include/g_mk_code_aliases.h similarity index 100% rename from loader/include/x64/g_mk_code_aliases.h rename to loader/include/g_mk_code_aliases.h diff --git a/loader/include/x64/g_mk_root_page_table.h b/loader/include/g_mk_root_page_table.h similarity index 88% rename from loader/include/x64/g_mk_root_page_table.h rename to loader/include/g_mk_root_page_table.h index 4d046f6e..3443a4c4 100644 --- a/loader/include/x64/g_mk_root_page_table.h +++ b/loader/include/g_mk_root_page_table.h @@ -28,12 +28,9 @@ #define G_MK_ROOT_PAGE_TABLE_H #include -#include - -/** @brief defines the type for the root page tables for this arch */ -typedef struct pml4t_t *root_page_table_t; +#include /** @brief stores pml4 for the microkernel */ -extern root_page_table_t g_mk_root_page_table; +extern root_page_table_t *g_mk_root_page_table; #endif diff --git a/loader/include/g_mk_stack.h b/loader/include/g_mk_stack.h index ba26636b..f63d6b91 100644 --- a/loader/include/g_mk_stack.h +++ b/loader/include/g_mk_stack.h @@ -32,7 +32,7 @@ #include /** @brief stores the stack used by the microkernel */ -extern struct span_t g_mk_stack[HYPERVISOR_MAX_VPS_PER_VM]; +extern struct span_t g_mk_stack[HYPERVISOR_MAX_PPS]; /** @brief stores the virtual address of the MK's stack */ extern uint64_t g_mk_stack_virt; diff --git a/loader/include/x64/g_mk_state.h b/loader/include/g_mk_state.h similarity index 95% rename from loader/include/x64/g_mk_state.h rename to loader/include/g_mk_state.h index f72f0356..df9de206 100644 --- a/loader/include/x64/g_mk_state.h +++ b/loader/include/g_mk_state.h @@ -31,6 +31,6 @@ #include /** @brief stores the microkernel state saves */ -extern struct state_save_t *g_mk_state[HYPERVISOR_MAX_VPS_PER_VM]; +extern struct state_save_t *g_mk_state[HYPERVISOR_MAX_PPS]; #endif diff --git a/loader/include/x64/g_root_vp_state.h b/loader/include/g_root_vp_state.h similarity index 94% rename from loader/include/x64/g_root_vp_state.h rename to loader/include/g_root_vp_state.h index 22f0e5fd..5ea9759e 100644 --- a/loader/include/x64/g_root_vp_state.h +++ b/loader/include/g_root_vp_state.h @@ -31,6 +31,6 @@ #include /** @brief stores the root VP state saves */ -extern struct state_save_t *g_root_vp_state[HYPERVISOR_MAX_VPS_PER_VM]; +extern struct state_save_t *g_root_vp_state[HYPERVISOR_MAX_PPS]; #endif diff --git a/loader/include/vmm_status.h b/loader/include/g_vmm_status.h similarity index 100% rename from loader/include/vmm_status.h rename to loader/include/g_vmm_status.h diff --git a/loader/include/x64/get_mk_huge_pool_addr.h b/loader/include/get_mk_huge_pool_addr.h similarity index 100% rename from loader/include/x64/get_mk_huge_pool_addr.h rename to loader/include/get_mk_huge_pool_addr.h diff --git a/loader/include/x64/get_mk_page_pool_addr.h b/loader/include/get_mk_page_pool_addr.h similarity index 100% rename from loader/include/x64/get_mk_page_pool_addr.h rename to loader/include/get_mk_page_pool_addr.h diff --git a/loader/include/interface/c/arm/aarch64/state_save_t.h b/loader/include/interface/c/arm/aarch64/state_save_t.h new file mode 100644 index 00000000..050e56cc --- /dev/null +++ b/loader/include/interface/c/arm/aarch64/state_save_t.h @@ -0,0 +1,166 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef STATE_SAVE_T_H +#define STATE_SAVE_T_H + +#include + +#pragma pack(push, 1) + +/** + * @struct state_save_t + * + * + * @brief Stores the registers and processor state that is used by the + * microkernel that must be restored in the event of an error or the + * successful launch of the hypervisor. + */ +struct state_save_t +{ + /**************************************************************************/ + /* General Purpose Registers */ + /**************************************************************************/ + + /** @brief stores the value of x0 (0x000) */ + uint64_t x0; + /** @brief stores the value of x1 (0x008) */ + uint64_t x1; + /** @brief stores the value of x2 (0x010) */ + uint64_t x2; + /** @brief stores the value of x3 (0x018) */ + uint64_t x3; + /** @brief stores the value of x4 (0x020) */ + uint64_t x4; + /** @brief stores the value of x5 (0x028) */ + uint64_t x5; + /** @brief stores the value of x6 (0x030) */ + uint64_t x6; + /** @brief stores the value of x7 (0x038) */ + uint64_t x7; + /** @brief stores the value of x8 (0x040) */ + uint64_t x8; + /** @brief stores the value of x9 (0x048) */ + uint64_t x9; + /** @brief stores the value of x10 (0x050) */ + uint64_t x10; + /** @brief stores the value of x11 (0x058) */ + uint64_t x11; + /** @brief stores the value of x12 (0x060) */ + uint64_t x12; + /** @brief stores the value of x13 (0x068) */ + uint64_t x13; + /** @brief stores the value of x14 (0x070) */ + uint64_t x14; + /** @brief stores the value of x15 (0x078) */ + uint64_t x15; + /** @brief stores the value of x16 (0x080) */ + uint64_t x16; + /** @brief stores the value of x17 (0x088) */ + uint64_t x17; + /** @brief stores the value of x18 (0x090) */ + uint64_t x18; + /** @brief stores the value of x19 (0x098) */ + uint64_t x19; + /** @brief stores the value of x20 (0x0A0) */ + uint64_t x20; + /** @brief stores the value of x21 (0x0A8) */ + uint64_t x21; + /** @brief stores the value of x22 (0x0B0) */ + uint64_t x22; + /** @brief stores the value of x23 (0x0B8) */ + uint64_t x23; + /** @brief stores the value of x24 (0x0C0) */ + uint64_t x24; + /** @brief stores the value of x25 (0x0C8) */ + uint64_t x25; + /** @brief stores the value of x26 (0x0D0) */ + uint64_t x26; + /** @brief stores the value of x27 (0x0D8) */ + uint64_t x27; + /** @brief stores the value of x28 (0x0E0) */ + uint64_t x28; + /** @brief stores the value of x29 (0x0E8) */ + uint64_t x29; + /** @brief stores the value of x30 (0x0F0) */ + uint64_t x30; + /** @brief stores the value of sp_el2 (0x0F8) */ + uint64_t sp_el2; + /** @brief stores the value of pc_el2 (0x100) */ + uint64_t pc_el2; + + /**************************************************************************/ + /* Saved Program Status Registers (SPSR) */ + /**************************************************************************/ + + /** @brief stores the value of daif (0x108) */ + uint64_t daif; + /** @brief stores the value of spsel (0x110) */ + uint64_t spsel; + + /** @brief reserved for future use (0x118) */ + uint64_t reserved0[0xE]; + + /**************************************************************************/ + /* Exceptions */ + /**************************************************************************/ + + /** @brief stores the value of vbar_el2 (0x188) */ + uint64_t vbar_el2; + + /**************************************************************************/ + /* System Registers */ + /**************************************************************************/ + + /** @brief stores the value of hcr_el2 (0x190) */ + uint64_t hcr_el2; + /** @brief stores the value of mair_el2 (0x198) */ + uint64_t mair_el2; + /** @brief stores the value of sctlr_el2 (0x1A0) */ + uint64_t sctlr_el2; + /** @brief stores the value of tcr_el2 (0x1A8) */ + uint64_t tcr_el2; + /** @brief stores the value of ttbr0_el2 (0x1B0) */ + uint64_t ttbr0_el2; + /** @brief stores the value of tpidr_el2 (0x1B8) */ + uint64_t tpidr_el2; + + /** @brief reserved for future use (0x1C0) */ + uint64_t reserved1[0xA]; + + /**************************************************************************/ + /* Handlers */ + /**************************************************************************/ + + /** @brief stores the promote handler (0x210) */ + void *promote_handler; + /** @brief stores the exception vectors (0x218) */ + void *exception_vectors; +}; + +#pragma pack(pop) + +#endif diff --git a/loader/include/interface/c/debug_ring_t.h b/loader/include/interface/c/debug_ring_t.h index 48c11265..acc226ae 100644 --- a/loader/include/interface/c/debug_ring_t.h +++ b/loader/include/interface/c/debug_ring_t.h @@ -28,7 +28,6 @@ #define DEBUG_RING_T_H #include -#include #include #pragma pack(push, 1) diff --git a/loader/include/interface/c/dump_vmm_args_t.h b/loader/include/interface/c/dump_vmm_args_t.h index 975598eb..1a059360 100644 --- a/loader/include/interface/c/dump_vmm_args_t.h +++ b/loader/include/interface/c/dump_vmm_args_t.h @@ -27,8 +27,7 @@ #ifndef DUMP_VMM_ARGS_T_H #define DUMP_VMM_ARGS_T_H -#include "debug_ring_t.h" - +#include #include #pragma pack(push, 1) diff --git a/loader/include/interface/c/x64/mk_args_t.h b/loader/include/interface/c/mk_args_t.h similarity index 79% rename from loader/include/interface/c/x64/mk_args_t.h rename to loader/include/interface/c/mk_args_t.h index ca37a459..053a00bf 100644 --- a/loader/include/interface/c/x64/mk_args_t.h +++ b/loader/include/interface/c/mk_args_t.h @@ -27,13 +27,11 @@ #ifndef MK_ARGS_T_H #define MK_ARGS_T_H -#include "../debug_ring_t.h" -#include "../mutable_span_t.h" -#include "../span_t.h" -#include "state_save_t.h" - #include -#include +#include +#include +#include +#include #include #pragma pack(push, 1) @@ -49,12 +47,12 @@ */ struct mk_args_t { - /** @brief stores the current pp */ - uint16_t pp; - /** @brief stores the number of online pps */ + /** @brief stores the current ppid (0x000) */ + uint16_t ppid; + /** @brief stores the number of online pps (0x002) */ uint16_t online_pps; - /** @brief reserved */ - uint32_t reserved2; + /** @brief reserved (0x004) */ + uint32_t reserved; /** @brief stores the location of the microkernel's state (0x008) */ struct state_save_t *mk_state; /** @brief stores the location of the root vp state (0x010) */ @@ -71,17 +69,10 @@ struct mk_args_t uint64_t rpt_phys; /** @brief stores the location of the microkernel's page pool */ struct mutable_span_t page_pool; - /** @brief stores the starting location of the page pool's direct map */ - uint64_t page_pool_base_virt; /** @brief stores the location of the microkernel's huge pool */ struct mutable_span_t huge_pool; - /** @brief stores the starting location of the huge pool's direct map */ - uint64_t huge_pool_base_virt; }; -/** @brief Check to make sure the mk_args_t is the right size. */ -STATIC_ASSERT(sizeof(struct mk_args_t) <= HYPERVISOR_PAGE_SIZE, invalid_size); - #pragma pack(pop) #endif diff --git a/loader/include/interface/c/start_vmm_args_t.h b/loader/include/interface/c/start_vmm_args_t.h index 15685b73..14f76848 100644 --- a/loader/include/interface/c/start_vmm_args_t.h +++ b/loader/include/interface/c/start_vmm_args_t.h @@ -27,9 +27,8 @@ #ifndef START_VMM_ARGS_T_H #define START_VMM_ARGS_T_H -#include "span_t.h" - #include +#include #include #pragma pack(push, 1) diff --git a/loader/include/interface/c/x64/cpuid_commands.h b/loader/include/interface/c/x64/cpuid_commands.h index 2358b3b7..62bba685 100644 --- a/loader/include/interface/c/x64/cpuid_commands.h +++ b/loader/include/interface/c/x64/cpuid_commands.h @@ -39,4 +39,9 @@ /** @brief defines the value of ECX for the CPUID report off command */ #define CPUID_COMMAND_ECX_REPORT_OFF ((uint32_t)0xBF000002U) +/** @brief defines the value of RAX on success */ +#define CPUID_COMMAND_RAX_SUCCESS ((uint64_t)0x0U) +/** @brief defines the value of RAX on failure */ +#define CPUID_COMMAND_RAX_FAILURE ((uint64_t)0x1U) + #endif diff --git a/loader/include/interface/c/x64/global_descriptor_table_register_t.h b/loader/include/interface/c/x64/global_descriptor_table_register_t.h index 1a552306..1eed651c 100644 --- a/loader/include/interface/c/x64/global_descriptor_table_register_t.h +++ b/loader/include/interface/c/x64/global_descriptor_table_register_t.h @@ -27,7 +27,6 @@ #ifndef GLOBAL_DESCRIPTOR_TABLE_REGISTER_T_H #define GLOBAL_DESCRIPTOR_TABLE_REGISTER_T_H -#include #include #pragma pack(push, 1) @@ -47,9 +46,6 @@ struct global_descriptor_table_register_t uint64_t *base; }; -/** @brief Check to make sure the gdtr_t is the right size. */ -STATIC_ASSERT(sizeof(struct global_descriptor_table_register_t) == 10, invalid_size); - #pragma pack(pop) #endif diff --git a/loader/include/interface/c/x64/interrupt_descriptor_table_register_t.h b/loader/include/interface/c/x64/interrupt_descriptor_table_register_t.h index 370708cb..9f2f2b0f 100644 --- a/loader/include/interface/c/x64/interrupt_descriptor_table_register_t.h +++ b/loader/include/interface/c/x64/interrupt_descriptor_table_register_t.h @@ -27,7 +27,6 @@ #ifndef INTERRUPT_DESCRIPTOR_TABLE_REGISTER_T_H #define INTERRUPT_DESCRIPTOR_TABLE_REGISTER_T_H -#include #include #pragma pack(push, 1) @@ -47,9 +46,6 @@ struct interrupt_descriptor_table_register_t uint64_t *base; }; -/** @brief Check to make sure the idtr_t is the right size. */ -STATIC_ASSERT(sizeof(struct interrupt_descriptor_table_register_t) == 10, invalid_size); - #pragma pack(pop) #endif diff --git a/loader/include/interface/c/x64/state_save_t.h b/loader/include/interface/c/x64/state_save_t.h index c7149a20..f8e81423 100644 --- a/loader/include/interface/c/x64/state_save_t.h +++ b/loader/include/interface/c/x64/state_save_t.h @@ -27,11 +27,9 @@ #ifndef STATE_SAVE_T_H #define STATE_SAVE_T_H -#include "global_descriptor_table_register_t.h" -#include "interrupt_descriptor_table_register_t.h" -#include "tss_t.h" - -#include +#include +#include +#include #include #pragma pack(push, 1) @@ -40,19 +38,9 @@ * @struct state_save_t * * - * @brief Stores state information for both Intel and AMD. Specifically, - * for a field to be included in this list, it must: - * - Be saved/restored by the VMCS/VMCB, meaning HVE will touch the field - * either because we don't have a choice, or because we enable HVE - * to do so (example being EFER and PAT on Intel) - * - Because the Microkernel needs it's own version of the field. - * - * This list provides the set of all registers that meet the criteria - * above. It should be noted that this is the common set of fields - * for both Intel and AMD. To ensure consistency, the Microkernel will - * save/restore these fields on every VMExit/VMEntry. This ensures - * extensions can use this list of fields as documentation as to which - * fields it will have to deal with on its own. + * @brief Stores the registers and processor state that is used by the + * microkernel that must be restored in the event of an error or the + * successful launch of the hypervisor. */ struct state_save_t { @@ -299,9 +287,6 @@ struct state_save_t uint64_t nmi; }; -/** @brief Check to make sure the state_save_t is the right size. */ -STATIC_ASSERT(sizeof(struct state_save_t) == 0x320, invalid_size); - #pragma pack(pop) #endif diff --git a/loader/include/interface/c/x64/tss_t.h b/loader/include/interface/c/x64/tss_t.h index 0fbc3546..c437c2df 100644 --- a/loader/include/interface/c/x64/tss_t.h +++ b/loader/include/interface/c/x64/tss_t.h @@ -28,7 +28,6 @@ #define TSS_T_H #include -#include #include #pragma pack(push, 1) @@ -78,9 +77,6 @@ struct tss_t uint16_t iomap; }; -/** @brief Check to make sure the state_save_t is the right size. */ -STATIC_ASSERT(sizeof(struct tss_t) <= HYPERVISOR_PAGE_SIZE, invalid_size); - #pragma pack(pop) #endif diff --git a/loader/include/interface/cpp/.clang-format b/loader/include/interface/cpp/.clang-format deleted file mode 100644 index 7d98f7b0..00000000 --- a/loader/include/interface/cpp/.clang-format +++ /dev/null @@ -1,138 +0,0 @@ -# -# Copyright (C) 2020 Assured Information Security, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -AccessModifierOffset: -4 -AlignAfterOpenBracket: AlwaysBreak -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlines: Right -AlignOperands: true -AlignTrailingComments: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: None -AllowShortIfStatementsOnASingleLine: false -AllowShortLambdasOnASingleLine: Empty -AllowShortLoopsOnASingleLine: false -# AlwaysBreakAfterDefinitionReturnType -AlwaysBreakAfterReturnType: AllDefinitions -AlwaysBreakBeforeMultilineStrings: true -AlwaysBreakTemplateDeclarations: Yes -BinPackArguments: false -BinPackParameters: false -BraceWrapping: - AfterClass: true - AfterControlStatement: false - AfterEnum: true - AfterFunction: true - AfterNamespace: true - # AfterObjCDeclaration - AfterStruct: true - AfterUnion: true - AfterExternBlock: true - BeforeCatch: true - BeforeElse: true - IndentBraces: false - SplitEmptyFunction: false - SplitEmptyRecord: false - SplitEmptyNamespace: false -# BreakAfterJavaFieldAnnotations -BreakBeforeBinaryOperators: None -BreakBeforeBraces: Custom -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeComma -BreakInheritanceList: AfterColon -BreakStringLiterals: true -ColumnLimit: 100 -# CommentPragmas -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: true -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -# DisableFormat -# ExperimentalAutoDetectBinPacking -FixNamespaceComments: false -# ForEachMacros -IncludeBlocks: Regroup -IncludeCategories: - # Headers in <> from specific external libraries. - - Regex: '<(bsl)\/' - Priority: 3 - # Headers in <> with extension. - - Regex: '<([A-Za-z0-9.\Q/-_\E])+>' - Priority: 2 - # Headers in "" with extension. - - Regex: '"([A-Za-z0-9.\Q/-_\E])+"' - Priority: 1 -# IncludeIsMainRegex -IndentCaseLabels: true -IndentPPDirectives: None -IndentWidth: 4 -IndentWrappedFunctionNames: false -# JavaImportGroups -# JavaScriptQuotes -# JavaScriptWrapImports -KeepEmptyLinesAtTheStartOfBlocks: true -Language: Cpp -# MacroBlockBegin -# MacroBlockEnd -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: All -# ObjCBinPackProtocolList -# ObjCBlockIndentWidth -# ObjCSpaceAfterProperty -# ObjCSpaceBeforeProtocolList -# PenaltyBreakAssignment -# PenaltyBreakBeforeFirstCallParameter -# PenaltyBreakComment -# PenaltyBreakFirstLessLess -# PenaltyBreakString -# PenaltyBreakTemplateDeclaration -# PenaltyExcessCharacter -# PenaltyReturnTypeOnItsOwnLine -PointerAlignment: Right -# RawStringFormats -ReflowComments: false -SortIncludes: true -SortUsingDeclarations: false -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: true -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 4 -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Auto -# StatementMacros -# TabWidth -UseTab: Never diff --git a/loader/include/interface/cpp/arm/aarch64/cpuid_commands.hpp b/loader/include/interface/cpp/arm/aarch64/cpuid_commands.hpp new file mode 100644 index 00000000..8248bde2 --- /dev/null +++ b/loader/include/interface/cpp/arm/aarch64/cpuid_commands.hpp @@ -0,0 +1,43 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef CPUID_COMMANDS_HPP +#define CPUID_COMMANDS_HPP + +#include +#include + +namespace loader +{ + /// @brief defines the value of EAX for all CPUID commands + constexpr auto CPUID_COMMAND_EAX{0x400000FF_u32}; + /// @brief defines the value of ECX for the CPUID stop command + constexpr auto CPUID_COMMAND_ECX_STOP{0xBF000000_u32}; + /// @brief defines the value of ECX for the CPUID report on command + constexpr auto CPUID_COMMAND_ECX_REPORT_ON{0xBF000001_u32}; + /// @brief defines the value of ECX for the CPUID report off command + constexpr auto CPUID_COMMAND_ECX_REPORT_OFF{0xBF000002_u32}; +} + +#endif diff --git a/loader/include/interface/cpp/arm/aarch64/state_save_t.hpp b/loader/include/interface/cpp/arm/aarch64/state_save_t.hpp new file mode 100644 index 00000000..5f4ea66e --- /dev/null +++ b/loader/include/interface/cpp/arm/aarch64/state_save_t.hpp @@ -0,0 +1,174 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef STATE_SAVE_T_HPP +#define STATE_SAVE_T_HPP + +#include +#include +#include +#include + +#pragma pack(push, 1) + +namespace loader +{ + /// @brief the size of reserved #0 in the state_save_t + constexpr auto SS_RESERVED0_SIZE{0xE_umax}; + /// @brief the size of reserved #1 in the state_save_t + constexpr auto SS_RESERVED1_SIZE{0xA_umax}; + + /// @struct loader::state_save_t + /// + /// + /// @brief Stores the registers and processor state that is used by the + /// microkernel that must be restored in the event of an error or the + /// successful launch of the hypervisor. + /// + struct state_save_t final + { + /// -------------------------------------------------------------------- + /// General Purpose Registers + /// -------------------------------------------------------------------- + + /// @brief stores the value of x0 (0x000) + bsl::uint64 x0; + /// @brief stores the value of x1 (0x008) + bsl::uint64 x1; + /// @brief stores the value of x2 (0x010) + bsl::uint64 x2; + /// @brief stores the value of x3 (0x018) + bsl::uint64 x3; + /// @brief stores the value of x4 (0x020) + bsl::uint64 x4; + /// @brief stores the value of x5 (0x028) + bsl::uint64 x5; + /// @brief stores the value of x6 (0x030) + bsl::uint64 x6; + /// @brief stores the value of x7 (0x038) + bsl::uint64 x7; + /// @brief stores the value of x8 (0x040) + bsl::uint64 x8; + /// @brief stores the value of x9 (0x048) + bsl::uint64 x9; + /// @brief stores the value of x10 (0x050) + bsl::uint64 x10; + /// @brief stores the value of x11 (0x058) + bsl::uint64 x11; + /// @brief stores the value of x12 (0x060) + bsl::uint64 x12; + /// @brief stores the value of x13 (0x068) + bsl::uint64 x13; + /// @brief stores the value of x14 (0x070) + bsl::uint64 x14; + /// @brief stores the value of x15 (0x078) + bsl::uint64 x15; + /// @brief stores the value of x16 (0x080) + bsl::uint64 x16; + /// @brief stores the value of x17 (0x088) + bsl::uint64 x17; + /// @brief stores the value of x18 (0x090) + bsl::uint64 x18; + /// @brief stores the value of x19 (0x098) + bsl::uint64 x19; + /// @brief stores the value of x20 (0x0A0) + bsl::uint64 x20; + /// @brief stores the value of x21 (0x0A8) + bsl::uint64 x21; + /// @brief stores the value of x22 (0x0B0) + bsl::uint64 x22; + /// @brief stores the value of x23 (0x0B8) + bsl::uint64 x23; + /// @brief stores the value of x24 (0x0C0) + bsl::uint64 x24; + /// @brief stores the value of x25 (0x0C8) + bsl::uint64 x25; + /// @brief stores the value of x26 (0x0D0) + bsl::uint64 x26; + /// @brief stores the value of x27 (0x0D8) + bsl::uint64 x27; + /// @brief stores the value of x28 (0x0E0) + bsl::uint64 x28; + /// @brief stores the value of x29 (0x0E8) + bsl::uint64 x29; + /// @brief stores the value of x30 (0x0F0) + bsl::uint64 x30; + /// @brief stores the value of sp_el2 (0x0F8) + bsl::uint64 sp_el2; + /// @brief stores the value of pc_el2 (0x100) + bsl::uint64 pc_el2; + + /// -------------------------------------------------------------------- + /// Saved Program Status Registers (SPSR) + /// -------------------------------------------------------------------- + + /// @brief stores the value of daif (0x108) + bsl::uint64 daif; + /// @brief stores the value of spsel (0x110) + bsl::uint64 spsel; + + /// @brief reserved for future use (0x118) + bsl::details::carray reserved0; + + /// -------------------------------------------------------------------- + /// Exceptions + /// -------------------------------------------------------------------- + + /// @brief stores the value of vbar_el2 (0x188) + bsl::uint64 vbar_el2; + + /// -------------------------------------------------------------------- + /// System Registers + /// -------------------------------------------------------------------- + + /// @brief stores the value of hcr_el2 (0x190) + bsl::uint64 hcr_el2; + /// @brief stores the value of mair_el2 (0x198) + bsl::uint64 mair_el2; + /// @brief stores the value of sctlr_el2 (0x1A0) + bsl::uint64 sctlr_el2; + /// @brief stores the value of tcr_el2 (0x1A8) + bsl::uint64 tcr_el2; + /// @brief stores the value of ttbr0_el2 (0x1B0) + bsl::uint64 ttbr0_el2; + /// @brief stores the value of tpidr_el2 (0x1B8) + bsl::uint64 tpidr_el2; + + /// @brief reserved for future use (0x1C0) + bsl::details::carray reserved1; + + /// -------------------------------------------------------------------- + /// Handlers + /// -------------------------------------------------------------------- + + /// @brief stores the promote handler (0x210) + void *promote_handler; + /// @brief stores the exception vectors (0x218) + void *exception_vectors; + }; +} + +#pragma pack(pop) + +#endif diff --git a/loader/include/interface/cpp/debug_ring_t.hpp b/loader/include/interface/cpp/debug_ring_t.hpp index 3e4c4be4..e02f2118 100644 --- a/loader/include/interface/cpp/debug_ring_t.hpp +++ b/loader/include/interface/cpp/debug_ring_t.hpp @@ -48,7 +48,7 @@ namespace loader bsl::uint64 spos; /// @brief stores the characters in the debug ring - bsl::details::carray buf; + bsl::details::carray buf; }; } diff --git a/loader/include/interface/cpp/dump_vmm_args_t.hpp b/loader/include/interface/cpp/dump_vmm_args_t.hpp index 2f7c23d6..eabfcea1 100644 --- a/loader/include/interface/cpp/dump_vmm_args_t.hpp +++ b/loader/include/interface/cpp/dump_vmm_args_t.hpp @@ -25,7 +25,7 @@ #ifndef DUMP_VMM_ARGS_T_HPP #define DUMP_VMM_ARGS_T_HPP -#include "debug_ring_t.hpp" +#include #include #include @@ -36,7 +36,7 @@ namespace loader { /// @brief defines the IOCTL index for dumping a VMs debug ring - constexpr bsl::safe_uint32 DUMP_VMM_CMD{bsl::to_u32(0xBF03)}; + constexpr auto DUMP_VMM_CMD{0xBF03_u32}; /// @struct loader::dump_vmm_args_t /// diff --git a/loader/include/interface/cpp/x64/mk_args_t.hpp b/loader/include/interface/cpp/mk_args_t.hpp similarity index 72% rename from loader/include/interface/cpp/x64/mk_args_t.hpp rename to loader/include/interface/cpp/mk_args_t.hpp index cb89c0e6..b24056e6 100644 --- a/loader/include/interface/cpp/x64/mk_args_t.hpp +++ b/loader/include/interface/cpp/mk_args_t.hpp @@ -25,10 +25,10 @@ #ifndef MK_ARGS_T_HPP #define MK_ARGS_T_HPP -#include "state_save_t.hpp" +#include +#include #include -#include #include #include #include @@ -48,12 +48,12 @@ namespace loader /// struct mk_args_t final { - /// @brief reserved - bsl::uint16 reserved1; - /// @brief stores the number of online pps + /// @brief stores the current ppid (0x000) + bsl::uint16 ppid; + /// @brief stores the number of online pps (0x002) bsl::uint16 online_pps; - /// @brief reserved - bsl::uint32 reserved2; + /// @brief reserved (0x004) + bsl::uint32 reserved; /// @brief stores the location of the microkernel's state (0x008) state_save_t *mk_state; /// @brief stores the location of the root vp state (0x010) @@ -61,31 +61,18 @@ namespace loader /// @brief stores the location of the debug ring (0x018) debug_ring_t *debug_ring; /// @brief stores the location of the microkernel's ELF file - bsl::span mk_elf_file; + bsl::span mk_elf_file; /// @brief stores the location of the extension's ELF files - bsl::array, HYPERVISOR_MAX_EXTENSIONS> ext_elf_files; + bsl::array, HYPERVISOR_MAX_EXTENSIONS.get()> ext_elf_files; /// @brief stores the virtual address of the MK's RPT for this CPU void *rpt; /// @brief stores the physical address of the MK's RPT for this CPU bsl::uint64 rpt_phys; /// @brief stores the location of the microkernel's page pool - bsl::span page_pool; - /// @brief stores the starting location of the page pool's direct map - bsl::uint64 page_pool_base_virt; + bsl::span page_pool; /// @brief stores the location of the microkernel's huge pool - bsl::span huge_pool; - /// @brief stores the starting location of the huge pool's direct map - bsl::uint64 huge_pool_base_virt; + bsl::span huge_pool; }; - - namespace details - { - /// @brief defined the expected size of the mk_args_t struct - constexpr bsl::safe_uintmax EXPECTED_MK_ARGS_T_SIZE{bsl::to_umax(HYPERVISOR_PAGE_SIZE)}; - - /// Check to make sure the mk_args_t is the right size. - static_assert(!(sizeof(mk_args_t) > EXPECTED_MK_ARGS_T_SIZE)); - } } #pragma pack(pop) diff --git a/loader/include/interface/cpp/page_pool_node_t.hpp b/loader/include/interface/cpp/page_pool_node_t.hpp new file mode 100644 index 00000000..abbda254 --- /dev/null +++ b/loader/include/interface/cpp/page_pool_node_t.hpp @@ -0,0 +1,58 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef PAGE_POOL_NODE_T_HPP +#define PAGE_POOL_NODE_T_HPP + +#include +#include +#include + +#pragma pack(push, 1) + +namespace loader +{ + /// @brief stores the size of the data portion of page_pool_node_t + constexpr auto PAGE_POOL_NODE_T_DATA_SIZE{0xFF8_umax}; + + /// @struct loader::page_pool_node_t + /// + /// + /// @brief Defines the structure of the microkernel's debug ring + /// + struct page_pool_node_t final + { + /// @brief a pointer to the next page in the page pool + page_pool_node_t *next; + /// @brief stores the page of memory itself + bsl::details::carray data; + }; + + /// @brief make sure that a page pool node is the size of a page. + static_assert(sizeof(page_pool_node_t) == HYPERVISOR_PAGE_SIZE); +} + +#pragma pack(pop) + +#endif diff --git a/loader/include/interface/cpp/start_vmm_args_t.hpp b/loader/include/interface/cpp/start_vmm_args_t.hpp index 22f21016..c6c0608f 100644 --- a/loader/include/interface/cpp/start_vmm_args_t.hpp +++ b/loader/include/interface/cpp/start_vmm_args_t.hpp @@ -25,10 +25,7 @@ #ifndef START_VMM_ARGS_T_HPP #define START_VMM_ARGS_T_HPP -#include - #include -#include #include #include #include @@ -39,7 +36,13 @@ namespace loader { /// @brief defines the IOCTL index for starting the VMM - constexpr bsl::safe_uint32 START_VMM_CMD{bsl::to_u32(0xBF01)}; + constexpr auto START_VMM_CMD{0xBF01_u32}; + + /// @brief defines the type used for passing the ext ELF files + using ext_elf_file_type = bsl::span; + + /// @brief defines the type used for passing the ext ELF files + using ext_elf_files_type = bsl::array; /// @struct loader::start_vmm_args_t /// @@ -61,9 +64,9 @@ namespace loader bsl::uint32 reserved; /// @brief stores the ELF file associated with the microkernel - bsl::span mk_elf_file; + bsl::span mk_elf_file; /// @brief stores the ELF files associated with the extensions - bsl::array, HYPERVISOR_MAX_EXTENSIONS> ext_elf_files; + ext_elf_files_type ext_elf_files; }; } diff --git a/loader/include/interface/cpp/stop_vmm_args_t.hpp b/loader/include/interface/cpp/stop_vmm_args_t.hpp index 2b1dc398..37f4cce0 100644 --- a/loader/include/interface/cpp/stop_vmm_args_t.hpp +++ b/loader/include/interface/cpp/stop_vmm_args_t.hpp @@ -34,7 +34,7 @@ namespace loader { /// @brief defines the IOCTL index for stopping the VMM - constexpr bsl::safe_uint32 STOP_VMM_CMD{bsl::to_u32(0xBF02)}; + constexpr auto STOP_VMM_CMD{0xBF02_u32}; /// @struct loader::stop_vmm_args_t /// diff --git a/loader/include/interface/cpp/x64/cpuid_commands.hpp b/loader/include/interface/cpp/x64/cpuid_commands.hpp index 48272062..03bad653 100644 --- a/loader/include/interface/cpp/x64/cpuid_commands.hpp +++ b/loader/include/interface/cpp/x64/cpuid_commands.hpp @@ -31,13 +31,18 @@ namespace loader { /// @brief defines the value of EAX for all CPUID commands - constexpr bsl::safe_uint32 CPUID_COMMAND_EAX{bsl::to_u32(0x400000FFU)}; + constexpr auto CPUID_COMMAND_EAX{0x400000FF_u32}; /// @brief defines the value of ECX for the CPUID stop command - constexpr bsl::safe_uint32 CPUID_COMMAND_ECX_STOP{bsl::to_u32(0xBF000000U)}; + constexpr auto CPUID_COMMAND_ECX_STOP{0xBF000000_u32}; /// @brief defines the value of ECX for the CPUID report on command - constexpr bsl::safe_uint32 CPUID_COMMAND_ECX_REPORT_ON{bsl::to_u32(0xBF000001U)}; + constexpr auto CPUID_COMMAND_ECX_REPORT_ON{0xBF000001_u32}; /// @brief defines the value of ECX for the CPUID report off command - constexpr bsl::safe_uint32 CPUID_COMMAND_ECX_REPORT_OFF{bsl::to_u32(0xBF000002U)}; + constexpr auto CPUID_COMMAND_ECX_REPORT_OFF{0xBF000002_u32}; + + /// @brief defines the value of RAX on success + constexpr auto CPUID_COMMAND_RAX_SUCCESS{0x0_u64}; + /// @brief defines the value of RAX on failure + constexpr auto CPUID_COMMAND_RAX_FAILURE{0x1_u64}; } #endif diff --git a/loader/include/interface/cpp/x64/global_descriptor_table_register_t.hpp b/loader/include/interface/cpp/x64/global_descriptor_table_register_t.hpp index a1fd0059..089c13b4 100644 --- a/loader/include/interface/cpp/x64/global_descriptor_table_register_t.hpp +++ b/loader/include/interface/cpp/x64/global_descriptor_table_register_t.hpp @@ -46,15 +46,6 @@ namespace loader /// @brief stores a pointer to the gdt bsl::uint64 *base; }; - - namespace details - { - /// @brief defined the expected size of the gdtr_t struct - constexpr bsl::safe_uintmax EXPECTED_GDTR_T_SIZE{bsl::to_umax(10)}; - - /// Check to make sure the gdtr_t is the right size. - static_assert(sizeof(global_descriptor_table_register_t) == EXPECTED_GDTR_T_SIZE); - } } #pragma pack(pop) diff --git a/loader/include/interface/cpp/x64/interrupt_descriptor_table_register_t.hpp b/loader/include/interface/cpp/x64/interrupt_descriptor_table_register_t.hpp index ca56d9f7..924b6ad4 100644 --- a/loader/include/interface/cpp/x64/interrupt_descriptor_table_register_t.hpp +++ b/loader/include/interface/cpp/x64/interrupt_descriptor_table_register_t.hpp @@ -46,15 +46,6 @@ namespace loader /// @brief stores a pointer to the idt bsl::uint64 *base; }; - - namespace details - { - /// @brief defined the expected size of the idtr_t struct - constexpr bsl::safe_uintmax EXPECTED_IDTR_T_SIZE{bsl::to_umax(10)}; - - /// Check to make sure the idtr_t is the right size. - static_assert(sizeof(interrupt_descriptor_table_register_t) == EXPECTED_IDTR_T_SIZE); - } } #pragma pack(pop) diff --git a/loader/include/interface/cpp/x64/state_save_t.hpp b/loader/include/interface/cpp/x64/state_save_t.hpp index f3fa8649..d2310bdb 100644 --- a/loader/include/interface/cpp/x64/state_save_t.hpp +++ b/loader/include/interface/cpp/x64/state_save_t.hpp @@ -25,9 +25,9 @@ #ifndef STATE_SAVE_T_HPP #define STATE_SAVE_T_HPP -#include "global_descriptor_table_register_t.hpp" -#include "interrupt_descriptor_table_register_t.hpp" -#include "tss_t.hpp" +#include +#include +#include #include #include @@ -38,36 +38,23 @@ namespace loader { - namespace details - { - /// @brief the size of reserved #0 in the state_save_t - constexpr bsl::safe_uintmax PAD_SIZE{bsl::to_umax(0x6)}; - /// @brief the size of reserved #0 in the state_save_t - constexpr bsl::safe_uintmax RESERVED0_SIZE{bsl::to_umax(0xB)}; - /// @brief the size of reserved #1 in the state_save_t - constexpr bsl::safe_uintmax RESERVED1_SIZE{bsl::to_umax(0x6)}; - /// @brief the size of reserved #2 in the state_save_t - constexpr bsl::safe_uintmax RESERVED2_SIZE{bsl::to_umax(0x8)}; - /// @brief the size of reserved #3 in the state_save_t - constexpr bsl::safe_uintmax RESERVED3_SIZE{bsl::to_umax(0x7)}; - } + /// @brief the size of reserved #0 in the state_save_t + constexpr auto SS_PAD_SIZE{0x6_umax}; + /// @brief the size of reserved #0 in the state_save_t + constexpr auto SS_RESERVED0_SIZE{0xB_umax}; + /// @brief the size of reserved #1 in the state_save_t + constexpr auto SS_RESERVED1_SIZE{0x6_umax}; + /// @brief the size of reserved #2 in the state_save_t + constexpr auto SS_RESERVED2_SIZE{0x8_umax}; + /// @brief the size of reserved #3 in the state_save_t + constexpr auto SS_RESERVED3_SIZE{0x7_umax}; /// @struct loader::state_save_t /// /// - /// @brief Stores state information for both Intel and AMD. Specifically, - /// for a field to be included in this list, it must: - /// - Be saved/restored by the VMCS/VMCB, meaning HVE will touch the - /// field either because we don't have a choice, or because we enable - /// HVE to do so (example being EFER and PAT on Intel) - /// - Because the Microkernel needs it's own version of the field. - /// - /// This list provides the set of all registers that meet the criteria - /// above. It should be noted that this is the common set of fields - /// for both Intel and AMD. To ensure consistency, the Microkernel will - /// save/restore these fields on every VMExit/VMEntry. This ensures - /// extensions can use this list of fields as documentation as to which - /// fields it will have to deal with on its own. + /// @brief Stores the registers and processor state that is used by the + /// microkernel that must be restored in the event of an error or the + /// successful launch of the hypervisor. /// struct state_save_t final { @@ -135,13 +122,13 @@ namespace loader global_descriptor_table_register_t gdtr; /// @brief added padding for alignment (0x0AA) - bsl::details::carray pad1; + bsl::details::carray pad1; /// @brief stores the value of the IDTR (0x0B0) interrupt_descriptor_table_register_t idtr; /// @brief added padding for alignment (0x0BA) - bsl::details::carray pad2; + bsl::details::carray pad2; /// @brief stores the value of the ES segment selector (0x0C0) bsl::uint16 es_selector; @@ -231,14 +218,14 @@ namespace loader bsl::uint64 cr4; /// @brief reserved for future use (0x168) - bsl::details::carray reserved0; + bsl::details::carray reserved0; /// -------------------------------------------------------------------- /// Debug Registers /// -------------------------------------------------------------------- /// @brief reserved for future use (0x1C0) - bsl::details::carray reserved1; + bsl::details::carray reserved1; /// @brief stores the value of DR6 debug register (0x1F0) bsl::uint64 dr6; @@ -246,7 +233,7 @@ namespace loader bsl::uint64 dr7; /// @brief reserved for future use (0x200) - bsl::details::carray reserved2; + bsl::details::carray reserved2; /// -------------------------------------------------------------------- /// MSRs @@ -280,7 +267,7 @@ namespace loader bsl::uint64 ia32_debugctl; /// @brief reserved for future use (0x2A8) - bsl::details::carray reserved3; + bsl::details::carray reserved3; /// -------------------------------------------------------------------- /// HVE Page @@ -313,15 +300,6 @@ namespace loader /// @brief stores whether or not an NMI fired (0x318) bsl::uint64 nmi; }; - - namespace details - { - /// @brief defined the expected size of the state_save_t struct - constexpr bsl::safe_uintmax EXPECTED_STATE_SAVE_T_SIZE{bsl::to_umax(0x320)}; - - /// Check to make sure the state_save_t is the right size. - static_assert(sizeof(state_save_t) == EXPECTED_STATE_SAVE_T_SIZE); - } } #pragma pack(pop) diff --git a/loader/include/interface/cpp/x64/tss_t.hpp b/loader/include/interface/cpp/x64/tss_t.hpp index 3362f1ce..d6d2590a 100644 --- a/loader/include/interface/cpp/x64/tss_t.hpp +++ b/loader/include/interface/cpp/x64/tss_t.hpp @@ -76,15 +76,6 @@ namespace loader /// @brief stores the offset to the IO map base address bsl::uint16 iomap; }; - - namespace details - { - /// @brief defined the expected size of the tss_t struct - constexpr bsl::safe_uintmax EXPECTED_TSS_T_SIZE{bsl::to_umax(HYPERVISOR_PAGE_SIZE)}; - - /// Check to make sure the tss_t is the right size. - static_assert(!(sizeof(tss_t) > EXPECTED_TSS_T_SIZE)); - } } #pragma pack(pop) diff --git a/loader/include/x64/map_4k_page.h b/loader/include/map_4k_page.h similarity index 83% rename from loader/include/x64/map_4k_page.h rename to loader/include/map_4k_page.h index 4b2105d8..16c3bbc3 100644 --- a/loader/include/x64/map_4k_page.h +++ b/loader/include/map_4k_page.h @@ -27,7 +27,7 @@ #ifndef MAP_4K_PAGE_H #define MAP_4K_PAGE_H -#include +#include #include /** @@ -63,28 +63,14 @@ * Layout Randomization, so the addresses shown here could have a fudge * factor added to them to add some entropy. * - * 0x00007FFFFFFFFFFF +------------------+ - * | MK Direct Map | - * 0x0000400000000000 +------------------+ - * | Unusable | - * 0x000006FFFFFFFFFF +------------------+ - * | MK Kernel | - * 0x0000060000000000 +------------------+ - * | Unusable | - * 0x000002FFFFFFFFFF +------------------+ - * | MK Stack | - * 0x0000020000000000 +------------------+ - * | Unusable | - * 0x0000000000000000 +------------------+ - * * * @param virt the virtual address to map phys to * @param phys the physical address to map * @param flags the p_flags field from the segment associated with this page - * @param pml4t the root page table to place the resulting map + * @param rpt the root page table to place the resulting map * @return 0 on success, LOADER_FAILURE on failure. */ int64_t map_4k_page( - uint64_t const virt, uint64_t const phys, uint32_t const flags, struct pml4t_t *const pml4t); + uint64_t const virt, uint64_t const phys, uint32_t const flags, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_4k_page_rw.h b/loader/include/map_4k_page_rw.h similarity index 94% rename from loader/include/x64/map_4k_page_rw.h rename to loader/include/map_4k_page_rw.h index 4691e311..6c885ded 100644 --- a/loader/include/x64/map_4k_page_rw.h +++ b/loader/include/map_4k_page_rw.h @@ -27,7 +27,7 @@ #ifndef MAP_4K_PAGE_RW_H #define MAP_4K_PAGE_RW_H -#include +#include #include /** @@ -44,9 +44,9 @@ * * @param virt the virtual address to map phys to * @param phys the physical address to map - * @param pml4t the root page table to place the resulting map + * @param rpt the root page table to place the resulting map * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t map_4k_page_rw(void const *const virt, uint64_t const phys, struct pml4t_t *const pml4t); +int64_t map_4k_page_rw(void const *const virt, uint64_t const phys, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_4k_page_rx.h b/loader/include/map_4k_page_rx.h similarity index 94% rename from loader/include/x64/map_4k_page_rx.h rename to loader/include/map_4k_page_rx.h index 1eef3f2c..01e2c612 100644 --- a/loader/include/x64/map_4k_page_rx.h +++ b/loader/include/map_4k_page_rx.h @@ -27,7 +27,7 @@ #ifndef MAP_4K_PAGE_RX_H #define MAP_4K_PAGE_RX_H -#include +#include #include /** @@ -44,9 +44,9 @@ * * @param virt the virtual address to map phys to * @param phys the physical address to map - * @param pml4t the root page table to place the resulting map + * @param rpt the root page table to place the resulting map * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t map_4k_page_rx(void const *const virt, uint64_t const phys, struct pml4t_t *const pml4t); +int64_t map_4k_page_rx(void const *const virt, uint64_t const phys, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_ext_elf_files.h b/loader/include/map_ext_elf_files.h similarity index 89% rename from loader/include/x64/map_ext_elf_files.h rename to loader/include/map_ext_elf_files.h index 296ce06b..4c05c022 100644 --- a/loader/include/x64/map_ext_elf_files.h +++ b/loader/include/map_ext_elf_files.h @@ -27,7 +27,7 @@ #ifndef MAP_EXT_ELF_FILES_H #define MAP_EXT_ELF_FILES_H -#include +#include #include #include @@ -39,9 +39,9 @@ * * @param files a pointer to a span_t array that stores the ELF files * being mapped - * @param pml4t the root page table to map the ELF files into + * @param rpt the root page table to map the ELF files into * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t map_ext_elf_files(struct span_t const *const files, struct pml4t_t *const pml4t); +int64_t map_ext_elf_files(struct span_t const *const files, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_mk_args.h b/loader/include/map_mk_args.h similarity index 90% rename from loader/include/x64/map_mk_args.h rename to loader/include/map_mk_args.h index e31d8279..7e4ef435 100644 --- a/loader/include/x64/map_mk_args.h +++ b/loader/include/map_mk_args.h @@ -28,7 +28,7 @@ #define MAP_MK_ARGS_H #include -#include +#include #include /** @@ -39,9 +39,9 @@ * * @param args a pointer to a mk_args_t that stores the args * being mapped - * @param pml4t the root page table to map the args into + * @param rpt the root page table to map the args into * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t map_mk_args(struct mk_args_t const *const args, struct pml4t_t *const pml4t); +int64_t map_mk_args(struct mk_args_t const *const args, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_mk_code_aliases.h b/loader/include/map_mk_code_aliases.h similarity index 93% rename from loader/include/x64/map_mk_code_aliases.h rename to loader/include/map_mk_code_aliases.h index 89d20b2b..9f6b1f1d 100644 --- a/loader/include/x64/map_mk_code_aliases.h +++ b/loader/include/map_mk_code_aliases.h @@ -28,7 +28,7 @@ #define MAP_MK_CODE_ALIASES_H #include -#include +#include #include /** @@ -40,9 +40,9 @@ * * @param a a pointer to a code_aliases_t that stores the aliases * being mapped - * @param pml4t the root page table to map the code aliases into + * @param rpt the root page table to map the code aliases into * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t map_mk_code_aliases(struct code_aliases_t const *const a, struct pml4t_t *const pml4t); +int64_t map_mk_code_aliases(struct code_aliases_t const *const a, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_mk_debug_ring.h b/loader/include/map_mk_debug_ring.h similarity index 89% rename from loader/include/x64/map_mk_debug_ring.h rename to loader/include/map_mk_debug_ring.h index 08b13273..0b10b264 100644 --- a/loader/include/x64/map_mk_debug_ring.h +++ b/loader/include/map_mk_debug_ring.h @@ -28,7 +28,7 @@ #define MAP_MK_DEBUG_RING_H #include -#include +#include /** * @@ -38,9 +38,10 @@ * * @param debug_ring a pointer to a debug_ring_t that stores the debug_ring * being mapped - * @param pml4t the root page table to map the debug_ring into + * @param rpt the root page table to map the debug_ring into * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t map_mk_debug_ring(struct debug_ring_t const *const debug_ring, struct pml4t_t *const pml4t); +int64_t +map_mk_debug_ring(struct debug_ring_t const *const debug_ring, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_mk_elf_file.h b/loader/include/map_mk_elf_file.h similarity index 89% rename from loader/include/x64/map_mk_elf_file.h rename to loader/include/map_mk_elf_file.h index ce0df583..98cd0b1e 100644 --- a/loader/include/x64/map_mk_elf_file.h +++ b/loader/include/map_mk_elf_file.h @@ -27,7 +27,7 @@ #ifndef MAP_MK_ELF_FILE_H #define MAP_MK_ELF_FILE_H -#include +#include #include #include @@ -39,9 +39,9 @@ * * @param file a pointer to a span_t that stores the ELF file * being mapped - * @param pml4t the root page table to map the ELF file into + * @param rpt the root page table to map the ELF file into * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t map_mk_elf_file(struct span_t const *const file, struct pml4t_t *const pml4t); +int64_t map_mk_elf_file(struct span_t const *const file, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_mk_elf_segments.h b/loader/include/map_mk_elf_segments.h similarity index 93% rename from loader/include/x64/map_mk_elf_segments.h rename to loader/include/map_mk_elf_segments.h index 9a035ce1..23768960 100644 --- a/loader/include/x64/map_mk_elf_segments.h +++ b/loader/include/map_mk_elf_segments.h @@ -28,7 +28,7 @@ #define MAP_MK_ELF_SEGMENTS_H #include -#include +#include #include /** @@ -39,10 +39,10 @@ * * @param segments a pointer to a elf_segment_t array that stores the ELF * segments being mapped - * @param pml4t the root page table to map the ELF segments into + * @param rpt the root page table to map the ELF segments into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_mk_elf_segments(struct elf_segment_t const *const segments, struct pml4t_t *const pml4t); +map_mk_elf_segments(struct elf_segment_t const *const segments, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_mk_huge_pool.h b/loader/include/map_mk_huge_pool.h similarity index 89% rename from loader/include/x64/map_mk_huge_pool.h rename to loader/include/map_mk_huge_pool.h index e9b39c41..556f6686 100644 --- a/loader/include/x64/map_mk_huge_pool.h +++ b/loader/include/map_mk_huge_pool.h @@ -28,7 +28,7 @@ #define MAP_MK_HUGE_POOL_H #include -#include +#include #include /** @@ -39,9 +39,10 @@ * * @param huge_pool a pointer to a mutable_span_t that stores the huge pool * being mapped - * @param pml4t the root page table to map the huge pool into + * @param rpt the root page table to map the huge pool into * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t map_mk_huge_pool(struct mutable_span_t const *const huge_pool, struct pml4t_t *const pml4t); +int64_t +map_mk_huge_pool(struct mutable_span_t const *const huge_pool, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_mk_page_pool.h b/loader/include/map_mk_page_pool.h similarity index 92% rename from loader/include/x64/map_mk_page_pool.h rename to loader/include/map_mk_page_pool.h index 6693a728..bc5bff9c 100644 --- a/loader/include/x64/map_mk_page_pool.h +++ b/loader/include/map_mk_page_pool.h @@ -28,7 +28,7 @@ #define MAP_MK_PAGE_POOL_H #include -#include +#include #include /** @@ -51,9 +51,10 @@ * * @param page_pool a pointer to a mutable_span_t that stores the page pool * being mapped - * @param pml4t the root page table to map the page pool into + * @param rpt the root page table to map the page pool into * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t map_mk_page_pool(struct mutable_span_t const *const page_pool, struct pml4t_t *const pml4t); +int64_t +map_mk_page_pool(struct mutable_span_t const *const page_pool, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_mk_stack.h b/loader/include/map_mk_stack.h similarity index 93% rename from loader/include/x64/map_mk_stack.h rename to loader/include/map_mk_stack.h index 869e3096..6675bf69 100644 --- a/loader/include/x64/map_mk_stack.h +++ b/loader/include/map_mk_stack.h @@ -27,7 +27,7 @@ #ifndef MAP_MK_STACK_H #define MAP_MK_STACK_H -#include +#include #include #include @@ -41,10 +41,10 @@ * being mapped * @param virt provide the virtual address that the stack * should be mapped to. - * @param pml4t the root page table to map the stack into + * @param rpt the root page table to map the stack into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_mk_stack(struct span_t const *const stack, uint64_t const virt, struct pml4t_t *const pml4t); +map_mk_stack(struct span_t const *const stack, uint64_t const virt, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_mk_state.h b/loader/include/map_mk_state.h similarity index 89% rename from loader/include/x64/map_mk_state.h rename to loader/include/map_mk_state.h index bbc8c979..96422078 100644 --- a/loader/include/x64/map_mk_state.h +++ b/loader/include/map_mk_state.h @@ -27,7 +27,7 @@ #ifndef MAP_MK_STATE_H #define MAP_MK_STATE_H -#include +#include #include #include @@ -39,9 +39,9 @@ * * @param state a pointer to a state_save_t that stores the state * being mapped - * @param pml4t the root page table to map the state into + * @param rpt the root page table to map the state into * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t map_mk_state(struct state_save_t const *const state, struct pml4t_t *const pml4t); +int64_t map_mk_state(struct state_save_t const *const state, root_page_table_t *const rpt); #endif diff --git a/loader/include/x64/map_root_vp_state.h b/loader/include/map_root_vp_state.h similarity index 93% rename from loader/include/x64/map_root_vp_state.h rename to loader/include/map_root_vp_state.h index 1086bc28..e65fb46f 100644 --- a/loader/include/x64/map_root_vp_state.h +++ b/loader/include/map_root_vp_state.h @@ -27,7 +27,7 @@ #ifndef MAP_ROOT_VP_STATE_H #define MAP_ROOT_VP_STATE_H -#include +#include #include #include @@ -39,9 +39,9 @@ * * @param state a pointer to a state_save_t that stores the state * being mapped - * @param pml4t the root page table to map the state into + * @param rpt the root page table to map the state into * @return 0 on success, LOADER_FAILURE on failure. */ -int64_t map_root_vp_state(struct state_save_t const *const state, struct pml4t_t *const pml4t); +int64_t map_root_vp_state(struct state_save_t const *const state, root_page_table_t *const rpt); #endif diff --git a/loader/include/interface/c/mutable_span_t.h b/loader/include/mutable_span_t.h similarity index 100% rename from loader/include/interface/c/mutable_span_t.h rename to loader/include/mutable_span_t.h diff --git a/loader/include/platform.h b/loader/include/platform.h index c780e979..af199533 100644 --- a/loader/include/platform.h +++ b/loader/include/platform.h @@ -112,27 +112,27 @@ uintptr_t platform_virt_to_phys(void const *const virt); * * @brief Sets "num" bytes in the memory pointed to by "ptr" to "val". * If the provided parameters are valid, returns 0, otherwise - * returns FAILURE. + * returns LOADER_FAILURE. * * * @param ptr a pointer to the memory to set * @param val the value to set each byte to * @param num the number of bytes in "ptr" to set to "val". * @return If the provided parameters are valid, returns 0, otherwise - * returns FAILURE. + * returns LOADER_FAILURE. */ int64_t platform_memset(void *const ptr, uint8_t const val, uint64_t const num); /** * * @brief Copies "num" bytes from "src" to "dst". If "src" or "dst" are - * ((void *)0), returns FAILURE, otherwise returns 0. + * ((void *)0), returns LOADER_FAILURE, otherwise returns 0. * * * @param dst a pointer to the memory to copy to * @param src a pointer to the memory to copy from * @param num the number of bytes to copy - * @return If "src" or "dst" are ((void *)0), returns FAILURE, otherwise + * @return If "src" or "dst" are ((void *)0), returns LOADER_FAILURE, otherwise * returns 0. */ int64_t platform_memcpy(void *const dst, void const *const src, uint64_t const num); @@ -140,14 +140,14 @@ int64_t platform_memcpy(void *const dst, void const *const src, uint64_t const n /** * * @brief Copies "num" bytes from "src" to "dst". If "src" or "dst" are - * ((void *)0), returns FAILURE, otherwise returns 0. Note that this function can + * ((void *)0), returns LOADER_FAILURE, otherwise returns 0. Note that this function can * be used to copy memory from userspace via an IOCTL. * * * @param dst a pointer to the memory to copy to * @param src a pointer to the memory to copy from * @param num the number of bytes to copy - * @return If "src" or "dst" are ((void *)0), returns FAILURE, otherwise + * @return If "src" or "dst" are ((void *)0), returns LOADER_FAILURE, otherwise * returns 0. */ int64_t platform_copy_from_user(void *const dst, void const *const src, uint64_t const num); @@ -155,14 +155,14 @@ int64_t platform_copy_from_user(void *const dst, void const *const src, uint64_t /** * * @brief Copies "num" bytes from "src" to "dst". If "src" or "dst" are - * ((void *)0), returns FAILURE, otherwise returns 0. Note that this function can + * ((void *)0), returns LOADER_FAILURE, otherwise returns 0. Note that this function can * be used to copy memory to userspace via an IOCTL. * * * @param dst a pointer to the memory to copy to * @param src a pointer to the memory to copy from * @param num the number of bytes to copy - * @return If "src" or "dst" are ((void *)0), returns FAILURE, otherwise + * @return If "src" or "dst" are ((void *)0), returns LOADER_FAILURE, otherwise * returns 0. */ int64_t platform_copy_to_user(void *const dst, void const *const src, uint64_t const num); @@ -198,4 +198,21 @@ typedef int64_t (*platform_per_cpu_func)(uint32_t const); */ int64_t platform_on_each_cpu(platform_per_cpu_func const func, uint32_t const reverse); +/** + * + * @brief Dumps the contents of the VMM's ring buffer. + */ +void platform_dump_vmm(void); + +/** + * + * @brief Initializes the archiecture. Some platforms might need per CPU + * initialization logic to get the CPU set up. Most platforms ignore + * calls to this function + * + * + * @return Returns 0 on success, LOADER_FAILURE otherwise + */ +int64_t platform_arch_init(void); + #endif diff --git a/loader/include/x64/promote.h b/loader/include/promote.h similarity index 100% rename from loader/include/x64/promote.h rename to loader/include/promote.h diff --git a/loader/include/x64/send_command_report_off.h b/loader/include/send_command_report_off.h similarity index 100% rename from loader/include/x64/send_command_report_off.h rename to loader/include/send_command_report_off.h diff --git a/loader/include/x64/send_command_report_on.h b/loader/include/send_command_report_on.h similarity index 100% rename from loader/include/x64/send_command_report_on.h rename to loader/include/send_command_report_on.h diff --git a/loader/include/x64/send_command_stop.h b/loader/include/send_command_stop.h similarity index 100% rename from loader/include/x64/send_command_stop.h rename to loader/include/send_command_stop.h diff --git a/loader/include/x64/serial_init.h b/loader/include/serial_init.h similarity index 100% rename from loader/include/x64/serial_init.h rename to loader/include/serial_init.h diff --git a/loader/include/x64/serial_write.h b/loader/include/serial_write.h similarity index 100% rename from loader/include/x64/serial_write.h rename to loader/include/serial_write.h diff --git a/loader/include/serial_write_c.h b/loader/include/serial_write_c.h new file mode 100644 index 00000000..cf881fcf --- /dev/null +++ b/loader/include/serial_write_c.h @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef SERIAL_WRITE_C +#define SERIAL_WRITE_C + +/** + * + * @brief Writes a character "c" to the serial device. + * + * + * @param c the character to write + */ +void serial_write_c(char const c); + +#endif diff --git a/loader/include/serial_write_hex.h b/loader/include/serial_write_hex.h new file mode 100644 index 00000000..ec8664d2 --- /dev/null +++ b/loader/include/serial_write_hex.h @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef SERIAL_WRITE_HEX +#define SERIAL_WRITE_HEX + +#include + +/** + * + * @brief Writes a hexidecimal number "val" to the serial device. + * + * + * @param val the hexidecimal number to write + */ +void serial_write_hex(uint64_t const val); + +#endif diff --git a/loader/include/interface/c/span_t.h b/loader/include/span_t.h similarity index 100% rename from loader/include/interface/c/span_t.h rename to loader/include/span_t.h diff --git a/loader/include/x64/code_aliases_t.h b/loader/include/x64/code_aliases_t.h index f2964dfa..bc9b1609 100644 --- a/loader/include/x64/code_aliases_t.h +++ b/loader/include/x64/code_aliases_t.h @@ -39,9 +39,9 @@ * provide the physical address of a page that is mapped into the * executable portion of a kernel module (e.g., Linux). To overcome this * the executable code is copied into an alias page. When the function - * is executed using the kernel module's CR3, nothing changes, but when - * the code is executed from the microkernel's root page tables, the - * pages stored here provide the page that store the executable code + * is executed using the kernel module's page tables, nothing changes, but + * when the code is executed from the microkernel's page tables, the + * pages stored here provide the page that stores the executable code * instead, ensuring we have a means to get a physical address of a page * that has the code we want. */ @@ -61,6 +61,10 @@ struct code_aliases_t void *esr_nmi; /** @brief stores an alias page to the esr_pf code */ void *esr_pf; + /** @brief stores an alias page to the serial_write_c code */ + void *serial_write_c; + /** @brief stores an alias page to the serial_write_hex code */ + void *serial_write_hex; }; #pragma pack(pop) diff --git a/loader/include/x64/disable_hve.h b/loader/include/x64/disable_hve.h index f13f97d3..344fda05 100644 --- a/loader/include/x64/disable_hve.h +++ b/loader/include/x64/disable_hve.h @@ -31,7 +31,7 @@ /** * - * @brief Disables AMD SVE + * @brief Disables Hardware Virtualization Extensions */ void disable_hve(void); diff --git a/loader/include/x64/enable_hve.h b/loader/include/x64/enable_hve.h index 1273f605..053cb802 100644 --- a/loader/include/x64/enable_hve.h +++ b/loader/include/x64/enable_hve.h @@ -32,7 +32,7 @@ /** * - * @brief Enables AMD SVE + * @brief Enables Hardware Virtualization Extensions * * * @param state the mk state save containing the HVE page diff --git a/loader/include/x64/intel/intrinsic_vmxoff.h b/loader/include/x64/intel/intrinsic_vmxoff.h index 3a2028b6..01f27e71 100644 --- a/loader/include/x64/intel/intrinsic_vmxoff.h +++ b/loader/include/x64/intel/intrinsic_vmxoff.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intel/intrinsic_vmxon.h b/loader/include/x64/intel/intrinsic_vmxon.h index e92ea84d..e2a04817 100644 --- a/loader/include/x64/intel/intrinsic_vmxon.h +++ b/loader/include/x64/intel/intrinsic_vmxon.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_cpuid.h b/loader/include/x64/intrinsic_cpuid.h index 5f30a93b..0f1405ea 100644 --- a/loader/include/x64/intrinsic_cpuid.h +++ b/loader/include/x64/intrinsic_cpuid.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_inb.h b/loader/include/x64/intrinsic_inb.h index 0a5fd0b0..8c9282c9 100644 --- a/loader/include/x64/intrinsic_inb.h +++ b/loader/include/x64/intrinsic_inb.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_lcr0.h b/loader/include/x64/intrinsic_lcr0.h new file mode 100644 index 00000000..53343d77 --- /dev/null +++ b/loader/include/x64/intrinsic_lcr0.h @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef INTRINSIC_LCR0_H +#define INTRINSIC_LCR0_H + +#include + +/** + * + * @brief Loads the CR0 control register with the provided value. + * + * + * @param val the value to load into CR0. + */ +void intrinsic_lcr0(uint64_t const val); + +#endif diff --git a/loader/include/x64/intrinsic_lcr4.h b/loader/include/x64/intrinsic_lcr4.h index c38ce5fb..7e06e85d 100644 --- a/loader/include/x64/intrinsic_lcr4.h +++ b/loader/include/x64/intrinsic_lcr4.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_lgdt.h b/loader/include/x64/intrinsic_lgdt.h new file mode 100644 index 00000000..271b17d6 --- /dev/null +++ b/loader/include/x64/intrinsic_lgdt.h @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef INTRINSIC_LGDT_H +#define INTRINSIC_LGDT_H + +#include + +/** + * + * @brief Executes the LGDT instruction given a pointer to a + * global_descriptor_table_register_t. + * + * + * @param gdtr a pointer to a global_descriptor_table_register_t + */ +void intrinsic_lgdt(struct global_descriptor_table_register_t *const gdtr); + +#endif diff --git a/loader/include/x64/intrinsic_ltr.h b/loader/include/x64/intrinsic_ltr.h new file mode 100644 index 00000000..5183d7ca --- /dev/null +++ b/loader/include/x64/intrinsic_ltr.h @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef INTRINSIC_LTR_H +#define INTRINSIC_LTR_H + +#include + +/** + * + * @brief Loads the TR segment register with the provided value. + * + * + * @param val the value to load into TR. + */ +void intrinsic_ltr(uint16_t const val); + +#endif diff --git a/loader/include/x64/intrinsic_outb.h b/loader/include/x64/intrinsic_outb.h index ccb60bdc..636f98bc 100644 --- a/loader/include/x64/intrinsic_outb.h +++ b/loader/include/x64/intrinsic_outb.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_rdmsr.h b/loader/include/x64/intrinsic_rdmsr.h index 07616b77..abc5f2c4 100644 --- a/loader/include/x64/intrinsic_rdmsr.h +++ b/loader/include/x64/intrinsic_rdmsr.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_scr0.h b/loader/include/x64/intrinsic_scr0.h index 16e6ff90..8152f88a 100644 --- a/loader/include/x64/intrinsic_scr0.h +++ b/loader/include/x64/intrinsic_scr0.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_scr4.h b/loader/include/x64/intrinsic_scr4.h index 5af4de7c..15e78b3d 100644 --- a/loader/include/x64/intrinsic_scr4.h +++ b/loader/include/x64/intrinsic_scr4.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_scs.h b/loader/include/x64/intrinsic_scs.h index ced89592..1b776649 100644 --- a/loader/include/x64/intrinsic_scs.h +++ b/loader/include/x64/intrinsic_scs.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_sds.h b/loader/include/x64/intrinsic_sds.h index 344d8ceb..c889eebf 100644 --- a/loader/include/x64/intrinsic_sds.h +++ b/loader/include/x64/intrinsic_sds.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_ses.h b/loader/include/x64/intrinsic_ses.h index f9542a38..5c0a8047 100644 --- a/loader/include/x64/intrinsic_ses.h +++ b/loader/include/x64/intrinsic_ses.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_sfs.h b/loader/include/x64/intrinsic_sfs.h index ed96afa1..56e22bcd 100644 --- a/loader/include/x64/intrinsic_sfs.h +++ b/loader/include/x64/intrinsic_sfs.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_sgdt.h b/loader/include/x64/intrinsic_sgdt.h index 1165ade2..5219f306 100644 --- a/loader/include/x64/intrinsic_sgdt.h +++ b/loader/include/x64/intrinsic_sgdt.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_sgs.h b/loader/include/x64/intrinsic_sgs.h index 36638960..c6ff6f0e 100644 --- a/loader/include/x64/intrinsic_sgs.h +++ b/loader/include/x64/intrinsic_sgs.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_sidt.h b/loader/include/x64/intrinsic_sidt.h index 1a428007..dd189e6b 100644 --- a/loader/include/x64/intrinsic_sidt.h +++ b/loader/include/x64/intrinsic_sidt.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_sldtr.h b/loader/include/x64/intrinsic_sldtr.h index ac8d7433..11591050 100644 --- a/loader/include/x64/intrinsic_sldtr.h +++ b/loader/include/x64/intrinsic_sldtr.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_sss.h b/loader/include/x64/intrinsic_sss.h index bea9ff9a..0925017f 100644 --- a/loader/include/x64/intrinsic_sss.h +++ b/loader/include/x64/intrinsic_sss.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_str.h b/loader/include/x64/intrinsic_str.h index a52f8ff1..b6c89e6c 100644 --- a/loader/include/x64/intrinsic_str.h +++ b/loader/include/x64/intrinsic_str.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/intrinsic_wrmsr.h b/loader/include/x64/intrinsic_wrmsr.h index a35239a4..6898a0d5 100644 --- a/loader/include/x64/intrinsic_wrmsr.h +++ b/loader/include/x64/intrinsic_wrmsr.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/include/x64/pdpt_t.h b/loader/include/x64/pdpt_t.h index c439ec87..c97fff0f 100644 --- a/loader/include/x64/pdpt_t.h +++ b/loader/include/x64/pdpt_t.h @@ -27,14 +27,13 @@ #ifndef PDPT_T_H #define PDPT_T_H -#pragma pack(push, 1) - #include #include -#include #include -/** @brief defines total number of entries in the PDPT */ +#pragma pack(push, 1) + +/** @brief defines total number of entries in the pdpt */ #define LOADER_NUM_PDPT_ENTRIES ((uint64_t)512) /** @@ -51,9 +50,6 @@ struct pdpt_t struct pdt_t *tables[LOADER_NUM_PDPT_ENTRIES]; }; -/** @brief verify that the pdpt_t structure is the right size */ -STATIC_ASSERT(sizeof(struct pdpt_t) == 0x2000, pdpt_t_has_incorrect_size); - #pragma pack(pop) #endif diff --git a/loader/include/interface/c/x64/pdpte_t.h b/loader/include/x64/pdpte_t.h similarity index 78% rename from loader/include/interface/c/x64/pdpte_t.h rename to loader/include/x64/pdpte_t.h index 9dad5889..a257a25f 100644 --- a/loader/include/interface/c/x64/pdpte_t.h +++ b/loader/include/x64/pdpte_t.h @@ -27,15 +27,14 @@ #ifndef PDPTE_T_H #define PDPTE_T_H +#include + #pragma pack(push, 1) #ifdef _MSC_VER #pragma warning(disable : 4214) #endif -#include -#include - /** * @struct pdpte_t * @@ -57,25 +56,22 @@ struct pdpte_t uint64_t pcd : ((uint64_t)1); /** @brief defines the "accessed" field in the page */ uint64_t a : ((uint64_t)1); - /** @brief defines an ignored field in the page */ - uint64_t ignored1 : ((uint64_t)1); - /** @brief defines a field in the page that must be 0 */ - uint64_t mbz1 : ((uint64_t)1); - /** @brief defines an ignored field in the page */ - uint64_t ignored2 : ((uint64_t)1); + /** @brief defines the "dirty" field in the page (ignored) */ + uint64_t d : ((uint64_t)1); + /** @brief defines the "page size" field in the page (must be 0) */ + uint64_t ps : ((uint64_t)1); + /** @brief defines the "global" field in the page (must be 0) */ + uint64_t g : ((uint64_t)1); /** @brief defines the "available to software" field in the page */ - uint64_t avl : ((uint64_t)3); - /** @brief defines the physical address field in the page */ + uint64_t available1 : ((uint64_t)3); + /** @brief defines the "physical address" field in the page */ uint64_t phys : ((uint64_t)40); - /** @brief defines fields in the page available to the OS for use */ - uint64_t available : ((uint64_t)11); + /** @brief defines the "available to software" field in the page */ + uint64_t available2 : ((uint64_t)11); /** @brief defines the "no-execute" field in the page */ uint64_t nx : ((uint64_t)1); }; -/** @brief Check to make sure the pdpte_t is the right size. */ -STATIC_ASSERT(sizeof(struct pdpte_t) == 8, invalid_size); - #ifdef _MSC_VER #pragma warning(default : 4214) #endif diff --git a/loader/include/x64/pdt_t.h b/loader/include/x64/pdt_t.h index e7835dde..c9d80806 100644 --- a/loader/include/x64/pdt_t.h +++ b/loader/include/x64/pdt_t.h @@ -27,13 +27,12 @@ #ifndef PDT_T_H #define PDT_T_H -#pragma pack(push, 1) - #include #include -#include #include +#pragma pack(push, 1) + /** @brief defines total number of entries in the PDT */ #define LOADER_NUM_PDT_ENTRIES ((uint64_t)512) @@ -51,9 +50,6 @@ struct pdt_t struct pt_t *tables[LOADER_NUM_PDT_ENTRIES]; }; -/** @brief verify that the pdt_t structure is the right size */ -STATIC_ASSERT(sizeof(struct pdt_t) == 0x2000, pdt_t_has_incorrect_size); - #pragma pack(pop) #endif diff --git a/loader/include/interface/c/x64/pdte_t.h b/loader/include/x64/pdte_t.h similarity index 78% rename from loader/include/interface/c/x64/pdte_t.h rename to loader/include/x64/pdte_t.h index 1a1476fe..fc203337 100644 --- a/loader/include/interface/c/x64/pdte_t.h +++ b/loader/include/x64/pdte_t.h @@ -27,15 +27,14 @@ #ifndef PDTE_T_H #define PDTE_T_H +#include + #pragma pack(push, 1) #ifdef _MSC_VER #pragma warning(disable : 4214) #endif -#include -#include - /** * @struct pdte_t * @@ -56,25 +55,22 @@ struct pdte_t uint64_t pcd : ((uint64_t)1); /** @brief defines the "accessed" field in the page */ uint64_t a : ((uint64_t)1); - /** @brief defines an ignored field in the page */ - uint64_t ignored1 : ((uint64_t)1); - /** @brief defines a field in the page that must be 0 */ - uint64_t mbz1 : ((uint64_t)1); - /** @brief defines an ignored field in the page */ - uint64_t ignored2 : ((uint64_t)1); + /** @brief defines the "dirty" field in the page (ignored) */ + uint64_t d : ((uint64_t)1); + /** @brief defines the "page size" field in the page (must be 0) */ + uint64_t ps : ((uint64_t)1); + /** @brief defines the "global" field in the page (must be 0) */ + uint64_t g : ((uint64_t)1); /** @brief defines the "available to software" field in the page */ - uint64_t avl : ((uint64_t)3); - /** @brief defines the physical address field in the page */ + uint64_t available1 : ((uint64_t)3); + /** @brief defines the "physical address" field in the page */ uint64_t phys : ((uint64_t)40); - /** @brief defines fields in the page available to the OS for use */ - uint64_t available : ((uint64_t)11); + /** @brief defines the "available to software" field in the page */ + uint64_t available2 : ((uint64_t)11); /** @brief defines the "no-execute" field in the page */ uint64_t nx : ((uint64_t)1); }; -/** @brief Check to make sure the pdte_t is the right size. */ -STATIC_ASSERT(sizeof(struct pdte_t) == 8, invalid_size); - #ifdef _MSC_VER #pragma warning(default : 4214) #endif diff --git a/loader/include/x64/pml4t_t.h b/loader/include/x64/pml4t_t.h index 533e8af9..43363c77 100644 --- a/loader/include/x64/pml4t_t.h +++ b/loader/include/x64/pml4t_t.h @@ -27,13 +27,12 @@ #ifndef PML4T_T_H #define PML4T_T_H -#pragma pack(push, 1) - #include #include -#include #include +#pragma pack(push, 1) + /** @brief defines total number of entries in the PML4T */ #define LOADER_NUM_PML4T_ENTRIES ((uint64_t)512) @@ -51,9 +50,6 @@ struct pml4t_t struct pdpt_t *tables[LOADER_NUM_PML4T_ENTRIES]; }; -/** @brief verify that the pml4t_t structure is the right size */ -STATIC_ASSERT(sizeof(struct pml4t_t) == 0x2000, pml4t_t_has_incorrect_size); - #pragma pack(pop) #endif diff --git a/loader/include/interface/c/x64/pml4te_t.h b/loader/include/x64/pml4te_t.h similarity index 80% rename from loader/include/interface/c/x64/pml4te_t.h rename to loader/include/x64/pml4te_t.h index c1fc6c2d..08f1c79f 100644 --- a/loader/include/interface/c/x64/pml4te_t.h +++ b/loader/include/x64/pml4te_t.h @@ -27,15 +27,14 @@ #ifndef PML4TE_T_H #define PML4TE_T_H +#include + #pragma pack(push, 1) #ifdef _MSC_VER #pragma warning(disable : 4214) #endif -#include -#include - /** * @struct pml4te_t * @@ -56,25 +55,24 @@ struct pml4te_t uint64_t pcd : ((uint64_t)1); /** @brief defines the "accessed" field in the page */ uint64_t a : ((uint64_t)1); - /** @brief defines an ignored field in the page */ - uint64_t ignored1 : ((uint64_t)1); - /** @brief defines a field in the page that must be 0 */ + /** @brief defines the "dirty" field in the page (ignored) */ + uint64_t ignored : ((uint64_t)1); + /** @brief defines the "page size" field in the page (must be 0) */ uint64_t mbz1 : ((uint64_t)1); - /** @brief defines a field in the page that must be 0 */ + /** @brief defines the "global" field in the page (must be 0) */ uint64_t mbz2 : ((uint64_t)1); + /** @brief defines our "aliased" field in the page */ + uint64_t alias : ((uint64_t)1); /** @brief defines the "available to software" field in the page */ - uint64_t avl : ((uint64_t)3); - /** @brief defines the physical address field in the page */ + uint64_t available1 : ((uint64_t)2); + /** @brief defines the "physical address" field in the page */ uint64_t phys : ((uint64_t)40); - /** @brief defines if this page is an alias (i.e., non-owning) */ - uint64_t alias : ((uint64_t)11); + /** @brief defines the "available to software" field in the page */ + uint64_t available2 : ((uint64_t)11); /** @brief defines the "no-execute" field in the page */ uint64_t nx : ((uint64_t)1); }; -/** @brief Check to make sure the pml4te_t is the right size. */ -STATIC_ASSERT(sizeof(struct pml4te_t) == 8, invalid_size); - #ifdef _MSC_VER #pragma warning(default : 4214) #endif diff --git a/loader/include/x64/pt_t.h b/loader/include/x64/pt_t.h index 303432b7..7f392754 100644 --- a/loader/include/x64/pt_t.h +++ b/loader/include/x64/pt_t.h @@ -27,12 +27,11 @@ #ifndef PT_T_H #define PT_T_H -#pragma pack(push, 1) - #include -#include #include +#pragma pack(push, 1) + /** @brief defines total number of entries in the PT */ #define LOADER_NUM_PT_ENTRIES ((uint64_t)512) @@ -48,9 +47,6 @@ struct pt_t struct pte_t entires[LOADER_NUM_PT_ENTRIES]; }; -/** @brief verify that the pt_t structure is the right size */ -STATIC_ASSERT(sizeof(struct pt_t) == 0x1000, pt_t_has_incorrect_size); - #pragma pack(pop) #endif diff --git a/loader/include/interface/c/x64/pte_t.h b/loader/include/x64/pte_t.h similarity index 81% rename from loader/include/interface/c/x64/pte_t.h rename to loader/include/x64/pte_t.h index 7d98a2fb..3c375b8e 100644 --- a/loader/include/interface/c/x64/pte_t.h +++ b/loader/include/x64/pte_t.h @@ -27,15 +27,14 @@ #ifndef PTE_T_H #define PTE_T_H +#include + #pragma pack(push, 1) #ifdef _MSC_VER #pragma warning(disable : 4214) #endif -#include -#include - /** * @struct pte_t * @@ -56,27 +55,24 @@ struct pte_t uint64_t pcd : ((uint64_t)1); /** @brief defines the "accessed" field in the page */ uint64_t a : ((uint64_t)1); - /** @brief defines the "dirty" field in the page */ + /** @brief defines the "dirty" field in the page (ignored) */ uint64_t d : ((uint64_t)1); - /** @brief defines the "page-attribute table" field in the page */ - uint64_t pat : ((uint64_t)1); - /** @brief defines the "global page" field in the page */ + /** @brief defines the "page size" field in the page (must be 0) */ + uint64_t ps : ((uint64_t)1); + /** @brief defines the "global" field in the page (must be 0) */ uint64_t g : ((uint64_t)1); - /** @brief defines the "available to software" field in the page */ - uint64_t avl : ((uint64_t)3); - /** @brief defines the physical address field in the page */ + /** @brief defines our "auto_release" field in the page */ + uint64_t auto_release : ((uint64_t)3); + /** @brief defines the "physical address" field in the page */ uint64_t phys : ((uint64_t)40); - /** @brief defines whether or not the page can be auto released */ - uint64_t auto_release : ((uint64_t)7); + /** @brief defines the "available to software" field in the page */ + uint64_t available2 : ((uint64_t)7); /** @brief defines the "memory protection key" field in the page */ uint64_t mpk : ((uint64_t)4); /** @brief defines the "no-execute" field in the page */ uint64_t nx : ((uint64_t)1); }; -/** @brief Check to make sure the pte_t is the right size. */ -STATIC_ASSERT(sizeof(struct pte_t) == 8, invalid_size); - #ifdef _MSC_VER #pragma warning(default : 4214) #endif diff --git a/loader/include/x64/root_page_table_t.h b/loader/include/x64/root_page_table_t.h new file mode 100644 index 00000000..3a0ca768 --- /dev/null +++ b/loader/include/x64/root_page_table_t.h @@ -0,0 +1,33 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ROOT_PAGE_TABLE_T_H +#define ROOT_PAGE_TABLE_T_H + +/** @brief defines the type for the root page tables for this arch */ +typedef struct pml4t_t root_page_table_t; + +#endif diff --git a/loader/linux/Makefile b/loader/linux/Makefile index 5dcf2146..9bc00479 100644 --- a/loader/linux/Makefile +++ b/loader/linux/Makefile @@ -26,242 +26,165 @@ VENDOR_ID := $(shell lscpu | grep 'Vendor ID') ifneq ($(KERNELRELEASE),) obj-m := $(TARGET_MODULE).o - $(TARGET_MODULE)-objs += src/entry.o - $(TARGET_MODULE)-objs += src/platform.o - - $(TARGET_MODULE)-objs += ../src/alloc_and_copy_ext_elf_files_from_user.o - $(TARGET_MODULE)-objs += ../src/alloc_and_copy_mk_elf_file_from_user.o - $(TARGET_MODULE)-objs += ../src/alloc_and_copy_mk_elf_segments.o - $(TARGET_MODULE)-objs += ../src/alloc_mk_args.o - $(TARGET_MODULE)-objs += ../src/alloc_mk_debug_ring.o - $(TARGET_MODULE)-objs += ../src/alloc_mk_huge_pool.o - $(TARGET_MODULE)-objs += ../src/alloc_mk_page_pool.o - $(TARGET_MODULE)-objs += ../src/alloc_mk_stack.o - $(TARGET_MODULE)-objs += ../src/dump_ext_elf_files.o - $(TARGET_MODULE)-objs += ../src/dump_mk_args.o - $(TARGET_MODULE)-objs += ../src/dump_mk_debug_ring.o - $(TARGET_MODULE)-objs += ../src/dump_mk_elf_file.o - $(TARGET_MODULE)-objs += ../src/dump_mk_elf_segments.o - $(TARGET_MODULE)-objs += ../src/dump_mk_huge_pool.o - $(TARGET_MODULE)-objs += ../src/dump_mk_page_pool.o - $(TARGET_MODULE)-objs += ../src/dump_mk_stack.o - $(TARGET_MODULE)-objs += ../src/dump_vmm.o - $(TARGET_MODULE)-objs += ../src/free_ext_elf_files.o - $(TARGET_MODULE)-objs += ../src/free_mk_args.o - $(TARGET_MODULE)-objs += ../src/free_mk_debug_ring.o - $(TARGET_MODULE)-objs += ../src/free_mk_elf_file.o - $(TARGET_MODULE)-objs += ../src/free_mk_elf_segments.o - $(TARGET_MODULE)-objs += ../src/free_mk_huge_pool.o - $(TARGET_MODULE)-objs += ../src/free_mk_page_pool.o - $(TARGET_MODULE)-objs += ../src/free_mk_stack.o - $(TARGET_MODULE)-objs += ../src/g_ext_elf_files.o - $(TARGET_MODULE)-objs += ../src/g_mk_args.o - $(TARGET_MODULE)-objs += ../src/g_mk_debug_ring.o - $(TARGET_MODULE)-objs += ../src/g_mk_elf_file.o - $(TARGET_MODULE)-objs += ../src/g_mk_elf_segments.o - $(TARGET_MODULE)-objs += ../src/g_mk_huge_pool.o - $(TARGET_MODULE)-objs += ../src/g_mk_page_pool.o - $(TARGET_MODULE)-objs += ../src/g_mk_stack.o - $(TARGET_MODULE)-objs += ../src/loader_fini.o - $(TARGET_MODULE)-objs += ../src/loader_init.o - $(TARGET_MODULE)-objs += ../src/start_vmm_per_cpu.o - $(TARGET_MODULE)-objs += ../src/start_vmm.o - $(TARGET_MODULE)-objs += ../src/stop_and_free_the_vmm.o - $(TARGET_MODULE)-objs += ../src/stop_vmm_per_cpu.o - $(TARGET_MODULE)-objs += ../src/stop_vmm.o - $(TARGET_MODULE)-objs += ../src/vmm_status.o + $(TARGET_MODULE)-objs += src/entry.o + $(TARGET_MODULE)-objs += src/platform.o + $(TARGET_MODULE)-objs += ../src/alloc_and_copy_ext_elf_files_from_user.o + $(TARGET_MODULE)-objs += ../src/alloc_and_copy_mk_elf_file_from_user.o + $(TARGET_MODULE)-objs += ../src/alloc_and_copy_mk_elf_segments.o + $(TARGET_MODULE)-objs += ../src/alloc_mk_args.o + $(TARGET_MODULE)-objs += ../src/alloc_mk_debug_ring.o + $(TARGET_MODULE)-objs += ../src/alloc_mk_huge_pool.o + $(TARGET_MODULE)-objs += ../src/alloc_mk_page_pool.o + $(TARGET_MODULE)-objs += ../src/alloc_mk_stack.o + $(TARGET_MODULE)-objs += ../src/dump_ext_elf_files.o + $(TARGET_MODULE)-objs += ../src/dump_mk_args.o + $(TARGET_MODULE)-objs += ../src/dump_mk_debug_ring.o + $(TARGET_MODULE)-objs += ../src/dump_mk_elf_file.o + $(TARGET_MODULE)-objs += ../src/dump_mk_elf_segments.o + $(TARGET_MODULE)-objs += ../src/dump_mk_huge_pool.o + $(TARGET_MODULE)-objs += ../src/dump_mk_page_pool.o + $(TARGET_MODULE)-objs += ../src/dump_mk_root_page_table.o + $(TARGET_MODULE)-objs += ../src/dump_mk_stack.o + $(TARGET_MODULE)-objs += ../src/dump_vmm.o + $(TARGET_MODULE)-objs += ../src/free_ext_elf_files.o + $(TARGET_MODULE)-objs += ../src/free_mk_args.o + $(TARGET_MODULE)-objs += ../src/free_mk_debug_ring.o + $(TARGET_MODULE)-objs += ../src/free_mk_elf_file.o + $(TARGET_MODULE)-objs += ../src/free_mk_elf_segments.o + $(TARGET_MODULE)-objs += ../src/free_mk_huge_pool.o + $(TARGET_MODULE)-objs += ../src/free_mk_page_pool.o + $(TARGET_MODULE)-objs += ../src/free_mk_stack.o + $(TARGET_MODULE)-objs += ../src/g_cpu_status.o + $(TARGET_MODULE)-objs += ../src/g_ext_elf_files.o + $(TARGET_MODULE)-objs += ../src/g_mk_args.o + $(TARGET_MODULE)-objs += ../src/g_mk_code_aliases.o + $(TARGET_MODULE)-objs += ../src/g_mk_debug_ring.o + $(TARGET_MODULE)-objs += ../src/g_mk_elf_file.o + $(TARGET_MODULE)-objs += ../src/g_mk_elf_segments.o + $(TARGET_MODULE)-objs += ../src/g_mk_huge_pool.o + $(TARGET_MODULE)-objs += ../src/g_mk_page_pool.o + $(TARGET_MODULE)-objs += ../src/g_mk_root_page_table.o + $(TARGET_MODULE)-objs += ../src/g_mk_stack.o + $(TARGET_MODULE)-objs += ../src/g_mk_state.o + $(TARGET_MODULE)-objs += ../src/g_root_vp_state.o + $(TARGET_MODULE)-objs += ../src/g_vmm_status.o + $(TARGET_MODULE)-objs += ../src/get_mk_huge_pool_addr.o + $(TARGET_MODULE)-objs += ../src/get_mk_page_pool_addr.o + $(TARGET_MODULE)-objs += ../src/loader_fini.o + $(TARGET_MODULE)-objs += ../src/loader_init.o + $(TARGET_MODULE)-objs += ../src/map_4k_page_rw.o + $(TARGET_MODULE)-objs += ../src/map_4k_page_rx.o + $(TARGET_MODULE)-objs += ../src/map_ext_elf_files.o + $(TARGET_MODULE)-objs += ../src/map_mk_args.o + $(TARGET_MODULE)-objs += ../src/map_mk_debug_ring.o + $(TARGET_MODULE)-objs += ../src/map_mk_elf_file.o + $(TARGET_MODULE)-objs += ../src/map_mk_elf_segments.o + $(TARGET_MODULE)-objs += ../src/map_mk_huge_pool.o + $(TARGET_MODULE)-objs += ../src/map_mk_page_pool.o + $(TARGET_MODULE)-objs += ../src/map_mk_stack.o + $(TARGET_MODULE)-objs += ../src/serial_write.o + $(TARGET_MODULE)-objs += ../src/start_vmm.o + $(TARGET_MODULE)-objs += ../src/start_vmm_per_cpu.o + $(TARGET_MODULE)-objs += ../src/stop_and_free_the_vmm.o + $(TARGET_MODULE)-objs += ../src/stop_vmm.o + $(TARGET_MODULE)-objs += ../src/stop_vmm_per_cpu.o + $(TARGET_MODULE)-objs += src/x64/demote.o + $(TARGET_MODULE)-objs += src/x64/esr_default.o + $(TARGET_MODULE)-objs += src/x64/esr_df.o + $(TARGET_MODULE)-objs += src/x64/esr_gpf.o + $(TARGET_MODULE)-objs += src/x64/esr_nmi.o + $(TARGET_MODULE)-objs += src/x64/esr_pf.o + $(TARGET_MODULE)-objs += src/x64/flush_cache.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_cpuid.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_inb.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_lcr4.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_outb.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_rdmsr.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_scr0.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_scr4.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_scs.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_sds.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_ses.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_sfs.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_sgdt.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_sgs.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_sidt.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_sldtr.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_sss.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_str.o + $(TARGET_MODULE)-objs += src/x64/intrinsic_wrmsr.o + $(TARGET_MODULE)-objs += src/x64/promote.o + $(TARGET_MODULE)-objs += src/x64/serial_write_c.o + $(TARGET_MODULE)-objs += src/x64/serial_write_hex.o + $(TARGET_MODULE)-objs += ../src/x64/alloc_and_copy_mk_code_aliases.o + $(TARGET_MODULE)-objs += ../src/x64/alloc_and_copy_mk_state.o + $(TARGET_MODULE)-objs += ../src/x64/alloc_and_copy_root_vp_state.o + $(TARGET_MODULE)-objs += ../src/x64/alloc_mk_root_page_table.o + $(TARGET_MODULE)-objs += ../src/x64/alloc_pdpt.o + $(TARGET_MODULE)-objs += ../src/x64/alloc_pdt.o + $(TARGET_MODULE)-objs += ../src/x64/alloc_pt.o + $(TARGET_MODULE)-objs += ../src/x64/dump_mk_code_aliases.o + $(TARGET_MODULE)-objs += ../src/x64/dump_mk_state.o + $(TARGET_MODULE)-objs += ../src/x64/dump_root_vp_state.o + $(TARGET_MODULE)-objs += ../src/x64/free_mk_code_aliases.o + $(TARGET_MODULE)-objs += ../src/x64/free_mk_root_page_table.o + $(TARGET_MODULE)-objs += ../src/x64/free_mk_state.o + $(TARGET_MODULE)-objs += ../src/x64/free_pdpt.o + $(TARGET_MODULE)-objs += ../src/x64/free_pdt.o + $(TARGET_MODULE)-objs += ../src/x64/free_pml4t.o + $(TARGET_MODULE)-objs += ../src/x64/free_root_vp_state.o + $(TARGET_MODULE)-objs += ../src/x64/get_gdt_descriptor_attrib.o + $(TARGET_MODULE)-objs += ../src/x64/get_gdt_descriptor_base.o + $(TARGET_MODULE)-objs += ../src/x64/get_gdt_descriptor_limit.o + $(TARGET_MODULE)-objs += ../src/x64/map_4k_page.o + $(TARGET_MODULE)-objs += ../src/x64/map_mk_code_aliases.o + $(TARGET_MODULE)-objs += ../src/x64/map_mk_state.o + $(TARGET_MODULE)-objs += ../src/x64/map_root_vp_state.o + $(TARGET_MODULE)-objs += ../src/x64/send_command_report_off.o + $(TARGET_MODULE)-objs += ../src/x64/send_command_report_on.o + $(TARGET_MODULE)-objs += ../src/x64/send_command_stop.o + $(TARGET_MODULE)-objs += ../src/x64/serial_init.o + $(TARGET_MODULE)-objs += ../src/x64/set_gdt_descriptor.o + $(TARGET_MODULE)-objs += ../src/x64/set_idt_descriptor.o EXTRA_CFLAGS += -I$(src)/include + EXTRA_CFLAGS += -I$(src)/include/x64 EXTRA_CFLAGS += -I$(src)/include/std EXTRA_CFLAGS += -I$(src)/include/platform_interface/c EXTRA_CFLAGS += -I$(src)/../include + EXTRA_CFLAGS += -I$(src)/../include/x64/ EXTRA_CFLAGS += -I$(src)/../include/interface/c - EXTRA_CFLAGS += -I$(src)/../include/interface/c/bfelf + EXTRA_CFLAGS += -I$(src)/../include/interface/c/x64 EXTRA_CFLAGS += -I$(CMAKE_BINARY_DIR)/include - ifneq (,$(findstring AuthenticAMD,$(VENDOR_ID))) - $(TARGET_MODULE)-objs += src/x64/demote.o - $(TARGET_MODULE)-objs += src/x64/esr_default.o - $(TARGET_MODULE)-objs += src/x64/esr_df.o - $(TARGET_MODULE)-objs += src/x64/esr_gpf.o - $(TARGET_MODULE)-objs += src/x64/esr_nmi.o - $(TARGET_MODULE)-objs += src/x64/esr_pf.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_cpuid.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_inb.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_lcr4.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_outb.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_rdmsr.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_scr0.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_scr4.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_scs.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sds.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_ses.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sfs.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sgdt.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sgs.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sidt.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sldtr.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sss.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_str.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_wrmsr.o - $(TARGET_MODULE)-objs += src/x64/promote.o + EXTRA_AFLAGS += -I$(CMAKE_BINARY_DIR)/include + ifneq (,$(findstring AuthenticAMD,$(VENDOR_ID))) $(TARGET_MODULE)-objs += src/x64/amd/disable_interrupts.o $(TARGET_MODULE)-objs += src/x64/amd/enable_interrupts.o - - $(TARGET_MODULE)-objs += ../src/x64/alloc_and_copy_mk_code_aliases.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_and_copy_mk_state.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_and_copy_root_vp_state.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_mk_root_page_table.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_pdpt.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_pdt.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_pt.o - $(TARGET_MODULE)-objs += ../src/x64/dump_mk_code_aliases.o - $(TARGET_MODULE)-objs += ../src/x64/dump_mk_root_page_table.o - $(TARGET_MODULE)-objs += ../src/x64/dump_mk_state.o - $(TARGET_MODULE)-objs += ../src/x64/dump_root_vp_state.o - $(TARGET_MODULE)-objs += ../src/x64/free_mk_code_aliases.o - $(TARGET_MODULE)-objs += ../src/x64/free_mk_root_page_table.o - $(TARGET_MODULE)-objs += ../src/x64/free_mk_state.o - $(TARGET_MODULE)-objs += ../src/x64/free_pdpt.o - $(TARGET_MODULE)-objs += ../src/x64/free_pdt.o - $(TARGET_MODULE)-objs += ../src/x64/free_pml4t.o - $(TARGET_MODULE)-objs += ../src/x64/free_root_vp_state.o - $(TARGET_MODULE)-objs += ../src/x64/g_mk_code_aliases.o - $(TARGET_MODULE)-objs += ../src/x64/g_mk_root_page_table.o - $(TARGET_MODULE)-objs += ../src/x64/g_mk_state.o - $(TARGET_MODULE)-objs += ../src/x64/g_root_vp_state.o - $(TARGET_MODULE)-objs += ../src/x64/get_gdt_descriptor_attrib.o - $(TARGET_MODULE)-objs += ../src/x64/get_gdt_descriptor_base.o - $(TARGET_MODULE)-objs += ../src/x64/get_gdt_descriptor_limit.o - $(TARGET_MODULE)-objs += ../src/x64/get_mk_huge_pool_addr.o - $(TARGET_MODULE)-objs += ../src/x64/get_mk_page_pool_addr.o - $(TARGET_MODULE)-objs += ../src/x64/map_4k_page_rw.o - $(TARGET_MODULE)-objs += ../src/x64/map_4k_page_rx.o - $(TARGET_MODULE)-objs += ../src/x64/map_4k_page.o - $(TARGET_MODULE)-objs += ../src/x64/map_ext_elf_files.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_args.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_debug_ring.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_code_aliases.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_elf_file.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_elf_segments.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_huge_pool.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_page_pool.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_stack.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_state.o - $(TARGET_MODULE)-objs += ../src/x64/map_root_vp_state.o - $(TARGET_MODULE)-objs += ../src/x64/send_command_report_off.o - $(TARGET_MODULE)-objs += ../src/x64/send_command_report_on.o - $(TARGET_MODULE)-objs += ../src/x64/send_command_stop.o - $(TARGET_MODULE)-objs += ../src/x64/serial_init.o - $(TARGET_MODULE)-objs += ../src/x64/serial_write.o - $(TARGET_MODULE)-objs += ../src/x64/set_gdt_descriptor.o - $(TARGET_MODULE)-objs += ../src/x64/set_idt_descriptor.o - - $(TARGET_MODULE)-objs += ../src/x64/amd/enable_hve.o + $(TARGET_MODULE)-objs += ../src/x64/amd/check_cpu_configuration.o $(TARGET_MODULE)-objs += ../src/x64/amd/disable_hve.o - $(TARGET_MODULE)-objs += ../src/x64/amd/check_for_hve_support.o + $(TARGET_MODULE)-objs += ../src/x64/amd/enable_hve.o - EXTRA_CFLAGS += -I$(src)/include/x64 EXTRA_CFLAGS += -I$(src)/include/x64/amd - EXTRA_CFLAGS += -I$(src)/../include/x64/ EXTRA_CFLAGS += -I$(src)/../include/x64/amd - EXTRA_CFLAGS += -I$(src)/../include/interface/c/x64 EXTRA_CFLAGS += -I$(src)/../include/interface/c/x64/amd endif ifneq (,$(findstring GenuineIntel,$(VENDOR_ID))) - $(TARGET_MODULE)-objs += src/x64/demote.o - $(TARGET_MODULE)-objs += src/x64/esr_default.o - $(TARGET_MODULE)-objs += src/x64/esr_df.o - $(TARGET_MODULE)-objs += src/x64/esr_gpf.o - $(TARGET_MODULE)-objs += src/x64/esr_nmi.o - $(TARGET_MODULE)-objs += src/x64/esr_pf.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_cpuid.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_inb.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_lcr4.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_outb.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_rdmsr.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_scr0.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_scr4.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_scs.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sds.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_ses.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sfs.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sgdt.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sgs.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sidt.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sldtr.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_sss.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_str.o - $(TARGET_MODULE)-objs += src/x64/intrinsic_wrmsr.o - $(TARGET_MODULE)-objs += src/x64/promote.o - $(TARGET_MODULE)-objs += src/x64/intel/disable_interrupts.o $(TARGET_MODULE)-objs += src/x64/intel/enable_interrupts.o $(TARGET_MODULE)-objs += src/x64/intel/intrinsic_vmxoff.o $(TARGET_MODULE)-objs += src/x64/intel/intrinsic_vmxon.o - - $(TARGET_MODULE)-objs += ../src/x64/alloc_and_copy_mk_code_aliases.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_and_copy_mk_state.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_and_copy_root_vp_state.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_mk_root_page_table.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_pdpt.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_pdt.o - $(TARGET_MODULE)-objs += ../src/x64/alloc_pt.o - $(TARGET_MODULE)-objs += ../src/x64/dump_mk_code_aliases.o - $(TARGET_MODULE)-objs += ../src/x64/dump_mk_root_page_table.o - $(TARGET_MODULE)-objs += ../src/x64/dump_mk_state.o - $(TARGET_MODULE)-objs += ../src/x64/dump_root_vp_state.o - $(TARGET_MODULE)-objs += ../src/x64/free_mk_code_aliases.o - $(TARGET_MODULE)-objs += ../src/x64/free_mk_root_page_table.o - $(TARGET_MODULE)-objs += ../src/x64/free_mk_state.o - $(TARGET_MODULE)-objs += ../src/x64/free_pdpt.o - $(TARGET_MODULE)-objs += ../src/x64/free_pdt.o - $(TARGET_MODULE)-objs += ../src/x64/free_pml4t.o - $(TARGET_MODULE)-objs += ../src/x64/free_root_vp_state.o - $(TARGET_MODULE)-objs += ../src/x64/g_mk_code_aliases.o - $(TARGET_MODULE)-objs += ../src/x64/g_mk_root_page_table.o - $(TARGET_MODULE)-objs += ../src/x64/g_mk_state.o - $(TARGET_MODULE)-objs += ../src/x64/g_root_vp_state.o - $(TARGET_MODULE)-objs += ../src/x64/get_gdt_descriptor_attrib.o - $(TARGET_MODULE)-objs += ../src/x64/get_gdt_descriptor_base.o - $(TARGET_MODULE)-objs += ../src/x64/get_gdt_descriptor_limit.o - $(TARGET_MODULE)-objs += ../src/x64/get_mk_huge_pool_addr.o - $(TARGET_MODULE)-objs += ../src/x64/get_mk_page_pool_addr.o - $(TARGET_MODULE)-objs += ../src/x64/map_4k_page_rw.o - $(TARGET_MODULE)-objs += ../src/x64/map_4k_page_rx.o - $(TARGET_MODULE)-objs += ../src/x64/map_4k_page.o - $(TARGET_MODULE)-objs += ../src/x64/map_ext_elf_files.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_args.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_debug_ring.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_code_aliases.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_elf_file.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_elf_segments.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_huge_pool.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_page_pool.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_stack.o - $(TARGET_MODULE)-objs += ../src/x64/map_mk_state.o - $(TARGET_MODULE)-objs += ../src/x64/map_root_vp_state.o - $(TARGET_MODULE)-objs += ../src/x64/send_command_report_off.o - $(TARGET_MODULE)-objs += ../src/x64/send_command_report_on.o - $(TARGET_MODULE)-objs += ../src/x64/send_command_stop.o - $(TARGET_MODULE)-objs += ../src/x64/serial_init.o - $(TARGET_MODULE)-objs += ../src/x64/serial_write.o - $(TARGET_MODULE)-objs += ../src/x64/set_gdt_descriptor.o - $(TARGET_MODULE)-objs += ../src/x64/set_idt_descriptor.o - - $(TARGET_MODULE)-objs += ../src/x64/intel/enable_hve.o + $(TARGET_MODULE)-objs += ../src/x64/intel/check_cpu_configuration.o $(TARGET_MODULE)-objs += ../src/x64/intel/disable_hve.o - $(TARGET_MODULE)-objs += ../src/x64/intel/check_for_hve_support.o + $(TARGET_MODULE)-objs += ../src/x64/intel/enable_hve.o - EXTRA_CFLAGS += -I$(src)/include/x64 EXTRA_CFLAGS += -I$(src)/include/x64/intel - EXTRA_CFLAGS += -I$(src)/../include/x64/ EXTRA_CFLAGS += -I$(src)/../include/x64/intel - EXTRA_CFLAGS += -I$(src)/../include/interface/c/x64 EXTRA_CFLAGS += -I$(src)/../include/interface/c/x64/intel endif + else BUILDSYSTEM_DIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) diff --git a/loader/linux/include/types.h b/loader/linux/include/types.h index 1966538a..55e6cfa3 100644 --- a/loader/linux/include/types.h +++ b/loader/linux/include/types.h @@ -29,7 +29,7 @@ #ifndef TYPES_H #define TYPES_H -#include "stdint.h" +#include /** * @brief Returned by a loader function when a function succeeds. diff --git a/loader/linux/src/platform.c b/loader/linux/src/platform.c index d8eeb318..83f20037 100644 --- a/loader/linux/src/platform.c +++ b/loader/linux/src/platform.c @@ -427,3 +427,26 @@ platform_on_each_cpu(platform_per_cpu_func const func, uint32_t const order) return ret; } + +/** + * + * @brief Dumps the contents of the VMM's ring buffer. + */ +void +platform_dump_vmm(void) +{} + +/** + * + * @brief Initializes the archiecture. Some platforms might need per CPU + * initialization logic to get the CPU set up. Most platforms ignore + * calls to this function + * + * + * @return Returns 0 on success, LOADER_FAILURE otherwise + */ +int64_t +platform_arch_init(void) +{ + return LOADER_SUCCESS; +} diff --git a/loader/linux/src/x64/demote.S b/loader/linux/src/x64/demote.S index 0e754fb0..448594be 100644 --- a/loader/linux/src/x64/demote.S +++ b/loader/linux/src/x64/demote.S @@ -26,8 +26,132 @@ * SOFTWARE. */ +#define ASSEMBLY +#include #include + /** @brief defines the offset of state_save_t.rax */ + #define SS_OFFSET_RAX 0x000 + /** @brief defines the offset of state_save_t.rbx */ + #define SS_OFFSET_RBX 0x008 + /** @brief defines the offset of state_save_t.rcx */ + #define SS_OFFSET_RCX 0x010 + /** @brief defines the offset of state_save_t.rdx */ + #define SS_OFFSET_RDX 0x018 + /** @brief defines the offset of state_save_t.rbp */ + #define SS_OFFSET_RBP 0x020 + /** @brief defines the offset of state_save_t.rsi */ + #define SS_OFFSET_RSI 0x028 + /** @brief defines the offset of state_save_t.rdi */ + #define SS_OFFSET_RDI 0x030 + /** @brief defines the offset of state_save_t.r8 */ + #define SS_OFFSET_R8 0x038 + /** @brief defines the offset of state_save_t.r9 */ + #define SS_OFFSET_R9 0x040 + /** @brief defines the offset of state_save_t.r10 */ + #define SS_OFFSET_R10 0x048 + /** @brief defines the offset of state_save_t.r11 */ + #define SS_OFFSET_R11 0x050 + /** @brief defines the offset of state_save_t.r12 */ + #define SS_OFFSET_R12 0x058 + /** @brief defines the offset of state_save_t.r13 */ + #define SS_OFFSET_R13 0x060 + /** @brief defines the offset of state_save_t.r14 */ + #define SS_OFFSET_R14 0x068 + /** @brief defines the offset of state_save_t.r15 */ + #define SS_OFFSET_R15 0x070 + /** @brief defines the offset of state_save_t.rip */ + #define SS_OFFSET_RIP 0x078 + /** @brief defines the offset of state_save_t.rsp */ + #define SS_OFFSET_RSP 0x080 + /** @brief defines the offset of state_save_t.rflags */ + #define SS_OFFSET_RFLAGS 0x088 + /** @brief defines the offset of state_save_t.gdtr */ + #define SS_OFFSET_GDTR 0x0A0 + /** @brief defines the offset of state_save_t.idtr */ + #define SS_OFFSET_IDTR 0x0B0 + /** @brief defines the offset of state_save_t.es_selector */ + #define SS_OFFSET_ES_SELECTOR 0x0C0 + /** @brief defines the offset of state_save_t.cs_selector */ + #define SS_OFFSET_CS_SELECTOR 0x0D0 + /** @brief defines the offset of state_save_t.ss_selector */ + #define SS_OFFSET_SS_SELECTOR 0x0E0 + /** @brief defines the offset of state_save_t.ds_selector */ + #define SS_OFFSET_DS_SELECTOR 0x0F0 + /** @brief defines the offset of state_save_t.fs_selector */ + #define SS_OFFSET_FS_SELECTOR 0x100 + /** @brief defines the offset of state_save_t.gs_selector */ + #define SS_OFFSET_GS_SELECTOR 0x110 + /** @brief defines the offset of state_save_t.ldtr_selector */ + #define SS_OFFSET_LDTR_SELECTOR 0x120 + /** @brief defines the offset of state_save_t.tr_selector */ + #define SS_OFFSET_TR_SELECTOR 0x130 + /** @brief defines the offset of state_save_t.cr0 */ + #define SS_OFFSET_CR0 0x140 + /** @brief defines the offset of state_save_t.cr2 */ + #define SS_OFFSET_CR2 0x150 + /** @brief defines the offset of state_save_t.cr3 */ + #define SS_OFFSET_CR3 0x158 + /** @brief defines the offset of state_save_t.cr4 */ + #define SS_OFFSET_CR4 0x160 + /** @brief defines the offset of state_save_t.dr6 */ + #define SS_OFFSET_DR6 0x1F0 + /** @brief defines the offset of state_save_t.dr7 */ + #define SS_OFFSET_DR7 0x1F8 + /** @brief defines the offset of state_save_t.ia32_efer */ + #define SS_OFFSET_IA32_EFER 0x240 + /** @brief defines the offset of state_save_t.ia32_star */ + #define SS_OFFSET_IA32_STAR 0x248 + /** @brief defines the offset of state_save_t.ia32_lstar */ + #define SS_OFFSET_IA32_LSTAR 0x250 + /** @brief defines the offset of state_save_t.ia32_cstar */ + #define SS_OFFSET_IA32_CSTAR 0x258 + /** @brief defines the offset of state_save_t.ia32_fmask */ + #define SS_OFFSET_IA32_FMASK 0x260 + /** @brief defines the offset of state_save_t.ia32_fs_base */ + #define SS_OFFSET_IA32_FS_BASE 0x268 + /** @brief defines the offset of state_save_t.ia32_gs_base */ + #define SS_OFFSET_IA32_GS_BASE 0x270 + /** @brief defines the offset of state_save_t.ia32_kernel_gs_base */ + #define SS_OFFSET_IA32_KERNEL_GS_BASE 0x278 + /** @brief defines the offset of state_save_t.ia32_sysenter_cs */ + #define SS_OFFSET_IA32_SYSENTER_CS 0x280 + /** @brief defines the offset of state_save_t.ia32_sysenter_esp */ + #define SS_OFFSET_IA32_SYSENTER_ESP 0x288 + /** @brief defines the offset of state_save_t.ia32_sysenter_eip */ + #define SS_OFFSET_IA32_SYSENTER_EIP 0x290 + /** @brief defines the offset of state_save_t.ia32_pat */ + #define SS_OFFSET_IA32_PAT 0x298 + /** @brief defines the offset of state_save_t.ia32_debugctl */ + #define SS_OFFSET_IA32_DEBUGCTL 0x2A0 + + /** @brief defines MSR_IA32_SYSENTER_CS */ + #define MSR_IA32_SYSENTER_CS 0x00000174 + /** @brief defines MSR_IA32_SYSENTER_ESP */ + #define MSR_IA32_SYSENTER_ESP 0x00000175 + /** @brief defines MSR_IA32_SYSENTER_EIP */ + #define MSR_IA32_SYSENTER_EIP 0x00000176 + /** @brief defines MSR_IA32_DEBUGCTL */ + #define MSR_IA32_DEBUGCTL 0x000001D9 + /** @brief defines MSR_IA32_PAT */ + #define MSR_IA32_PAT 0x00000277 + /** @brief defines MSR_IA32_EFER */ + #define MSR_IA32_EFER 0xC0000080 + /** @brief defines MSR_IA32_STAR */ + #define MSR_IA32_STAR 0xC0000081 + /** @brief defines MSR_IA32_LSTAR */ + #define MSR_IA32_LSTAR 0xC0000082 + /** @brief defines MSR_IA32_CSTAR */ + #define MSR_IA32_CSTAR 0xC0000083 + /** @brief defines MSR_IA32_FMASK */ + #define MSR_IA32_FMASK 0xC0000084 + /** @brief defines MSR_IA32_FS_BASE */ + #define MSR_IA32_FS_BASE 0xC0000100 + /** @brief defines MSR_IA32_GS_BASE */ + #define MSR_IA32_GS_BASE 0xC0000101 + /** @brief defines MSR_IA32_KERNEL_GS_BASE */ + #define MSR_IA32_KERNEL_GS_BASE 0xC0000102 + .code64 .intel_syntax noprefix @@ -36,29 +160,35 @@ demote: UNWIND_HINT_EMPTY + /**************************************************************************/ + /* Report Success On Completion */ + /**************************************************************************/ + + xor rax, rax + /**************************************************************************/ /* General Purpose Registers */ /**************************************************************************/ - mov [rdx + 0x000], rax - mov [rdx + 0x008], rbx - mov [rdx + 0x010], rcx - mov [rdx + 0x018], rdx - mov [rdx + 0x020], rbp - mov [rdx + 0x028], rsi - mov [rdx + 0x030], rdi - mov [rdx + 0x038], r8 - mov [rdx + 0x040], r9 - mov [rdx + 0x048], r10 - mov [rdx + 0x050], r11 - mov [rdx + 0x058], r12 - mov [rdx + 0x060], r13 - mov [rdx + 0x068], r14 - mov [rdx + 0x070], r15 + mov [rdx + SS_OFFSET_RAX], rax + mov [rdx + SS_OFFSET_RBX], rbx + mov [rdx + SS_OFFSET_RCX], rcx + mov [rdx + SS_OFFSET_RDX], rdx + mov [rdx + SS_OFFSET_RBP], rbp + mov [rdx + SS_OFFSET_RSI], rsi + mov [rdx + SS_OFFSET_RDI], rdi + mov [rdx + SS_OFFSET_R8], r8 + mov [rdx + SS_OFFSET_R9], r9 + mov [rdx + SS_OFFSET_R10], r10 + mov [rdx + SS_OFFSET_R11], r11 + mov [rdx + SS_OFFSET_R12], r12 + mov [rdx + SS_OFFSET_R13], r13 + mov [rdx + SS_OFFSET_R14], r14 + mov [rdx + SS_OFFSET_R15], r15 - lea rax, [rip + demotion_success] - mov [rdx + 0x078], rax - mov [rdx + 0x080], rsp + lea rax, [rip + demotion_return] + mov [rdx + SS_OFFSET_RIP], rax + mov [rdx + SS_OFFSET_RSP], rsp /**************************************************************************/ /* Setup */ @@ -73,8 +203,8 @@ demote: /**************************************************************************/ pushf - pop [r15 + 0x088] - push [r14 + 0x088] + pop [r15 + SS_OFFSET_RFLAGS] + push [r14 + SS_OFFSET_RFLAGS] popf /**************************************************************************/ @@ -83,168 +213,162 @@ demote: call disable_interrupts - sidt [r15 + 0x0B0] - lidt [r14 + 0x0B0] + sidt [r15 + SS_OFFSET_IDTR] + lidt [r14 + SS_OFFSET_IDTR] /**************************************************************************/ /* MSRs */ /**************************************************************************/ - mov ecx, 0xC0000080 /* EFER */ + mov ecx, MSR_IA32_EFER rdmsr - mov [r15 + 0x240], eax - mov [r15 + 0x244], edx - mov eax, [r14 + 0x240] - mov edx, [r14 + 0x244] + mov [r15 + SS_OFFSET_IA32_EFER + 0x0], eax + mov [r15 + SS_OFFSET_IA32_EFER + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_EFER + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_EFER + 0x4] wrmsr - mov ecx, 0xC0000081 /* STAR */ + mov ecx, MSR_IA32_STAR rdmsr - mov [r15 + 0x248], eax - mov [r15 + 0x24C], edx - mov eax, [r14 + 0x248] - mov edx, [r14 + 0x24C] + mov [r15 + SS_OFFSET_IA32_STAR + 0x0], eax + mov [r15 + SS_OFFSET_IA32_STAR + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_STAR + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_STAR + 0x4] wrmsr - mov ecx, 0xC0000082 /* LSTAR */ + mov ecx, MSR_IA32_LSTAR rdmsr - mov [r15 + 0x250], eax - mov [r15 + 0x254], edx - mov eax, [r14 + 0x250] - mov edx, [r14 + 0x254] + mov [r15 + SS_OFFSET_IA32_LSTAR + 0x0], eax + mov [r15 + SS_OFFSET_IA32_LSTAR + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_LSTAR + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_LSTAR + 0x4] wrmsr - mov ecx, 0xC0000083 /* CSTAR */ + mov ecx, MSR_IA32_CSTAR rdmsr - mov [r15 + 0x258], eax - mov [r15 + 0x25C], edx - mov eax, [r14 + 0x258] - mov edx, [r14 + 0x25C] + mov [r15 + SS_OFFSET_IA32_CSTAR + 0x0], eax + mov [r15 + SS_OFFSET_IA32_CSTAR + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_CSTAR + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_CSTAR + 0x4] wrmsr - mov ecx, 0xC0000084 /* FMASK */ + mov ecx, MSR_IA32_FMASK rdmsr - mov [r15 + 0x260], eax - mov [r15 + 0x264], edx - mov eax, [r14 + 0x260] - mov edx, [r14 + 0x264] + mov [r15 + SS_OFFSET_IA32_FMASK + 0x0], eax + mov [r15 + SS_OFFSET_IA32_FMASK + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_FMASK + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_FMASK + 0x4] wrmsr - mov ecx, 0xC0000100 /* FS Base */ + mov ecx, MSR_IA32_FS_BASE rdmsr - mov [r15 + 0x268], eax - mov [r15 + 0x26C], edx - mov eax, [r14 + 0x268] - mov edx, [r14 + 0x26C] + mov [r15 + SS_OFFSET_IA32_FS_BASE + 0x0], eax + mov [r15 + SS_OFFSET_IA32_FS_BASE + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_FS_BASE + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_FS_BASE + 0x4] wrmsr - mov ecx, 0xC0000101 /* GS Base */ + mov ecx, MSR_IA32_GS_BASE rdmsr - mov [r15 + 0x270], eax - mov [r15 + 0x274], edx - mov eax, [r14 + 0x270] - mov edx, [r14 + 0x274] + mov [r15 + SS_OFFSET_IA32_GS_BASE + 0x0], eax + mov [r15 + SS_OFFSET_IA32_GS_BASE + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_GS_BASE + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_GS_BASE + 0x4] wrmsr - mov ecx, 0xC0000102 /* Kernel GS Base */ + mov ecx, MSR_IA32_KERNEL_GS_BASE rdmsr - mov [r15 + 0x278], eax - mov [r15 + 0x27C], edx - mov eax, [r14 + 0x278] - mov edx, [r14 + 0x27C] + mov [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x0], eax + mov [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x4] wrmsr - mov ecx, 0x00000174 /* SYSENTER_CS */ + mov ecx, MSR_IA32_SYSENTER_CS rdmsr - mov [r15 + 0x280], eax - mov [r15 + 0x284], edx - mov eax, [r14 + 0x280] - mov edx, [r14 + 0x284] + mov [r15 + SS_OFFSET_IA32_SYSENTER_CS + 0x0], eax + mov [r15 + SS_OFFSET_IA32_SYSENTER_CS + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_SYSENTER_CS + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_SYSENTER_CS + 0x4] wrmsr - mov ecx, 0x00000175 /* SYSENTER_ESP */ + mov ecx, MSR_IA32_SYSENTER_ESP rdmsr - mov [r15 + 0x288], eax - mov [r15 + 0x28C], edx - mov eax, [r14 + 0x288] - mov edx, [r14 + 0x28C] + mov [r15 + SS_OFFSET_IA32_SYSENTER_ESP + 0x0], eax + mov [r15 + SS_OFFSET_IA32_SYSENTER_ESP + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_SYSENTER_ESP + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_SYSENTER_ESP + 0x4] wrmsr - mov ecx, 0x00000176 /* SYSENTER_EIP */ + mov ecx, MSR_IA32_SYSENTER_EIP rdmsr - mov [r15 + 0x290], eax - mov [r15 + 0x294], edx - mov eax, [r14 + 0x290] - mov edx, [r14 + 0x294] + mov [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x0], eax + mov [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_SYSENTER_EIP + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_SYSENTER_EIP + 0x4] wrmsr - mov ecx, 0x00000277 /* PAT */ + mov ecx, MSR_IA32_PAT rdmsr - mov [r15 + 0x298], eax - mov [r15 + 0x29C], edx - mov eax, [r14 + 0x298] - mov edx, [r14 + 0x29C] + mov [r15 + SS_OFFSET_IA32_PAT + 0x0], eax + mov [r15 + SS_OFFSET_IA32_PAT + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_PAT + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_PAT + 0x4] wrmsr - mov ecx, 0x000001D9 /* DEBUGCTL */ + mov ecx, MSR_IA32_DEBUGCTL rdmsr - mov [r15 + 0x2A0], eax - mov [r15 + 0x2A4], edx - mov eax, [r14 + 0x2A0] - mov edx, [r14 + 0x2A4] + mov [r15 + SS_OFFSET_IA32_DEBUGCTL + 0x0], eax + mov [r15 + SS_OFFSET_IA32_DEBUGCTL + 0x4], edx + mov eax, [r14 + SS_OFFSET_IA32_DEBUGCTL + 0x0] + mov edx, [r14 + SS_OFFSET_IA32_DEBUGCTL + 0x4] wrmsr /**************************************************************************/ /* GDT */ /**************************************************************************/ - sgdt [r15 + 0x0A0] - lgdt [r14 + 0x0A0] + sgdt [r15 + SS_OFFSET_GDTR] + lgdt [r14 + SS_OFFSET_GDTR] mov dx, es - mov [r15 + 0x0C0], dx - mov dx, [r14 + 0x0C0] + mov [r15 + SS_OFFSET_ES_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_ES_SELECTOR] mov es, dx mov dx, cs - mov [r15 + 0x0D0], dx - mov ax, [r14 + 0x0D0] + mov [r15 + SS_OFFSET_CS_SELECTOR], dx + mov ax, [r14 + SS_OFFSET_CS_SELECTOR] push rax mov dx, ss - mov [r15 + 0x0E0], dx - mov dx, [r14 + 0x0E0] + mov [r15 + SS_OFFSET_SS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_SS_SELECTOR] mov ss, dx mov dx, ds - mov [r15 + 0x0F0], dx - mov dx, [r14 + 0x0F0] + mov [r15 + SS_OFFSET_DS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_DS_SELECTOR] mov ds, dx mov dx, fs - mov [r15 + 0x100], dx - mov dx, [r14 + 0x100] + mov [r15 + SS_OFFSET_FS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_FS_SELECTOR] mov fs, dx mov dx, gs - mov [r15 + 0x110], dx - mov dx, [r14 + 0x110] + mov [r15 + SS_OFFSET_GS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_GS_SELECTOR] mov gs, dx - mov ecx, 0x000001D9 - xor rax, rax - xor rdx, rdx - mov ax, [r14 + 0x110] - wrmsr - sldt dx - mov [r15 + 0x120], dx - mov dx, [r14 + 0x120] + mov [r15 + SS_OFFSET_LDTR_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_LDTR_SELECTOR] lldt dx str dx - mov [r15 + 0x130], dx - mov dx, [r14 + 0x130] + mov [r15 + SS_OFFSET_TR_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_TR_SELECTOR] ltr dx lea rax, [rip + gdt_and_cs_loaded] @@ -259,39 +383,43 @@ gdt_and_cs_loaded: /**************************************************************************/ mov rax, cr0 - mov [r15 + 0x140], rax - mov rax, [r14 + 0x140] + mov [r15 + SS_OFFSET_CR0], rax + mov rax, [r14 + SS_OFFSET_CR0] mov cr0, rax mov rax, cr2 - mov [r15 + 0x150], rax - mov rax, [r14 + 0x150] + mov [r15 + SS_OFFSET_CR2], rax + mov rax, [r14 + SS_OFFSET_CR2] mov cr2, rax mov rax, cr4 - mov [r15 + 0x160], rax - mov rax, [r14 + 0x160] + mov [r15 + SS_OFFSET_CR4], rax + mov rax, [r14 + SS_OFFSET_CR4] mov cr4, rax mov rax, cr3 - mov [r15 + 0x158], rax - mov rax, [r14 + 0x158] + mov [r15 + SS_OFFSET_CR3], rax + mov rax, [r14 + SS_OFFSET_CR3] mov cr3, rax - mov rsp, [r14 + 0x080] + /**************************************************************************/ + /* Stack */ + /**************************************************************************/ + + mov rsp, [r14 + SS_OFFSET_RSP] /**************************************************************************/ /* Debug Registers */ /**************************************************************************/ mov rax, dr6 - mov [r15 + 0x1F0], rax - mov rax, [r14 + 0x1F0] + mov [r15 + SS_OFFSET_DR6], rax + mov rax, [r14 + SS_OFFSET_DR6] mov dr6, rax mov rax, dr7 - mov [r15 + 0x1F8], rax - mov rax, [r14 + 0x1F8] + mov [r15 + SS_OFFSET_DR7], rax + mov rax, [r14 + SS_OFFSET_DR7] mov dr7, rax /**************************************************************************/ @@ -299,11 +427,11 @@ gdt_and_cs_loaded: /**************************************************************************/ mov rdi, r13 - push [r14 + 0x078] + push [r14 + SS_OFFSET_RIP] ret int 3 -demotion_success: +demotion_return: /** * NOTE: diff --git a/loader/linux/src/x64/esr_default.S b/loader/linux/src/x64/esr_default.S index b072c870..bd1b4515 100644 --- a/loader/linux/src/x64/esr_default.S +++ b/loader/linux/src/x64/esr_default.S @@ -36,22 +36,43 @@ esr_default: UNWIND_HINT_EMPTY - mov rdx, 0x03F8 - mov rax, 0x45 - out dx, al + mov rdi, 'e' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x53 - out dx, al + mov rdi, 's' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x52 - out dx, al + mov rdi, 'r' + call serial_write_c + + mov rdi, '_' + call serial_write_c + + mov rdi, 'd' + call serial_write_c + + mov rdi, 'e' + call serial_write_c + + mov rdi, 'f' + call serial_write_c + + mov rdi, 'a' + call serial_write_c + + mov rdi, 'u' + call serial_write_c + + mov rdi, 'l' + call serial_write_c + + mov rdi, 't' + call serial_write_c + + mov rdi, '\n' + call serial_write_c cli hlt - ret - int 3 - .size esr_default, 0x1000 diff --git a/loader/linux/src/x64/esr_df.S b/loader/linux/src/x64/esr_df.S index d03f8ae1..0f4bb043 100644 --- a/loader/linux/src/x64/esr_df.S +++ b/loader/linux/src/x64/esr_df.S @@ -36,34 +36,28 @@ esr_df: UNWIND_HINT_EMPTY - mov rdx, 0x03F8 - mov rax, 0x45 - out dx, al + mov rdi, 'e' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x53 - out dx, al + mov rdi, 's' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x52 - out dx, al + mov rdi, 'r' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x20 - out dx, al + mov rdi, '_' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x44 - out dx, al + mov rdi, 'd' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x46 - out dx, al + mov rdi, 'f' + call serial_write_c + + mov rdi, '\n' + call serial_write_c cli hlt - ret - int 3 - .size esr_df, 0x1000 diff --git a/loader/linux/src/x64/esr_gpf.S b/loader/linux/src/x64/esr_gpf.S index 6cbcddb3..665f1079 100644 --- a/loader/linux/src/x64/esr_gpf.S +++ b/loader/linux/src/x64/esr_gpf.S @@ -36,38 +36,31 @@ esr_gpf: UNWIND_HINT_EMPTY - mov rdx, 0x03F8 - mov rax, 0x45 - out dx, al + mov rdi, 'e' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x53 - out dx, al + mov rdi, 's' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x52 - out dx, al + mov rdi, 'r' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x20 - out dx, al + mov rdi, '_' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x47 - out dx, al + mov rdi, 'g' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x50 - out dx, al + mov rdi, 'p' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x46 - out dx, al + mov rdi, 'f' + call serial_write_c + + mov rdi, '\n' + call serial_write_c cli hlt - ret - int 3 - .size esr_gpf, 0x1000 diff --git a/loader/linux/src/x64/esr_nmi.S b/loader/linux/src/x64/esr_nmi.S index 60efac10..741e9184 100644 --- a/loader/linux/src/x64/esr_nmi.S +++ b/loader/linux/src/x64/esr_nmi.S @@ -26,6 +26,9 @@ * SOFTWARE. */ + /** @brief defines the offset of state_save_t.ia32_debugctl */ + #define SS_OFFSET_NMI 0x318 + #include .code64 @@ -47,7 +50,7 @@ esr_nmi: push rdx mov rax, 0x1 - mov [r15 + 0x318], rax + mov [r15 + SS_OFFSET_NMI], rax pop rdx pop rax diff --git a/loader/linux/src/x64/esr_pf.S b/loader/linux/src/x64/esr_pf.S index bd9a8174..0c59b836 100644 --- a/loader/linux/src/x64/esr_pf.S +++ b/loader/linux/src/x64/esr_pf.S @@ -36,31 +36,25 @@ esr_pf: UNWIND_HINT_EMPTY - mov rdx, 0x03F8 - mov rax, 0x45 - out dx, al + mov rdi, 'e' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x53 - out dx, al + mov rdi, 's' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x52 - out dx, al + mov rdi, 'r' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x20 - out dx, al + mov rdi, '_' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x50 - out dx, al + mov rdi, 'p' + call serial_write_c - mov rdx, 0x03F8 - mov rax, 0x46 - out dx, al + mov rdi, 'f' + call serial_write_c - cli - hlt + mov rdi, '\n' + call serial_write_c .size esr_pf, 0x1000 diff --git a/loader/linux/src/x64/flush_cache.S b/loader/linux/src/x64/flush_cache.S new file mode 100644 index 00000000..a6085220 --- /dev/null +++ b/loader/linux/src/x64/flush_cache.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl flush_cache + .type flush_cache, @function +flush_cache: + + clflush [rdi] + ret + int 3 + + .size flush_cache, .-flush_cache diff --git a/loader/linux/src/x64/promote.S b/loader/linux/src/x64/promote.S index ddd3950f..a59290cb 100644 --- a/loader/linux/src/x64/promote.S +++ b/loader/linux/src/x64/promote.S @@ -26,8 +26,134 @@ * SOFTWARE. */ +#define ASSEMBLY +#include #include + /** @brief defines the offset of state_save_t.rax */ + #define SS_OFFSET_RAX 0x000 + /** @brief defines the offset of state_save_t.rbx */ + #define SS_OFFSET_RBX 0x008 + /** @brief defines the offset of state_save_t.rcx */ + #define SS_OFFSET_RCX 0x010 + /** @brief defines the offset of state_save_t.rdx */ + #define SS_OFFSET_RDX 0x018 + /** @brief defines the offset of state_save_t.rbp */ + #define SS_OFFSET_RBP 0x020 + /** @brief defines the offset of state_save_t.rsi */ + #define SS_OFFSET_RSI 0x028 + /** @brief defines the offset of state_save_t.rdi */ + #define SS_OFFSET_RDI 0x030 + /** @brief defines the offset of state_save_t.r8 */ + #define SS_OFFSET_R8 0x038 + /** @brief defines the offset of state_save_t.r9 */ + #define SS_OFFSET_R9 0x040 + /** @brief defines the offset of state_save_t.r10 */ + #define SS_OFFSET_R10 0x048 + /** @brief defines the offset of state_save_t.r11 */ + #define SS_OFFSET_R11 0x050 + /** @brief defines the offset of state_save_t.r12 */ + #define SS_OFFSET_R12 0x058 + /** @brief defines the offset of state_save_t.r13 */ + #define SS_OFFSET_R13 0x060 + /** @brief defines the offset of state_save_t.r14 */ + #define SS_OFFSET_R14 0x068 + /** @brief defines the offset of state_save_t.r15 */ + #define SS_OFFSET_R15 0x070 + /** @brief defines the offset of state_save_t.rip */ + #define SS_OFFSET_RIP 0x078 + /** @brief defines the offset of state_save_t.rsp */ + #define SS_OFFSET_RSP 0x080 + /** @brief defines the offset of state_save_t.rflags */ + #define SS_OFFSET_RFLAGS 0x088 + /** @brief defines the offset of state_save_t.gdtr */ + #define SS_OFFSET_GDTR 0x0A0 + /** @brief defines the offset of state_save_t.idtr */ + #define SS_OFFSET_IDTR 0x0B0 + /** @brief defines the offset of state_save_t.es_selector */ + #define SS_OFFSET_ES_SELECTOR 0x0C0 + /** @brief defines the offset of state_save_t.cs_selector */ + #define SS_OFFSET_CS_SELECTOR 0x0D0 + /** @brief defines the offset of state_save_t.ss_selector */ + #define SS_OFFSET_SS_SELECTOR 0x0E0 + /** @brief defines the offset of state_save_t.ds_selector */ + #define SS_OFFSET_DS_SELECTOR 0x0F0 + /** @brief defines the offset of state_save_t.fs_selector */ + #define SS_OFFSET_FS_SELECTOR 0x100 + /** @brief defines the offset of state_save_t.gs_selector */ + #define SS_OFFSET_GS_SELECTOR 0x110 + /** @brief defines the offset of state_save_t.ldtr_selector */ + #define SS_OFFSET_LDTR_SELECTOR 0x120 + /** @brief defines the offset of state_save_t.tr_selector */ + #define SS_OFFSET_TR_SELECTOR 0x130 + /** @brief defines the offset of state_save_t.cr0 */ + #define SS_OFFSET_CR0 0x140 + /** @brief defines the offset of state_save_t.cr2 */ + #define SS_OFFSET_CR2 0x150 + /** @brief defines the offset of state_save_t.cr3 */ + #define SS_OFFSET_CR3 0x158 + /** @brief defines the offset of state_save_t.cr4 */ + #define SS_OFFSET_CR4 0x160 + /** @brief defines the offset of state_save_t.dr6 */ + #define SS_OFFSET_DR6 0x1F0 + /** @brief defines the offset of state_save_t.dr7 */ + #define SS_OFFSET_DR7 0x1F8 + /** @brief defines the offset of state_save_t.ia32_efer */ + #define SS_OFFSET_IA32_EFER 0x240 + /** @brief defines the offset of state_save_t.ia32_star */ + #define SS_OFFSET_IA32_STAR 0x248 + /** @brief defines the offset of state_save_t.ia32_lstar */ + #define SS_OFFSET_IA32_LSTAR 0x250 + /** @brief defines the offset of state_save_t.ia32_cstar */ + #define SS_OFFSET_IA32_CSTAR 0x258 + /** @brief defines the offset of state_save_t.ia32_fmask */ + #define SS_OFFSET_IA32_FMASK 0x260 + /** @brief defines the offset of state_save_t.ia32_fs_base */ + #define SS_OFFSET_IA32_FS_BASE 0x268 + /** @brief defines the offset of state_save_t.ia32_gs_base */ + #define SS_OFFSET_IA32_GS_BASE 0x270 + /** @brief defines the offset of state_save_t.ia32_kernel_gs_base */ + #define SS_OFFSET_IA32_KERNEL_GS_BASE 0x278 + /** @brief defines the offset of state_save_t.ia32_sysenter_cs */ + #define SS_OFFSET_IA32_SYSENTER_CS 0x280 + /** @brief defines the offset of state_save_t.ia32_sysenter_esp */ + #define SS_OFFSET_IA32_SYSENTER_ESP 0x288 + /** @brief defines the offset of state_save_t.ia32_sysenter_eip */ + #define SS_OFFSET_IA32_SYSENTER_EIP 0x290 + /** @brief defines the offset of state_save_t.ia32_pat */ + #define SS_OFFSET_IA32_PAT 0x298 + /** @brief defines the offset of state_save_t.ia32_debugctl */ + #define SS_OFFSET_IA32_DEBUGCTL 0x2A0 + /** @brief defines the offset of state_save_t.nmi */ + #define SS_OFFSET_NMI 0x318 + + /** @brief defines MSR_IA32_SYSENTER_CS */ + #define MSR_IA32_SYSENTER_CS 0x00000174 + /** @brief defines MSR_IA32_SYSENTER_ESP */ + #define MSR_IA32_SYSENTER_ESP 0x00000175 + /** @brief defines MSR_IA32_SYSENTER_EIP */ + #define MSR_IA32_SYSENTER_EIP 0x00000176 + /** @brief defines MSR_IA32_DEBUGCTL */ + #define MSR_IA32_DEBUGCTL 0x000001D9 + /** @brief defines MSR_IA32_PAT */ + #define MSR_IA32_PAT 0x00000277 + /** @brief defines MSR_IA32_EFER */ + #define MSR_IA32_EFER 0xC0000080 + /** @brief defines MSR_IA32_STAR */ + #define MSR_IA32_STAR 0xC0000081 + /** @brief defines MSR_IA32_LSTAR */ + #define MSR_IA32_LSTAR 0xC0000082 + /** @brief defines MSR_IA32_CSTAR */ + #define MSR_IA32_CSTAR 0xC0000083 + /** @brief defines MSR_IA32_FMASK */ + #define MSR_IA32_FMASK 0xC0000084 + /** @brief defines MSR_IA32_FS_BASE */ + #define MSR_IA32_FS_BASE 0xC0000100 + /** @brief defines MSR_IA32_GS_BASE */ + #define MSR_IA32_GS_BASE 0xC0000101 + /** @brief defines MSR_IA32_KERNEL_GS_BASE */ + #define MSR_IA32_KERNEL_GS_BASE 0xC0000102 + .code64 .intel_syntax noprefix @@ -40,10 +166,10 @@ promote: /* Debug Registers */ /**************************************************************************/ - mov rax, [r15 + 0x1F8] + mov rax, [r15 + SS_OFFSET_DR7] mov dr7, rax - mov rax, [r15 + 0x1F0] + mov rax, [r15 + SS_OFFSET_DR6] mov dr6, rax /**************************************************************************/ @@ -63,27 +189,31 @@ promote: * CR3 so that we can push/pop as needed */ - mov rax, [r15 + 0x158] + mov rax, [r15 + SS_OFFSET_CR3] and rax, 0xFFFFFFFFFFFFF000 mov cr3, rax - mov rax, [r15 + 0x160] + mov rax, [r15 + SS_OFFSET_CR4] and rax, 0xFFFFFFFFFFFFFF7F mov cr4, rax - mov rax, [r15 + 0x158] + mov rax, [r15 + SS_OFFSET_CR3] mov cr3, rax - mov rax, [r15 + 0x160] + mov rax, [r15 + SS_OFFSET_CR4] mov cr4, rax - mov rax, [r15 + 0x150] + mov rax, [r15 + SS_OFFSET_CR2] mov cr2, rax - mov rax, [r15 + 0x140] + mov rax, [r15 + SS_OFFSET_CR0] mov cr0, rax - mov rsp, [r15 + 0x080] + /**************************************************************************/ + /* Stack */ + /**************************************************************************/ + + mov rsp, [r15 + SS_OFFSET_RSP] /**************************************************************************/ /* Clear TSS Busy */ @@ -124,30 +254,30 @@ promote: * this code needs to execute. */ - lgdt [r15 + 0x0A0] + lgdt [r15 + SS_OFFSET_GDTR] - mov dx, [r15 + 0x0C0] + mov dx, [r15 + SS_OFFSET_ES_SELECTOR] mov es, dx - mov ax, [r15 + 0x0D0] + mov ax, [r15 + SS_OFFSET_CS_SELECTOR] push rax - mov dx, [r15 + 0x0E0] + mov dx, [r15 + SS_OFFSET_SS_SELECTOR] mov ss, dx - mov dx, [r15 + 0x0F0] + mov dx, [r15 + SS_OFFSET_DS_SELECTOR] mov ds, dx - mov dx, [r15 + 0x100] + mov dx, [r15 + SS_OFFSET_FS_SELECTOR] mov fs, dx - mov dx, [r15 + 0x110] + mov dx, [r15 + SS_OFFSET_GS_SELECTOR] mov gs, dx - mov dx, [r15 + 0x120] + mov dx, [r15 + SS_OFFSET_LDTR_SELECTOR] lldt dx - mov dx, [r15 + 0x130] + mov dx, [r15 + SS_OFFSET_TR_SELECTOR] ltr dx lea rax, [rip + gdt_and_cs_loaded] @@ -161,82 +291,82 @@ gdt_and_cs_loaded: /* MSRs */ /**************************************************************************/ - mov ecx, 0x000001D9 /* DEBUGCTL */ - mov eax, [r15 + 0x2A0] - mov edx, [r15 + 0x2A4] + mov ecx, MSR_IA32_DEBUGCTL + mov eax, [r15 + SS_OFFSET_IA32_DEBUGCTL + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_DEBUGCTL + 0x4] wrmsr - mov ecx, 0x00000277 /* PAT */ - mov eax, [r15 + 0x298] - mov edx, [r15 + 0x29C] + mov ecx, MSR_IA32_PAT + mov eax, [r15 + SS_OFFSET_IA32_PAT + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_PAT + 0x4] wrmsr - mov ecx, 0x00000176 /* SYSENTER_EIP */ - mov eax, [r15 + 0x290] - mov edx, [r15 + 0x294] + mov ecx, MSR_IA32_SYSENTER_EIP + mov eax, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x4] wrmsr - mov ecx, 0x00000175 /* SYSENTER_ESP */ - mov eax, [r15 + 0x288] - mov edx, [r15 + 0x28C] + mov ecx, MSR_IA32_SYSENTER_EIP + mov eax, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0x4] wrmsr - mov ecx, 0x00000174 /* SYSENTER_CS */ - mov eax, [r15 + 0x280] - mov edx, [r15 + 0x284] + mov ecx, MSR_IA32_SYSENTER_CS + mov eax, [r15 + SS_OFFSET_IA32_SYSENTER_CS + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_SYSENTER_CS + 0x4] wrmsr - mov ecx, 0xC0000102 /* Kernel GS Base */ - mov eax, [r15 + 0x278] - mov edx, [r15 + 0x27C] + mov ecx, MSR_IA32_KERNEL_GS_BASE + mov eax, [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0x4] wrmsr - mov ecx, 0xC0000101 /* GS Base */ - mov eax, [r15 + 0x270] - mov edx, [r15 + 0x274] + mov ecx, MSR_IA32_GS_BASE + mov eax, [r15 + SS_OFFSET_IA32_GS_BASE + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_GS_BASE + 0x4] wrmsr - mov ecx, 0xC0000100 /* FS Base */ - mov eax, [r15 + 0x268] - mov edx, [r15 + 0x26C] + mov ecx, MSR_IA32_FS_BASE + mov eax, [r15 + SS_OFFSET_IA32_FS_BASE + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_FS_BASE + 0x4] wrmsr - mov ecx, 0xC0000084 /* FMASK */ - mov eax, [r15 + 0x260] - mov edx, [r15 + 0x264] + mov ecx, MSR_IA32_FMASK + mov eax, [r15 + SS_OFFSET_IA32_FMASK + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_FMASK + 0x4] wrmsr - mov ecx, 0xC0000083 /* CSTAR */ - mov eax, [r15 + 0x258] - mov edx, [r15 + 0x25C] + mov ecx, MSR_IA32_CSTAR + mov eax, [r15 + SS_OFFSET_IA32_CSTAR + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_CSTAR + 0x4] wrmsr - mov ecx, 0xC0000082 /* LSTAR */ - mov eax, [r15 + 0x250] - mov edx, [r15 + 0x254] + mov ecx, MSR_IA32_LSTAR + mov eax, [r15 + SS_OFFSET_IA32_LSTAR + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_LSTAR + 0x4] wrmsr - mov ecx, 0xC0000081 /* STAR */ - mov eax, [r15 + 0x248] - mov edx, [r15 + 0x24C] + mov ecx, MSR_IA32_STAR + mov eax, [r15 + SS_OFFSET_IA32_STAR + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_STAR + 0x4] wrmsr - mov ecx, 0xC0000080 /* EFER */ - mov eax, [r15 + 0x240] - mov edx, [r15 + 0x244] + mov ecx, MSR_IA32_EFER + mov eax, [r15 + SS_OFFSET_IA32_EFER + 0x0] + mov edx, [r15 + SS_OFFSET_IA32_EFER + 0x4] wrmsr /**************************************************************************/ /* IDT */ /**************************************************************************/ - lidt [r15 + 0x0B0] + lidt [r15 + SS_OFFSET_IDTR] /**************************************************************************/ /* NMIs */ /**************************************************************************/ - mov rax, [r15 + 0x318] + mov rax, [r15 + SS_OFFSET_NMI] cmp rax, 0x1 jne nmis_complete @@ -248,32 +378,32 @@ nmis_complete: /* Flags */ /**************************************************************************/ - push [r15 + 0x088] + push [r15 + SS_OFFSET_RFLAGS] popf /**************************************************************************/ /* General Purpose Registers */ /**************************************************************************/ - mov rax, [r15 + 0x078] + mov rax, [r15 + SS_OFFSET_RIP] push rax - mov r14, [r15 + 0x068] - mov r13, [r15 + 0x060] - mov r12, [r15 + 0x058] - mov r11, [r15 + 0x050] - mov r10, [r15 + 0x048] - mov r9, [r15 + 0x040] - mov r8, [r15 + 0x038] - mov rdi, [r15 + 0x030] - mov rsi, [r15 + 0x028] - mov rbp, [r15 + 0x020] - mov rdx, [r15 + 0x018] - mov rcx, [r15 + 0x010] - mov rbx, [r15 + 0x008] - mov rax, [r15 + 0x000] + mov r14, [r15 + SS_OFFSET_R14] + mov r13, [r15 + SS_OFFSET_R13] + mov r12, [r15 + SS_OFFSET_R12] + mov r11, [r15 + SS_OFFSET_R11] + mov r10, [r15 + SS_OFFSET_R10] + mov r9, [r15 + SS_OFFSET_R9] + mov r8, [r15 + SS_OFFSET_R8] + mov rdi, [r15 + SS_OFFSET_RDI] + mov rsi, [r15 + SS_OFFSET_RSI] + mov rbp, [r15 + SS_OFFSET_RBP] + mov rdx, [r15 + SS_OFFSET_RDX] + mov rcx, [r15 + SS_OFFSET_RCX] + mov rbx, [r15 + SS_OFFSET_RBX] + mov rax, [r15 + SS_OFFSET_RAX] - mov r15, [r15 + 0x070] + mov r15, [r15 + SS_OFFSET_R15] call enable_interrupts ret diff --git a/loader/linux/src/x64/serial_write_c.S b/loader/linux/src/x64/serial_write_c.S new file mode 100644 index 00000000..f25761a7 --- /dev/null +++ b/loader/linux/src/x64/serial_write_c.S @@ -0,0 +1,60 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define ASSEMBLY +#include +#include + + .code64 + .intel_syntax noprefix + + .globl serial_write_c + .align 0x1000 +serial_write_c: + UNWIND_HINT_EMPTY + + push rax + push rdx + +wait_for_ffio_empty: + mov rdx, HYPERVISOR_SERIAL_PORT + add rdx, 5 + in al, dx + + and al, 0x20 + cmp al, 0x0 + jz wait_for_ffio_empty + + mov rdx, HYPERVISOR_SERIAL_PORT + mov rax, rdi + out dx, al + + pop rdx + pop rax + ret + int 3 + + .size serial_write_c, .-serial_write_c diff --git a/loader/linux/src/x64/serial_write_hex.S b/loader/linux/src/x64/serial_write_hex.S new file mode 100644 index 00000000..2e6b34a6 --- /dev/null +++ b/loader/linux/src/x64/serial_write_hex.S @@ -0,0 +1,151 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define ASSEMBLY +#include +#include + + .code64 + .intel_syntax noprefix + + .globl serial_write_hex + .align 0x1000 +serial_write_hex: + UNWIND_HINT_EMPTY + + push rdx + + mov rdx, rdi + + mov rdi, 0x30 + call serial_write_c + + mov rdi, 0x78 + call serial_write_c + + mov rdi, rdx + shr rdi, 60 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 56 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 52 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 48 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 44 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 40 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 36 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 32 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 28 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 24 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 20 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 16 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 12 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 8 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + shr rdi, 4 + and rdi, 0xFF + call serial_write_hex_digit + + mov rdi, rdx + and rdi, 0xFF + call serial_write_hex_digit + + pop rdx + ret + int 3 + +serial_write_hex_digit: + + cmp rdi, 9 + jg serial_write_hex_digit_a_to_f + + add rdi, 0x30 + call serial_write_c + + ret + int 3 + +serial_write_hex_digit_a_to_f: + + add rdi, 0x37 + call serial_write_c + + ret + int 3 + + .size serial_write_hex, .-serial_write_hex diff --git a/loader/src/alloc_and_copy_mk_elf_segments.c b/loader/src/alloc_and_copy_mk_elf_segments.c index e1523d6b..0ae283c2 100644 --- a/loader/src/alloc_and_copy_mk_elf_segments.c +++ b/loader/src/alloc_and_copy_mk_elf_segments.c @@ -24,8 +24,8 @@ * SOFTWARE. */ -#include -#include +#include +#include #include #include #include diff --git a/loader/src/alloc_mk_huge_pool.c b/loader/src/alloc_mk_huge_pool.c index 002b8db5..264fd2f5 100644 --- a/loader/src/alloc_mk_huge_pool.c +++ b/loader/src/alloc_mk_huge_pool.c @@ -46,7 +46,7 @@ int64_t alloc_mk_huge_pool(uint32_t const size, struct mutable_span_t *const huge_pool) { if (0U == size) { - huge_pool->size = HYPERVISOR_HUGE_POOL_SIZE; + huge_pool->size = HYPERVISOR_MK_HUGE_POOL_SIZE; } else { huge_pool->size = HYPERVISOR_PAGE_SIZE * (uint64_t)size; diff --git a/loader/src/alloc_mk_page_pool.c b/loader/src/alloc_mk_page_pool.c index 1c0e2719..f573028f 100644 --- a/loader/src/alloc_mk_page_pool.c +++ b/loader/src/alloc_mk_page_pool.c @@ -46,7 +46,7 @@ int64_t alloc_mk_page_pool(uint32_t const size, struct mutable_span_t *const page_pool) { if (0U == size) { - page_pool->size = HYPERVISOR_PAGE_POOL_SIZE; + page_pool->size = HYPERVISOR_MK_PAGE_POOL_SIZE; } else { page_pool->size = HYPERVISOR_PAGE_SIZE * (uint64_t)size; diff --git a/loader/src/arm/aarch64/alloc_and_copy_mk_code_aliases.c b/loader/src/arm/aarch64/alloc_and_copy_mk_code_aliases.c new file mode 100644 index 00000000..03777532 --- /dev/null +++ b/loader/src/arm/aarch64/alloc_and_copy_mk_code_aliases.c @@ -0,0 +1,80 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * + * @brief The function's main purpose is allocate pages for all of the + * executable code that is currently linked into the kernel module, and + * copy this code into the newly allocated pages so that they can be + * mapped into the microkernel's root page tables, creating an alias. + * The following diagram is what we are doing here: + * + * |-------> physical address (OS kernel) + * | + * virtual address <----| + * | + * |-------> physical address (microkernel) + * + * As you can see, the same virtual address for both the OS kernel and + * the microkernel point to two different physical addresses. The + * physical address for the microkernel is the alias, and we create + * the alias by copying the page located in the OS kenrel to the page + * located in the microkernel. This is done because we cannot actually + * get the physical address of the OS kernel, but we can access the + * contents of the page using the virtual address. So we copy the page + * to a page that we can get the physical address of and point the + * microkernel to that page instead. It should be noted that on Linux, + * if you do try to get the physical address of the code that we need + * to map into the microkernel, you will actually get what looks like + * a valid physical address, but be warned that the page it returns + * is actually garbage. You can only get the physical address of + * memory that is allocated using vmalloc(), which is why we need to + * create the aliases, as we need the physical address of the code so + * that we can map it into the microkernel's root page tables. + * + * + * @param a a pointer to a code_aliases_t that will store the + * resulting aliases. + * @return 0 on success, LOADER_FAILURE on failure. + */ +int64_t +alloc_and_copy_mk_code_aliases(struct code_aliases_t *const a) +{ + (void)a; + return LOADER_SUCCESS; +} diff --git a/loader/src/arm/aarch64/alloc_and_copy_mk_state.c b/loader/src/arm/aarch64/alloc_and_copy_mk_state.c new file mode 100644 index 00000000..981f46d6 --- /dev/null +++ b/loader/src/arm/aarch64/alloc_and_copy_mk_state.c @@ -0,0 +1,121 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @brief defines the default value of daif */ +#define DEFAULT_DAIF ((uint64_t)0x3C0) +/** @brief defines the default value of spsel */ +#define DEFAULT_SPSEL ((uint64_t)0x1) + +/** @brief defines the default value of hcr_el2 */ +#define DEFAULT_HCR_EL2 ((uint64_t)0x0) +/** @brief defines the default value of mair_el2 */ +#define DEFAULT_MAIR_EL2 ((uint64_t)0xFFBB4400) +/** @brief defines the default value of sctlr_el2 */ +#define DEFAULT_SCTLR_EL2 ((uint64_t)0x30C5183D) +/** @brief defines the default value of tcr_el2 */ +#define DEFAULT_TCR_EL2 ((uint64_t)0x80843510) +/** @brief defines the default value of ttbr0_el2 */ +#define DEFAULT_TTBR0_EL2 ((uint64_t)0x0) + +/** + * + * @brief The function's main purpose is to set up the state for the + * microkernel. + * + * + * @param rpt the mkcrokernel's root page table + * @param mk_elf_file the microkernel's ELF file + * @param mk_stack the microkernel's stack + * @param mk_stack_virt the microkernel's virtual address of the stack + * @param state where to save the newly set up state to + * @return 0 on success, LOADER_FAILURE on failure. + */ +int64_t +alloc_and_copy_mk_state( + root_page_table_t const *const rpt, + struct span_t const *const mk_elf_file, + struct span_t const *const mk_stack, + uint64_t const mk_stack_virt, + struct state_save_t **const state) +{ + struct bfelf_elf64_ehdr_t const *ehdr = ((void *)0); + if (get_elf64_ehdr(mk_elf_file->addr, &ehdr)) { + bferror("get_elf64_ehdr failed"); + return LOADER_FAILURE; + } + + /**************************************************************************/ + /* Allocate the resulting state */ + /**************************************************************************/ + + *state = (struct state_save_t *)platform_alloc(HYPERVISOR_PAGE_SIZE); + if (((void *)0) == *state) { + bferror("platform_alloc failed"); + return LOADER_FAILURE; + } + + /**************************************************************************/ + /* General Purpose Registers */ + /**************************************************************************/ + + (*state)->pc_el2 = ((uint64_t)ehdr->e_entry); + (*state)->sp_el2 = ((uint64_t)(mk_stack_virt + mk_stack->size)); + + /**************************************************************************/ + /* Saved Program Status Registers (SPSR) */ + /**************************************************************************/ + + (*state)->daif = DEFAULT_DAIF; + (*state)->spsel = DEFAULT_SPSEL; + + /**************************************************************************/ + /* Exceptions */ + /**************************************************************************/ + + (*state)->vbar_el2 = ((uint64_t)&exception_vectors); + + /**************************************************************************/ + /* System Registers */ + /**************************************************************************/ + + (*state)->hcr_el2 = DEFAULT_HCR_EL2; + (*state)->mair_el2 = DEFAULT_MAIR_EL2; + (*state)->sctlr_el2 = DEFAULT_SCTLR_EL2; + (*state)->tcr_el2 = DEFAULT_TCR_EL2; + (*state)->ttbr0_el2 = platform_virt_to_phys(rpt); + + return LOADER_SUCCESS; +} diff --git a/loader/src/arm/aarch64/alloc_and_copy_root_vp_state.c b/loader/src/arm/aarch64/alloc_and_copy_root_vp_state.c new file mode 100644 index 00000000..89d77bab --- /dev/null +++ b/loader/src/arm/aarch64/alloc_and_copy_root_vp_state.c @@ -0,0 +1,97 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * + * @brief The function's main purpose is to save state from a root VP. + * The root VP is the thing executing the root VM's operating system + * (i.e., the kernel running this driver) for a specific processor. + * When the microkernel is started, it will overwrite this state, and + * then it will eventually take the state saved by this function and + * use it to run the OS inside a VM, in effect, demoting the currently + * running OS. + * + * + * @param state where to save the newly set up state to + * @return 0 on success, LOADER_FAILURE on failure. + */ +int64_t +alloc_and_copy_root_vp_state(struct state_save_t **const state) +{ + *state = (struct state_save_t *)platform_alloc(HYPERVISOR_PAGE_SIZE); + if (((void *)0) == *state) { + bferror("platform_alloc failed"); + return LOADER_FAILURE; + } + + /**************************************************************************/ + /* Saved Program Status Registers (SPSR) */ + /**************************************************************************/ + + (*state)->daif = read_daif(); + (*state)->spsel = read_spsel(); + + /**************************************************************************/ + /* Exceptions */ + /**************************************************************************/ + + (*state)->vbar_el2 = read_vbar_el2(); + + /**************************************************************************/ + /* System Registers */ + /**************************************************************************/ + + (*state)->hcr_el2 = read_hcr_el2(); + (*state)->mair_el2 = read_mair_el2(); + (*state)->sctlr_el2 = read_sctlr_el2(); + (*state)->tcr_el2 = read_tcr_el2(); + (*state)->ttbr0_el2 = read_ttbr0_el2(); + + /**************************************************************************/ + /* Handlers */ + /**************************************************************************/ + + (*state)->promote_handler = &promote; + (*state)->exception_vectors = &exception_vectors; + + return LOADER_SUCCESS; +} diff --git a/loader/src/arm/aarch64/alloc_l1t.c b/loader/src/arm/aarch64/alloc_l1t.c new file mode 100644 index 00000000..fc855c48 --- /dev/null +++ b/loader/src/arm/aarch64/alloc_l1t.c @@ -0,0 +1,92 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * + * @brief Given a l0t_t and a virtual address, this function allocates a + * l1t_t and adds it to the l0t_t. If an l1t_t has already been allocated, + * this function will fail. + * + * + * @param l0 the l0t_t to add the newly allocated l1t_t to + * @param virt the virtual address to get the l0t_t offset from. + * @return a pointer to the newly allocated l1t_t on success, ((void *)0) + * otherwise. + */ +struct l1t_t * +alloc_l1t(struct l0t_t *const l0t, uint64_t const virt) +{ + uint64_t i; + uint64_t phys; + struct l1t_t *l1t; + struct l0te_t *l0te; + + l0te = &l0t->entires[l0to(virt)]; + if (l0te->p != ((uint64_t)0)) { + bferror_x64("l1t already present", virt); + return ((void *)0); + } + + l1t = (struct l1t_t *)platform_alloc(sizeof(struct l1t_t)); + if (((void *)0) == l1t) { + bferror("platform_alloc failed"); + goto platform_alloc_l1t_failed; + } + + for (i = 0; i < LOADER_NUM_L1T_ENTRIES; ++i) { + flush_cache(&(l1t->entires[i])); + } + + phys = platform_virt_to_phys(l1t); + if (((uint64_t)0) == phys) { + bferror("platform_virt_to_phys_l1t failed"); + goto platform_virt_to_phys_l1t_failed; + } + + l0t->tables[l0to(virt)] = l1t; + l0te->phys = (phys >> HYPERVISOR_PAGE_SHIFT); + l0te->p = ((uint64_t)1); + l0te->bt = ((uint64_t)1); + + flush_cache(l0te); + return l1t; + +platform_virt_to_phys_l1t_failed: + + platform_free(l1t, sizeof(struct l1t_t)); +platform_alloc_l1t_failed: + + return ((void *)0); +} diff --git a/loader/src/arm/aarch64/alloc_l2t.c b/loader/src/arm/aarch64/alloc_l2t.c new file mode 100644 index 00000000..a1dc6b8e --- /dev/null +++ b/loader/src/arm/aarch64/alloc_l2t.c @@ -0,0 +1,92 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * + * @brief Given a l1t_t and a virtual address, this function allocates a + * l2t_t and adds it to the l1t_t. If an l2t_t has already been allocated, + * this function will fail. + * + * + * @param l1 the l1t_t to add the newly allocated l2t_t to + * @param virt the virtual address to get the l1t_t offset from. + * @return a pointer to the newly allocated l2t_t on success, ((void *)0) + * otherwise. + */ +struct l2t_t * +alloc_l2t(struct l1t_t *const l1t, uint64_t const virt) +{ + uint64_t i; + uint64_t phys; + struct l2t_t *l2t; + struct l1te_t *l1te; + + l1te = &l1t->entires[l1to(virt)]; + if (l1te->p != ((uint64_t)0)) { + bferror_x64("l2t already present", virt); + return ((void *)0); + } + + l2t = (struct l2t_t *)platform_alloc(sizeof(struct l2t_t)); + if (((void *)0) == l2t) { + bferror("platform_alloc failed"); + goto platform_alloc_l2t_failed; + } + + for (i = 0; i < LOADER_NUM_L2T_ENTRIES; ++i) { + flush_cache(&(l2t->entires[i])); + } + + phys = platform_virt_to_phys(l2t); + if (((uint64_t)0) == phys) { + bferror("platform_virt_to_phys_l2t failed"); + goto platform_virt_to_phys_l2t_failed; + } + + l1t->tables[l1to(virt)] = l2t; + l1te->phys = (phys >> HYPERVISOR_PAGE_SHIFT); + l1te->p = ((uint64_t)1); + l1te->bt = ((uint64_t)1); + + flush_cache(l1te); + return l2t; + +platform_virt_to_phys_l2t_failed: + + platform_free(l2t, sizeof(struct l2t_t)); +platform_alloc_l2t_failed: + + return ((void *)0); +} diff --git a/loader/src/arm/aarch64/alloc_l3t.c b/loader/src/arm/aarch64/alloc_l3t.c new file mode 100644 index 00000000..c1746bd5 --- /dev/null +++ b/loader/src/arm/aarch64/alloc_l3t.c @@ -0,0 +1,92 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * + * @brief Given a l2t_t and a virtual address, this function allocates a + * l3t_t and adds it to the l2t_t. If an l3t_t has already been allocated, + * this function will fail. + * + * + * @param l2 the l2t_t to add the newly allocated l3t_t to + * @param virt the virtual address to get the l2t_t offset from. + * @return a pointer to the newly allocated l3t_t on success, ((void *)0) + * otherwise. + */ +struct l3t_t * +alloc_l3t(struct l2t_t *const l2t, uint64_t const virt) +{ + uint64_t i; + uint64_t phys; + struct l3t_t *l3t; + struct l2te_t *l2te; + + l2te = &l2t->entires[l2to(virt)]; + if (l2te->p != ((uint64_t)0)) { + bferror_x64("l3t already present", virt); + return ((void *)0); + } + + l3t = (struct l3t_t *)platform_alloc(sizeof(struct l3t_t)); + if (((void *)0) == l3t) { + bferror("platform_alloc failed"); + goto platform_alloc_l3t_failed; + } + + for (i = 0; i < LOADER_NUM_L3T_ENTRIES; ++i) { + flush_cache(&(l3t->entires[i])); + } + + phys = platform_virt_to_phys(l3t); + if (((uint64_t)0) == phys) { + bferror("platform_virt_to_phys_l3t failed"); + goto platform_virt_to_phys_l3t_failed; + } + + l2t->tables[l2to(virt)] = l3t; + l2te->phys = (phys >> HYPERVISOR_PAGE_SHIFT); + l2te->p = ((uint64_t)1); + l2te->bt = ((uint64_t)1); + + flush_cache(l2te); + return l3t; + +platform_virt_to_phys_l3t_failed: + + platform_free(l3t, sizeof(struct l3t_t)); +platform_alloc_l3t_failed: + + return ((void *)0); +} diff --git a/loader/src/arm/aarch64/alloc_mk_root_page_table.c b/loader/src/arm/aarch64/alloc_mk_root_page_table.c new file mode 100644 index 00000000..c1842b97 --- /dev/null +++ b/loader/src/arm/aarch64/alloc_mk_root_page_table.c @@ -0,0 +1,64 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +/** + * + * @brief This function allocates the root page table + * + * + * @param rpt where to return the resulting root page table + * @return 0 on success, LOADER_FAILURE on failure. + */ +int64_t +alloc_mk_root_page_table(root_page_table_t **const rpt) +{ + uint64_t i; + + *rpt = (root_page_table_t *)platform_alloc(sizeof(root_page_table_t)); + if (((void *)0) == *rpt) { + bferror("platform_alloc failed"); + return LOADER_FAILURE; + } + + for (i = 0; i < LOADER_NUM_L0T_ENTRIES; ++i) { + flush_cache(&((*rpt)->entires[i])); + } + + if (map_4k_page_rw(*rpt, ((uint64_t)0), *rpt)) { + bferror("map_4k_page_rw failed"); + return LOADER_FAILURE; + } + + return LOADER_SUCCESS; +} diff --git a/loader/src/arm/aarch64/check_cpu_configuration.c b/loader/src/arm/aarch64/check_cpu_configuration.c new file mode 100644 index 00000000..086a79e8 --- /dev/null +++ b/loader/src/arm/aarch64/check_cpu_configuration.c @@ -0,0 +1,110 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + +/** @brief define the expected value of CurrentEL */ +#define CURRENTEL_EXPECTED ((uint64_t)0x8) + +/** + * NOTE: + * - ARMv8 doesn't really have the same thing as CPUID on x86. Instead, it + * has ID_ fields that can be read to get feature information that we care + * about. Due to this issue, there isn't a clean way to ensure the specific + * CPU we are executing on is supported, but instead we can only check + * to ensure specific features are supported. + * - ARMv8 has something called Virtualization Host Extensions (VHE). This + * was added in ARMv8.1. ARMv8.0 (i.e. the original) has had virtualization + * support from launch. The problem was, this initial virtualization + * support didn't include support for hosted (i.e. type 2) hypervisors. So + * hypervisors like Xen, HyperV and ESXi all worked great, but KVM needed a + * small stub inside of EL2 to forward traps to EL1 since you could not run + * the Linux kernel in EL2 which is how KVM works (as it is hosted). VHE + * adds support for this but allowing not only EL1 <-> EL0 but also + * EL2 <-> EL0, which is what allows Linux to run in EL2. + * - Bareflank's microkernel is a Type 1, meaning it is not hosted, so it + * does not need VHE support. On Intel, each extension runs in Ring 3. + * This is because rings 1 and 2 were removed. On ARM, extensions run in + * EL1, and any operations that an extension performs that are priviledged + * are trapped by the microkernel and handled. This is mainly because on + * CPUs that do not have VHE, the microkernel cannot run extensions in EL0. + * Even if it could, there would be no need and doing so would only reduce + * the overall performance of the extension as more operations would have + * to be moved to the microkernel. + * - Note that one limitation of using EL2 without VHE is that the hypervisor + * cannot use the upper half of the canonical address space. For Bareflank, + * this is a non-issue as it doesn't use this address space anyways. It + * should be noted however that if late-launch is ever supported, care will + * need to be taken to ensure kernel addresses from EL1 are not used by + * the microkernel, which is something the x86 version of the loader does + * when late-launch is used. + * - For now, the loader assumes we are running on ARMv8 or higher, and we + * check to ensure the loader is running in EL2. VHE is not enabled by the + * loader so it is never used. Any additional features that are needed by the + * microkernel can be checked here, but for now, it is pretty simple as we + * assume that we only have ARMv8.0. + */ + +/** + * + * @brief Check we're running on a supported ARM processor + * + * + * @return Return 0 if running on a supported ARM processor, LOADER_FAILURE + * otherwise. + */ +static inline int64_t +check_for_el2(void) +{ + if (CURRENTEL_EXPECTED != read_currentel()) { + bferror("cpu is not in EL2"); + return LOADER_FAILURE; + } + + return LOADER_SUCCESS; +} + +/** + * + * @brief This function checks to see if the CPU is supported as well as + * it's system configuration. + * + * + * @return Returns 0 on success + */ +int64_t +check_cpu_configuration(void) +{ + if (check_for_el2()) { + bferror("check_for_el2 failed"); + return LOADER_FAILURE; + } + + return LOADER_SUCCESS; +} diff --git a/loader/src/arm/aarch64/dump_mk_code_aliases.c b/loader/src/arm/aarch64/dump_mk_code_aliases.c new file mode 100644 index 00000000..535e60f3 --- /dev/null +++ b/loader/src/arm/aarch64/dump_mk_code_aliases.c @@ -0,0 +1,47 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +/** + * + * @brief Outputs the contents of a provided code_aliases_t. + * + * + * @param a the code_aliases_t to output + */ +void +dump_mk_code_aliases(struct code_aliases_t *const a) +{ + if (((void *)0) == a) { + bferror("a is NULL"); + return; + } + + return; +} diff --git a/loader/src/arm/aarch64/dump_mk_state.c b/loader/src/arm/aarch64/dump_mk_state.c new file mode 100644 index 00000000..fef6906d --- /dev/null +++ b/loader/src/arm/aarch64/dump_mk_state.c @@ -0,0 +1,95 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +/** + * + * @brief Outputs the contents of a provided mk state. + * + * + * @param state the mk state to output + * @param cpu the CPU that this mk state belongs to + */ +void +dump_mk_state(struct state_save_t *const state, uint32_t const cpu) +{ + if (((void *)0) == state) { + bferror("state is NULL"); + return; + } + + bfdebug_d32("mk state on cpu", cpu); + bfdebug_ptr(" - virt", state); + + bfdebug_x64(" - x0", state->x0); + bfdebug_x64(" - x1", state->x1); + bfdebug_x64(" - x2", state->x2); + bfdebug_x64(" - x3", state->x3); + bfdebug_x64(" - x4", state->x4); + bfdebug_x64(" - x5", state->x5); + bfdebug_x64(" - x6", state->x6); + bfdebug_x64(" - x7", state->x7); + bfdebug_x64(" - x8", state->x8); + bfdebug_x64(" - x9", state->x9); + bfdebug_x64(" - x10", state->x10); + bfdebug_x64(" - x11", state->x11); + bfdebug_x64(" - x12", state->x12); + bfdebug_x64(" - x13", state->x13); + bfdebug_x64(" - x14", state->x14); + bfdebug_x64(" - x15", state->x15); + bfdebug_x64(" - x16", state->x16); + bfdebug_x64(" - x17", state->x17); + bfdebug_x64(" - x18", state->x18); + bfdebug_x64(" - x19", state->x19); + bfdebug_x64(" - x20", state->x20); + bfdebug_x64(" - x21", state->x21); + bfdebug_x64(" - x22", state->x22); + bfdebug_x64(" - x23", state->x23); + bfdebug_x64(" - x24", state->x24); + bfdebug_x64(" - x25", state->x25); + bfdebug_x64(" - x26", state->x26); + bfdebug_x64(" - x27", state->x27); + bfdebug_x64(" - x28", state->x28); + bfdebug_x64(" - x29", state->x29); + bfdebug_x64(" - x30", state->x30); + bfdebug_x64(" - sp_el2", state->sp_el2); + bfdebug_x64(" - pc_el2", state->pc_el2); + + bfdebug_x64(" - daif", state->daif); + bfdebug_x64(" - spsel", state->spsel); + + bfdebug_x64(" - vbar_el2", state->vbar_el2); + bfdebug_ptr(" - vbar_el2 addr", &state->vbar_el2); + + bfdebug_x64(" - hcr_el2", state->hcr_el2); + bfdebug_x64(" - mair_el2", state->mair_el2); + bfdebug_x64(" - sctlr_el2", state->sctlr_el2); + bfdebug_x64(" - tcr_el2", state->tcr_el2); + bfdebug_x64(" - ttbr0_el2", state->ttbr0_el2); +} diff --git a/loader/src/arm/aarch64/dump_root_vp_state.c b/loader/src/arm/aarch64/dump_root_vp_state.c new file mode 100644 index 00000000..62b65332 --- /dev/null +++ b/loader/src/arm/aarch64/dump_root_vp_state.c @@ -0,0 +1,94 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +/** + * + * @brief Outputs the contents of a provided root vp state. + * + * + * @param state the root vp state to output + * @param cpu the CPU that this root vp state belongs to + */ +void +dump_root_vp_state(struct state_save_t *const state, uint32_t const cpu) +{ + if (((void *)0) == state) { + bferror("state is NULL"); + return; + } + + bfdebug_d32("root vp state on cpu", cpu); + bfdebug_ptr(" - virt", state); + + bfdebug_x64(" - x0", state->x0); + bfdebug_x64(" - x1", state->x1); + bfdebug_x64(" - x2", state->x2); + bfdebug_x64(" - x3", state->x3); + bfdebug_x64(" - x4", state->x4); + bfdebug_x64(" - x5", state->x5); + bfdebug_x64(" - x6", state->x6); + bfdebug_x64(" - x7", state->x7); + bfdebug_x64(" - x8", state->x8); + bfdebug_x64(" - x9", state->x9); + bfdebug_x64(" - x10", state->x10); + bfdebug_x64(" - x11", state->x11); + bfdebug_x64(" - x12", state->x12); + bfdebug_x64(" - x13", state->x13); + bfdebug_x64(" - x14", state->x14); + bfdebug_x64(" - x15", state->x15); + bfdebug_x64(" - x16", state->x16); + bfdebug_x64(" - x17", state->x17); + bfdebug_x64(" - x18", state->x18); + bfdebug_x64(" - x19", state->x19); + bfdebug_x64(" - x20", state->x20); + bfdebug_x64(" - x21", state->x21); + bfdebug_x64(" - x22", state->x22); + bfdebug_x64(" - x23", state->x23); + bfdebug_x64(" - x24", state->x24); + bfdebug_x64(" - x25", state->x25); + bfdebug_x64(" - x26", state->x26); + bfdebug_x64(" - x27", state->x27); + bfdebug_x64(" - x28", state->x28); + bfdebug_x64(" - x29", state->x29); + bfdebug_x64(" - x30", state->x30); + bfdebug_x64(" - sp_el2", state->sp_el2); + bfdebug_x64(" - pc_el2", state->pc_el2); + + bfdebug_x64(" - daif", state->daif); + bfdebug_x64(" - spsel", state->spsel); + + bfdebug_x64(" - vbar_el2", state->vbar_el2); + + bfdebug_x64(" - hcr_el2", state->hcr_el2); + bfdebug_x64(" - mair_el2", state->mair_el2); + bfdebug_x64(" - sctlr_el2", state->sctlr_el2); + bfdebug_x64(" - tcr_el2", state->tcr_el2); + bfdebug_x64(" - ttbr0_el2", state->ttbr0_el2); +} diff --git a/loader/src/arm/aarch64/free_l0t.c b/loader/src/arm/aarch64/free_l0t.c new file mode 100644 index 00000000..a343bc59 --- /dev/null +++ b/loader/src/arm/aarch64/free_l0t.c @@ -0,0 +1,54 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +/** + * + * @brief Given a l0t_t, this function will free any previously allocated + * tables. + * + * + * @param l0t the l0t_t to free + */ +void +free_l0t(struct l0t_t *const l0t) +{ + uint64_t idx; + + for (idx = ((uint64_t)0); idx < LOADER_NUM_L0T_ENTRIES; ++idx) { + struct l1t_t *const l1t = l0t->tables[idx]; + if (((void *)0) != l1t) { + free_l1t(l1t); + platform_free(l1t, sizeof(struct l1t_t)); + } + } +} diff --git a/loader/src/arm/aarch64/free_l1t.c b/loader/src/arm/aarch64/free_l1t.c new file mode 100644 index 00000000..b23eaa3a --- /dev/null +++ b/loader/src/arm/aarch64/free_l1t.c @@ -0,0 +1,54 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +/** + * + * @brief Given a l1t_t, this function will free any previously allocated + * tables. + * + * + * @param l1t the l1t_t to free + */ +void +free_l1t(struct l1t_t *const l1t) +{ + uint64_t idx; + + for (idx = ((uint64_t)0); idx < LOADER_NUM_L1T_ENTRIES; ++idx) { + struct l2t_t *const l2t = l1t->tables[idx]; + if (((void *)0) != l2t) { + free_l2t(l2t); + platform_free(l2t, sizeof(struct l2t_t)); + } + } +} diff --git a/loader/src/arm/aarch64/free_l2t.c b/loader/src/arm/aarch64/free_l2t.c new file mode 100644 index 00000000..9acd69df --- /dev/null +++ b/loader/src/arm/aarch64/free_l2t.c @@ -0,0 +1,52 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +/** + * + * @brief Given a l2t_t, this function will free any previously allocated + * tables. + * + * + * @param l2t the l2t_t to free + */ +void +free_l2t(struct l2t_t *const l2t) +{ + uint64_t idx; + + for (idx = ((uint64_t)0); idx < LOADER_NUM_L2T_ENTRIES; ++idx) { + struct l3t_t *const l3t = l2t->tables[idx]; + if (((void *)0) != l3t) { + platform_free(l3t, sizeof(struct l3t_t)); + } + } +} diff --git a/loader/src/arm/aarch64/free_mk_code_aliases.c b/loader/src/arm/aarch64/free_mk_code_aliases.c new file mode 100644 index 00000000..52d0d11a --- /dev/null +++ b/loader/src/arm/aarch64/free_mk_code_aliases.c @@ -0,0 +1,44 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + +/** + * + * @brief Releases a previously allocated code_aliases_t that was allocated + * using the alloc_and_copy_mk_code_aliases function. + * + * + * @param a the code_aliases_t to free. + */ +void +free_mk_code_aliases(struct code_aliases_t *const a) +{ + (void)a; +} diff --git a/loader/src/arm/aarch64/free_mk_root_page_table.c b/loader/src/arm/aarch64/free_mk_root_page_table.c new file mode 100644 index 00000000..b7907111 --- /dev/null +++ b/loader/src/arm/aarch64/free_mk_root_page_table.c @@ -0,0 +1,51 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + +/** + * + * @brief Releases a previously allocated root_page_table_t that was allocated + * using the alloc_mk_root_page_table function. + * + * + * @param rpt the root_page_table_t to free. + */ +void +free_mk_root_page_table(root_page_table_t **const rpt) +{ + if (((void *)0) == *rpt) { + return; + } + + free_l0t(*rpt); + + platform_free(*rpt, sizeof(root_page_table_t)); + *rpt = ((void *)0); +} diff --git a/loader/src/arm/aarch64/free_mk_state.c b/loader/src/arm/aarch64/free_mk_state.c new file mode 100644 index 00000000..474b3ad5 --- /dev/null +++ b/loader/src/arm/aarch64/free_mk_state.c @@ -0,0 +1,49 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + +/** + * + * @brief Releases a previously allocated state_save_t that was allocated + * using the alloc_and_copy_mk_state function. + * + * + * @param state the state_save_t to free. + */ +void +free_mk_state(struct state_save_t **const state) +{ + if (((void *)0) == *state) { + return; + } + + platform_free(*state, HYPERVISOR_PAGE_SIZE); + *state = ((void *)0); +} diff --git a/loader/src/arm/aarch64/free_root_vp_state.c b/loader/src/arm/aarch64/free_root_vp_state.c new file mode 100644 index 00000000..7620b645 --- /dev/null +++ b/loader/src/arm/aarch64/free_root_vp_state.c @@ -0,0 +1,49 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + +/** + * + * @brief Releases a previously allocated state_save_t that was allocated + * using the alloc_and_copy_root_vp_state function. + * + * + * @param state the state_save_t to free. + */ +void +free_root_vp_state(struct state_save_t **const state) +{ + if (((void *)0) == *state) { + return; + } + + platform_free(*state, HYPERVISOR_PAGE_SIZE); + *state = ((void *)0); +} diff --git a/loader/src/arm/aarch64/map_4k_page.c b/loader/src/arm/aarch64/map_4k_page.c new file mode 100644 index 00000000..930de4ef --- /dev/null +++ b/loader/src/arm/aarch64/map_4k_page.c @@ -0,0 +1,137 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * + * @brief This function maps a 4k page given a physical address into a + * provided root page table at the provided virtual address. If the page + * is already mapped, this function will fail. Also note that this memory + * might need to allocate memory to expand the size of the page table + * tree. If this function fails, it will NOT attempt to cleanup memory + * that it allocated. Instead, you should free the provided root page + * table as a whole on error, or once it is no longer needed. + * + * + * @param virt the virtual address to map phys to + * @param phys the physical address to map + * @param flags the p_flags field from the segment associated with this page + * @param rpt the root page table to place the resulting map + * @return 0 on success, LOADER_FAILURE on failure. + */ +int64_t +map_4k_page(uint64_t const virt, uint64_t phys, uint32_t const flags, root_page_table_t *const rpt) +{ + struct l1t_t *l1t = ((void *)0); + struct l2t_t *l2t = ((void *)0); + struct l3t_t *l3t = ((void *)0); + struct l3te_t *l3te = ((void *)0); + + if (((uint64_t)0) == virt) { + bferror_x64("virt is NULL", virt); + return LOADER_FAILURE; + } + + if (((uint64_t)0) == phys) { + phys = platform_virt_to_phys((void *)virt); + if (((uint64_t)0) == phys) { + bferror("platform_virt_to_phys failed"); + return LOADER_FAILURE; + } + } + + if ((virt & (HYPERVISOR_PAGE_SIZE - ((uint64_t)1))) != ((uint64_t)0)) { + bferror_x64("virt is not page aligned", virt); + return LOADER_FAILURE; + } + + if ((phys & (HYPERVISOR_PAGE_SIZE - ((uint64_t)1))) != ((uint64_t)0)) { + bferror_x64("phys is not page aligned", phys); + return LOADER_FAILURE; + } + + l1t = rpt->tables[l0to(virt)]; + if (((void *)0) == l1t) { + l1t = alloc_l1t(rpt, virt); + } + + l2t = l1t->tables[l1to(virt)]; + if (((void *)0) == l2t) { + l2t = alloc_l2t(l1t, virt); + } + + l3t = l2t->tables[l2to(virt)]; + if (((void *)0) == l3t) { + l3t = alloc_l3t(l2t, virt); + } + + l3te = &l3t->entires[l3to(virt)]; + if (l3te->p != ((uint64_t)0)) { + bferror_x64("virt already mapped", virt); + return LOADER_FAILURE; + } + + l3te->phys = (phys >> HYPERVISOR_PAGE_SHIFT); + l3te->p = ((uint64_t)0x1); + l3te->page = ((uint64_t)0x1); + l3te->af = ((uint64_t)0x1); + + if ((flags & bfelf_pf_w) == 0U) { + l3te->ap = ((uint64_t)0x2); + } + + if ((flags & bfelf_pf_x) == 0U) { + l3te->xn = ((uint64_t)0x1); + } + + if ((flags & bfelf_pf_nc) == 0U) { + l3te->attr_indx = ((uint64_t)0x3); + l3te->sh = ((uint64_t)0x3); + } + + flush_cache(l3te); + return LOADER_SUCCESS; +} diff --git a/loader/src/arm/aarch64/map_mk_code_aliases.c b/loader/src/arm/aarch64/map_mk_code_aliases.c new file mode 100644 index 00000000..7165c214 --- /dev/null +++ b/loader/src/arm/aarch64/map_mk_code_aliases.c @@ -0,0 +1,85 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * + * @brief This function maps the code aliases into the microkernel's + * root page tables. For more information about how this mapping is + * performed, please see alloc_and_copy_mk_code_aliases. + * + * + * @param a a pointer to a code_aliases_t that stores the aliases + * being mapped + * @param rpt the root page table to map the code aliases into + * @return 0 on success, LOADER_FAILURE on failure. + */ +int64_t +map_mk_code_aliases(struct code_aliases_t const *const a, root_page_table_t *const rpt) +{ + if (map_4k_page_rx(demote, ((uint64_t)0), rpt)) { + bferror("map_4k_page_rx failed"); + return LOADER_FAILURE; + } + + if (map_4k_page_rx(promote, ((uint64_t)0), rpt)) { + bferror("map_4k_page_rx failed"); + return LOADER_FAILURE; + } + + if (map_4k_page_rx(esr, ((uint64_t)0), rpt)) { + bferror("map_4k_page_rx failed"); + return LOADER_FAILURE; + } + + if (map_4k_page_rx(exception_vectors, ((uint64_t)0), rpt)) { + bferror("map_4k_page_rx failed"); + return LOADER_FAILURE; + } + + if (map_4k_page_rx(serial_write_c, ((uint64_t)0), rpt)) { + bferror("map_4k_page_rx failed"); + return LOADER_FAILURE; + } + + if (map_4k_page_rx(serial_write_hex, ((uint64_t)0), rpt)) { + bferror("map_4k_page_rx failed"); + return LOADER_FAILURE; + } + + return LOADER_SUCCESS; +} diff --git a/loader/src/arm/aarch64/map_mk_state.c b/loader/src/arm/aarch64/map_mk_state.c new file mode 100644 index 00000000..a427c189 --- /dev/null +++ b/loader/src/arm/aarch64/map_mk_state.c @@ -0,0 +1,68 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * + * @brief This function maps the microkernel's state into the microkernel's + * root page tables. + * + * + * @param state a pointer to a state_save_t that stores the state + * being mapped + * @param rpt the root page table to map the state into + * @return 0 on success, LOADER_FAILURE on failure. + */ +int64_t +map_mk_state(struct state_save_t const *const state, root_page_table_t *const rpt) +{ + uint64_t uart0_addr = 0; + bfelf_elf64_word const rwnc = bfelf_pf_w | bfelf_pf_r | bfelf_pf_nc; + + if (map_4k_page_rw(state, ((uint64_t)0), rpt)) { + bferror("map_4k_page_rw failed"); + return LOADER_FAILURE; + } + + uart0_addr |= ((uint64_t)HYPERVISOR_SERIAL_PORTH) << ((uint64_t)16); + uart0_addr |= ((uint64_t)HYPERVISOR_SERIAL_PORTL); + + if (map_4k_page(uart0_addr, ((uint64_t)0), rwnc, rpt)) { + bferror("map_4k_page failed"); + return LOADER_FAILURE; + } + + return LOADER_SUCCESS; +} diff --git a/loader/src/arm/aarch64/map_root_vp_state.c b/loader/src/arm/aarch64/map_root_vp_state.c new file mode 100644 index 00000000..326e6f04 --- /dev/null +++ b/loader/src/arm/aarch64/map_root_vp_state.c @@ -0,0 +1,53 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include + +/** + * + * @brief This function maps the root VP's state into the microkernel's + * root page tables. + * + * + * @param state a pointer to a state_save_t that stores the state + * being mapped + * @param rpt the root page table to map the state into + * @return 0 on success, LOADER_FAILURE on failure. + */ +int64_t +map_root_vp_state(struct state_save_t const *const state, root_page_table_t *const rpt) +{ + if (map_4k_page_rw(state, ((uint64_t)0), rpt)) { + bferror("map_4k_page_rw failed"); + return LOADER_FAILURE; + } + + return LOADER_SUCCESS; +} diff --git a/loader/src/arm/aarch64/send_command_report_off.c b/loader/src/arm/aarch64/send_command_report_off.c new file mode 100644 index 00000000..90625345 --- /dev/null +++ b/loader/src/arm/aarch64/send_command_report_off.c @@ -0,0 +1,36 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +/** + * + * @brief Tells the hypervisor to report off + */ +void +send_command_report_off(void) +{} diff --git a/loader/src/arm/aarch64/send_command_report_on.c b/loader/src/arm/aarch64/send_command_report_on.c new file mode 100644 index 00000000..0e626803 --- /dev/null +++ b/loader/src/arm/aarch64/send_command_report_on.c @@ -0,0 +1,36 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +/** + * + * @brief Tells the hypervisor to report on + */ +void +send_command_report_on(void) +{} diff --git a/loader/src/arm/aarch64/send_command_stop.c b/loader/src/arm/aarch64/send_command_stop.c new file mode 100644 index 00000000..a351cf61 --- /dev/null +++ b/loader/src/arm/aarch64/send_command_stop.c @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +/** + * + * @brief Tells the hypervisor to stop + * + * + * @return 0 on success, LOADER_FAILURE on failure. + */ +int64_t +send_command_stop(void) +{ + return LOADER_SUCCESS; +} diff --git a/loader/src/arm/aarch64/serial_init.c b/loader/src/arm/aarch64/serial_init.c new file mode 100644 index 00000000..de4d6cbe --- /dev/null +++ b/loader/src/arm/aarch64/serial_init.c @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * + * @brief Initializes the serial port for use + */ +void +serial_init(void) +{ + /** + * NOTE: + * - The UART should be enabled by the bootloader automatically, so on + * the platforms that we currently support, there is no need to set up + * the UART manually. + * + * https://www.raspberrypi.org/documentation/configuration/config-txt/ + */ +} diff --git a/loader/src/dump_ext_elf_files.c b/loader/src/dump_ext_elf_files.c index 09b4b96d..3de8abef 100644 --- a/loader/src/dump_ext_elf_files.c +++ b/loader/src/dump_ext_elf_files.c @@ -35,13 +35,17 @@ * * * @param files the array of extension ELF files to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_ext_elf_files(struct span_t *const files) { uint64_t idx; + if (((void *)0) == files) { + bferror("files is NULL"); + return; + } + for (idx = ((uint64_t)0); idx < HYPERVISOR_MAX_EXTENSIONS; ++idx) { if (((void *)0) != files[idx].addr) { bfdebug_d32("ext elf file", (uint32_t)idx); diff --git a/loader/src/dump_mk_args.c b/loader/src/dump_mk_args.c index e76e6418..768cf717 100644 --- a/loader/src/dump_mk_args.c +++ b/loader/src/dump_mk_args.c @@ -35,13 +35,17 @@ * * @param args the mk args to output * @param cpu the CPU that this mk args belongs to - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_args(struct mk_args_t *const args, uint32_t const cpu) { uint64_t idx; + if (((void *)0) == args) { + bferror("args is NULL"); + return; + } + bfdebug_d32("mk args on cpu", cpu); bfdebug_x16(" - online_pps", args->online_pps); bfdebug_ptr(" - mk_state", args->mk_state); diff --git a/loader/src/dump_mk_debug_ring.c b/loader/src/dump_mk_debug_ring.c index c5a716d4..5c2b6a95 100644 --- a/loader/src/dump_mk_debug_ring.c +++ b/loader/src/dump_mk_debug_ring.c @@ -35,11 +35,15 @@ * * * @param debug_ring the mk debug ring to output information about - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_debug_ring(struct debug_ring_t *const debug_ring) { + if (((void *)0) == debug_ring) { + bferror("debug_ring is NULL"); + return; + } + bfdebug("mk debug ring:"); bfdebug_ptr(" - addr", debug_ring); bfdebug_x64(" - size", HYPERVISOR_DEBUG_RING_SIZE); diff --git a/loader/src/dump_mk_elf_file.c b/loader/src/dump_mk_elf_file.c index b82d0e5d..c415ea24 100644 --- a/loader/src/dump_mk_elf_file.c +++ b/loader/src/dump_mk_elf_file.c @@ -34,11 +34,15 @@ * * * @param file the mk elf file to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_elf_file(struct span_t *const file) { + if (((void *)0) == file) { + bferror("file is NULL"); + return; + } + bfdebug("mk elf file:"); bfdebug_ptr(" - addr", file->addr); bfdebug_x64(" - size", file->size); diff --git a/loader/src/dump_mk_elf_segments.c b/loader/src/dump_mk_elf_segments.c index 2eb1b186..c8b1af26 100644 --- a/loader/src/dump_mk_elf_segments.c +++ b/loader/src/dump_mk_elf_segments.c @@ -35,13 +35,17 @@ * * * @param segments the array of mk ELF segments to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_elf_segments(struct elf_segment_t *const segments) { uint64_t idx; + if (((void *)0) == segments) { + bferror("segments is NULL"); + return; + } + for (idx = ((uint64_t)0); idx < HYPERVISOR_MAX_SEGMENTS; ++idx) { if (((void *)0) != segments[idx].addr) { bfdebug_d32("mk elf segment", (uint32_t)idx); diff --git a/loader/src/dump_mk_huge_pool.c b/loader/src/dump_mk_huge_pool.c index 9dc7e6cb..9e3a6593 100644 --- a/loader/src/dump_mk_huge_pool.c +++ b/loader/src/dump_mk_huge_pool.c @@ -34,11 +34,15 @@ * * * @param huge_pool the mk huge pool to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_huge_pool(struct mutable_span_t *const huge_pool) { + if (((void *)0) == huge_pool) { + bferror("huge_pool is NULL"); + return; + } + bfdebug("mk huge pool:"); bfdebug_ptr(" - addr", huge_pool->addr); bfdebug_x64(" - size", huge_pool->size); diff --git a/loader/src/dump_mk_page_pool.c b/loader/src/dump_mk_page_pool.c index 26370179..70371ae8 100644 --- a/loader/src/dump_mk_page_pool.c +++ b/loader/src/dump_mk_page_pool.c @@ -34,11 +34,15 @@ * * * @param page_pool the mk page pool to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_page_pool(struct mutable_span_t *const page_pool) { + if (((void *)0) == page_pool) { + bferror("page_pool is NULL"); + return; + } + bfdebug("mk page pool:"); bfdebug_ptr(" - addr", page_pool->addr); bfdebug_x64(" - size", page_pool->size); diff --git a/loader/src/x64/dump_mk_root_page_table.c b/loader/src/dump_mk_root_page_table.c similarity index 84% rename from loader/src/x64/dump_mk_root_page_table.c rename to loader/src/dump_mk_root_page_table.c index b275b17c..102639b5 100644 --- a/loader/src/x64/dump_mk_root_page_table.c +++ b/loader/src/dump_mk_root_page_table.c @@ -25,7 +25,7 @@ */ #include -#include +#include #include /** @@ -33,12 +33,16 @@ * @brief Outputs the address of a provided mk root page table. * * - * @param pml4t the mk root page table to output - * @return 0 on success, LOADER_FAILURE on failure. + * @param rpt the mk root page table to output */ void -dump_mk_root_page_table(struct pml4t_t *const pml4t) +dump_mk_root_page_table(root_page_table_t *const rpt) { + if (((void *)0) == rpt) { + bferror("rpt is NULL"); + return; + } + bfdebug("mk root page table:"); - bfdebug_ptr(" - addr", pml4t); + bfdebug_ptr(" - addr", rpt); } diff --git a/loader/src/dump_mk_stack.c b/loader/src/dump_mk_stack.c index e6fece8c..d7190b62 100644 --- a/loader/src/dump_mk_stack.c +++ b/loader/src/dump_mk_stack.c @@ -35,11 +35,15 @@ * * @param stack the mk stack to output * @param cpu the CPU that this mk stack belongs to - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_stack(struct span_t *const stack, uint32_t const cpu) { + if (((void *)0) == stack) { + bferror("stack is NULL"); + return; + } + bfdebug_d32("mk stack on cpu", cpu); bfdebug_ptr(" - addr", stack->addr); bfdebug_x64(" - size", stack->size); diff --git a/loader/src/g_cpu_status.c b/loader/src/g_cpu_status.c new file mode 100644 index 00000000..1e4dba51 --- /dev/null +++ b/loader/src/g_cpu_status.c @@ -0,0 +1,31 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +/** @brief stores the current state of each CPU */ +uint32_t g_cpu_status[HYPERVISOR_MAX_PPS] = {0}; diff --git a/loader/src/g_mk_args.c b/loader/src/g_mk_args.c index c30be7c8..49955345 100644 --- a/loader/src/g_mk_args.c +++ b/loader/src/g_mk_args.c @@ -28,4 +28,4 @@ #include /** @brief stores the microkernel's _start args */ -struct mk_args_t *g_mk_args[HYPERVISOR_MAX_VPS_PER_VM] = {0}; +struct mk_args_t *g_mk_args[HYPERVISOR_MAX_PPS] = {0}; diff --git a/loader/src/x64/g_mk_code_aliases.c b/loader/src/g_mk_code_aliases.c similarity index 100% rename from loader/src/x64/g_mk_code_aliases.c rename to loader/src/g_mk_code_aliases.c diff --git a/loader/src/x64/g_mk_root_page_table.c b/loader/src/g_mk_root_page_table.c similarity index 93% rename from loader/src/x64/g_mk_root_page_table.c rename to loader/src/g_mk_root_page_table.c index 55a70fa9..520b8c68 100644 --- a/loader/src/x64/g_mk_root_page_table.c +++ b/loader/src/g_mk_root_page_table.c @@ -25,7 +25,7 @@ */ #include -#include +#include /** @brief stores pml4 for the microkernel */ -struct pml4t_t *g_mk_root_page_table = ((void *)0); +root_page_table_t *g_mk_root_page_table = ((void *)0); diff --git a/loader/src/g_mk_stack.c b/loader/src/g_mk_stack.c index 9302ca44..d5a0f677 100644 --- a/loader/src/g_mk_stack.c +++ b/loader/src/g_mk_stack.c @@ -29,7 +29,7 @@ #include /** @brief stores the stack used by the microkernel */ -struct span_t g_mk_stack[HYPERVISOR_MAX_VPS_PER_VM] = {0}; +struct span_t g_mk_stack[HYPERVISOR_MAX_PPS] = {0}; /** @brief stores the virtual address of the MK's stack */ uint64_t g_mk_stack_virt = HYPERVISOR_MK_STACK_ADDR; diff --git a/loader/src/x64/g_mk_state.c b/loader/src/g_mk_state.c similarity index 95% rename from loader/src/x64/g_mk_state.c rename to loader/src/g_mk_state.c index 66ccea95..e08050f9 100644 --- a/loader/src/x64/g_mk_state.c +++ b/loader/src/g_mk_state.c @@ -28,4 +28,4 @@ #include /** @brief stores the microkernel state saves */ -struct state_save_t *g_mk_state[HYPERVISOR_MAX_VPS_PER_VM]; +struct state_save_t *g_mk_state[HYPERVISOR_MAX_PPS]; diff --git a/loader/src/x64/g_root_vp_state.c b/loader/src/g_root_vp_state.c similarity index 95% rename from loader/src/x64/g_root_vp_state.c rename to loader/src/g_root_vp_state.c index 1fff3da1..49f29755 100644 --- a/loader/src/x64/g_root_vp_state.c +++ b/loader/src/g_root_vp_state.c @@ -28,4 +28,4 @@ #include /** @brief stores the root VP state saves */ -struct state_save_t *g_root_vp_state[HYPERVISOR_MAX_VPS_PER_VM]; +struct state_save_t *g_root_vp_state[HYPERVISOR_MAX_PPS]; diff --git a/loader/src/vmm_status.c b/loader/src/g_vmm_status.c similarity index 98% rename from loader/src/vmm_status.c rename to loader/src/g_vmm_status.c index 22255dd2..f9b3b1b4 100644 --- a/loader/src/vmm_status.c +++ b/loader/src/g_vmm_status.c @@ -24,7 +24,7 @@ * SOFTWARE. */ -#include +#include /** @brief stores the current state of the VMM */ uint32_t g_vmm_status = VMM_STATUS_STOPPED; diff --git a/loader/src/x64/get_mk_huge_pool_addr.c b/loader/src/get_mk_huge_pool_addr.c similarity index 100% rename from loader/src/x64/get_mk_huge_pool_addr.c rename to loader/src/get_mk_huge_pool_addr.c diff --git a/loader/src/x64/get_mk_page_pool_addr.c b/loader/src/get_mk_page_pool_addr.c similarity index 100% rename from loader/src/x64/get_mk_page_pool_addr.c rename to loader/src/get_mk_page_pool_addr.c diff --git a/loader/src/loader_fini.c b/loader/src/loader_fini.c index 0267ebf7..4c8d9866 100644 --- a/loader/src/loader_fini.c +++ b/loader/src/loader_fini.c @@ -29,9 +29,9 @@ #include #include #include +#include #include #include -#include /** * diff --git a/loader/src/loader_init.c b/loader/src/loader_init.c index f0f9d640..e5a18171 100644 --- a/loader/src/loader_init.c +++ b/loader/src/loader_init.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -34,9 +33,9 @@ #include #include #include +#include #include #include -#include /** * @@ -56,11 +55,6 @@ loader_init(void) return LOADER_FAILURE; } - if (check_for_hve_support()) { - bferror("check_for_hve_support failed"); - return LOADER_FAILURE; - } - if (alloc_mk_debug_ring(&g_mk_debug_ring)) { bferror("alloc_mk_debug_ring failed"); goto alloc_mk_debug_ring_failed; diff --git a/loader/src/x64/map_4k_page_rw.c b/loader/src/map_4k_page_rw.c similarity index 89% rename from loader/src/x64/map_4k_page_rw.c rename to loader/src/map_4k_page_rw.c index 29e2d2aa..fbb8af9a 100644 --- a/loader/src/x64/map_4k_page_rw.c +++ b/loader/src/map_4k_page_rw.c @@ -24,11 +24,11 @@ * SOFTWARE. */ -#include +#include #include #include #include -#include +#include /** * @@ -44,15 +44,15 @@ * * @param virt the virtual address to map phys to * @param phys the physical address to map - * @param pml4t the root page table to place the resulting map + * @param rpt the root page table to place the resulting map * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_4k_page_rw(void const *const virt, uint64_t const phys, struct pml4t_t *const pml4t) +map_4k_page_rw(void const *const virt, uint64_t const phys, root_page_table_t *const rpt) { bfelf_elf64_word const rw = bfelf_pf_w | bfelf_pf_r; - if (map_4k_page((uint64_t)virt, phys, rw, pml4t)) { + if (map_4k_page((uint64_t)virt, phys, rw, rpt)) { bferror("map_4k_page failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/map_4k_page_rx.c b/loader/src/map_4k_page_rx.c similarity index 89% rename from loader/src/x64/map_4k_page_rx.c rename to loader/src/map_4k_page_rx.c index ba62977c..2cdc43a6 100644 --- a/loader/src/x64/map_4k_page_rx.c +++ b/loader/src/map_4k_page_rx.c @@ -24,11 +24,11 @@ * SOFTWARE. */ -#include +#include #include #include #include -#include +#include /** * @@ -44,15 +44,15 @@ * * @param virt the virtual address to map phys to * @param phys the physical address to map - * @param pml4t the root page table to place the resulting map + * @param rpt the root page table to place the resulting map * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_4k_page_rx(void const *const virt, uint64_t const phys, struct pml4t_t *const pml4t) +map_4k_page_rx(void const *const virt, uint64_t const phys, root_page_table_t *const rpt) { bfelf_elf64_word const rw = bfelf_pf_r | bfelf_pf_x; - if (map_4k_page((uint64_t)virt, phys, rw, pml4t)) { + if (map_4k_page((uint64_t)virt, phys, rw, rpt)) { bferror("map_4k_page failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/map_ext_elf_files.c b/loader/src/map_ext_elf_files.c similarity index 84% rename from loader/src/x64/map_ext_elf_files.c rename to loader/src/map_ext_elf_files.c index 75f9977f..ce1dd2fa 100644 --- a/loader/src/x64/map_ext_elf_files.c +++ b/loader/src/map_ext_elf_files.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include /** @@ -39,16 +39,16 @@ * * @param file a pointer to a span_t that stores the ELF file * being mapped - * @param pml4t the root page table to map the stack into + * @param rpt the root page table to map the stack into * @return 0 on success, LOADER_FAILURE on failure. */ static int64_t -map_ext_elf_file(struct span_t const *const file, struct pml4t_t *const pml4t) +map_ext_elf_file(struct span_t const *const file, root_page_table_t *const rpt) { uint64_t off; for (off = ((uint64_t)0); off < file->size; off += HYPERVISOR_PAGE_SIZE) { - if (map_4k_page_rw(file->addr + off, ((uint64_t)0), pml4t)) { + if (map_4k_page_rw(file->addr + off, ((uint64_t)0), rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } @@ -65,16 +65,16 @@ map_ext_elf_file(struct span_t const *const file, struct pml4t_t *const pml4t) * * @param files a pointer to a span_t array that stores the ELF files * being mapped - * @param pml4t the root page table to map the ELF files into + * @param rpt the root page table to map the ELF files into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_ext_elf_files(struct span_t const *const files, struct pml4t_t *const pml4t) +map_ext_elf_files(struct span_t const *const files, root_page_table_t *const rpt) { uint64_t idx; for (idx = ((uint64_t)0); idx < HYPERVISOR_MAX_EXTENSIONS; ++idx) { - if (map_ext_elf_file(&files[idx], pml4t)) { + if (map_ext_elf_file(&files[idx], rpt)) { bferror("map_ext_elf_file failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/map_mk_args.c b/loader/src/map_mk_args.c similarity index 88% rename from loader/src/x64/map_mk_args.c rename to loader/src/map_mk_args.c index 664eae6b..7fb5f794 100644 --- a/loader/src/x64/map_mk_args.c +++ b/loader/src/map_mk_args.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include /** * @@ -38,13 +38,13 @@ * * @param args a pointer to a mk_args_t that stores the args * being mapped - * @param pml4t the root page table to map the args into + * @param rpt the root page table to map the args into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_mk_args(struct mk_args_t const *const args, struct pml4t_t *const pml4t) +map_mk_args(struct mk_args_t const *const args, root_page_table_t *const rpt) { - if (map_4k_page_rw(args, ((uint64_t)0), pml4t)) { + if (map_4k_page_rw(args, ((uint64_t)0), rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/map_mk_debug_ring.c b/loader/src/map_mk_debug_ring.c similarity index 90% rename from loader/src/x64/map_mk_debug_ring.c rename to loader/src/map_mk_debug_ring.c index e613e9f2..f63bfe86 100644 --- a/loader/src/x64/map_mk_debug_ring.c +++ b/loader/src/map_mk_debug_ring.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include /** * @@ -39,16 +39,16 @@ * * @param debug_ring a pointer to a debug_ring_t that stores the debug_ring * being mapped - * @param pml4t the root page table to map the debug_ring into + * @param rpt the root page table to map the debug_ring into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_mk_debug_ring(struct debug_ring_t const *const debug_ring, struct pml4t_t *const pml4t) +map_mk_debug_ring(struct debug_ring_t const *const debug_ring, root_page_table_t *const rpt) { uint64_t off = ((uint64_t)0); for (; off < HYPERVISOR_DEBUG_RING_SIZE; off += HYPERVISOR_PAGE_SIZE) { - if (map_4k_page_rw(((uint8_t *)debug_ring) + off, ((uint64_t)0), pml4t)) { + if (map_4k_page_rw(((uint8_t *)debug_ring) + off, ((uint64_t)0), rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/map_mk_elf_file.c b/loader/src/map_mk_elf_file.c similarity index 88% rename from loader/src/x64/map_mk_elf_file.c rename to loader/src/map_mk_elf_file.c index 410dcc93..4a3f52dd 100644 --- a/loader/src/x64/map_mk_elf_file.c +++ b/loader/src/map_mk_elf_file.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include /** @@ -39,16 +39,16 @@ * * @param file a pointer to a span_t that stores the ELF file * being mapped - * @param pml4t the root page table to map the ELF file into + * @param rpt the root page table to map the ELF file into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_mk_elf_file(struct span_t const *const file, struct pml4t_t *const pml4t) +map_mk_elf_file(struct span_t const *const file, root_page_table_t *const rpt) { uint64_t off; for (off = ((uint64_t)0); off < file->size; off += HYPERVISOR_PAGE_SIZE) { - if (map_4k_page_rw(file->addr + off, ((uint64_t)0), pml4t)) { + if (map_4k_page_rw(file->addr + off, ((uint64_t)0), rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/map_mk_elf_segments.c b/loader/src/map_mk_elf_segments.c similarity index 88% rename from loader/src/x64/map_mk_elf_segments.c rename to loader/src/map_mk_elf_segments.c index 32b672fc..377335c6 100644 --- a/loader/src/x64/map_mk_elf_segments.c +++ b/loader/src/map_mk_elf_segments.c @@ -24,13 +24,12 @@ * SOFTWARE. */ -#include #include #include #include #include #include -#include +#include /** * @@ -40,11 +39,11 @@ * * @param segments a pointer to a elf_segment_t that stores the ELF * segment being mapped - * @param pml4t the root page table to map the ELF segment into + * @param rpt the root page table to map the ELF segment into * @return 0 on success, LOADER_FAILURE on failure. */ static int64_t -map_mk_elf_segment(struct elf_segment_t const *const segment, struct pml4t_t *const pml4t) +map_mk_elf_segment(struct elf_segment_t const *const segment, root_page_table_t *const rpt) { uint64_t off; @@ -55,7 +54,7 @@ map_mk_elf_segment(struct elf_segment_t const *const segment, struct pml4t_t *co return LOADER_FAILURE; } - if (map_4k_page(segment->virt + off, phys, segment->flags, pml4t)) { + if (map_4k_page(segment->virt + off, phys, segment->flags, rpt)) { bferror("map_4k_page failed"); return LOADER_FAILURE; } @@ -72,16 +71,16 @@ map_mk_elf_segment(struct elf_segment_t const *const segment, struct pml4t_t *co * * @param segments a pointer to a elf_segment_t array that stores the ELF * segments being mapped - * @param pml4t the root page table to map the ELF segments into + * @param rpt the root page table to map the ELF segments into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_mk_elf_segments(struct elf_segment_t const *const segments, struct pml4t_t *const pml4t) +map_mk_elf_segments(struct elf_segment_t const *const segments, root_page_table_t *const rpt) { uint64_t idx; for (idx = ((uint64_t)0); idx < HYPERVISOR_MAX_SEGMENTS; ++idx) { - if (map_mk_elf_segment(&segments[idx], pml4t)) { + if (map_mk_elf_segment(&segments[idx], rpt)) { bferror("map_mk_elf_segment failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/map_mk_huge_pool.c b/loader/src/map_mk_huge_pool.c similarity index 88% rename from loader/src/x64/map_mk_huge_pool.c rename to loader/src/map_mk_huge_pool.c index 0159cc8c..d37ae164 100644 --- a/loader/src/x64/map_mk_huge_pool.c +++ b/loader/src/map_mk_huge_pool.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include /** * @@ -39,15 +39,15 @@ * * @param huge_pool a pointer to a mutable_span_t that stores the huge pool * being mapped - * @param pml4t the root page table to map the huge pool into + * @param rpt the root page table to map the huge pool into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_mk_huge_pool(struct mutable_span_t const *const huge_pool, struct pml4t_t *const pml4t) +map_mk_huge_pool(struct mutable_span_t const *const huge_pool, root_page_table_t *const rpt) { uint64_t off; uint64_t base_phys; - uint64_t const base_virt = HYPERVISOR_DIRECT_MAP_ADDR; + uint64_t const base_virt = HYPERVISOR_MK_HUGE_POOL_ADDR; base_phys = platform_virt_to_phys(huge_pool->addr); if (((uint64_t)0) == base_phys) { @@ -68,7 +68,7 @@ map_mk_huge_pool(struct mutable_span_t const *const huge_pool, struct pml4t_t *c return LOADER_FAILURE; } - if (map_4k_page_rw((void *)(base_virt + phys), phys, pml4t)) { + if (map_4k_page_rw((void *)(base_virt + phys), phys, rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/map_mk_page_pool.c b/loader/src/map_mk_page_pool.c similarity index 90% rename from loader/src/x64/map_mk_page_pool.c rename to loader/src/map_mk_page_pool.c index c6538e2f..e26900f7 100644 --- a/loader/src/x64/map_mk_page_pool.c +++ b/loader/src/map_mk_page_pool.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include /** * @@ -51,15 +51,15 @@ * * @param page_pool a pointer to a mutable_span_t that stores the page pool * being mapped - * @param pml4t the root page table to map the page pool into + * @param rpt the root page table to map the page pool into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_mk_page_pool(struct mutable_span_t const *const page_pool, struct pml4t_t *const pml4t) +map_mk_page_pool(struct mutable_span_t const *const page_pool, root_page_table_t *const rpt) { uint64_t off; uint64_t *prev = ((void *)0); - uint64_t const base_virt = HYPERVISOR_DIRECT_MAP_ADDR; + uint64_t const base_virt = HYPERVISOR_MK_PAGE_POOL_ADDR; for (off = ((uint64_t)0); off < page_pool->size; off += HYPERVISOR_PAGE_SIZE) { @@ -69,7 +69,7 @@ map_mk_page_pool(struct mutable_span_t const *const page_pool, struct pml4t_t *c return LOADER_FAILURE; } - if (map_4k_page_rw((void *)(base_virt + phys), phys, pml4t)) { + if (map_4k_page_rw((void *)(base_virt + phys), phys, rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/map_mk_stack.c b/loader/src/map_mk_stack.c similarity index 92% rename from loader/src/x64/map_mk_stack.c rename to loader/src/map_mk_stack.c index dc15e309..d4e61661 100644 --- a/loader/src/x64/map_mk_stack.c +++ b/loader/src/map_mk_stack.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include /** @@ -41,11 +41,11 @@ * being mapped * @param virt provide the virtual address that the stack * should be mapped to. - * @param pml4t the root page table to map the stack into + * @param rpt the root page table to map the stack into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_mk_stack(struct span_t const *const stack, uint64_t const virt, struct pml4t_t *const pml4t) +map_mk_stack(struct span_t const *const stack, uint64_t const virt, root_page_table_t *const rpt) { uint64_t off; @@ -56,7 +56,7 @@ map_mk_stack(struct span_t const *const stack, uint64_t const virt, struct pml4t return LOADER_FAILURE; } - if (map_4k_page_rw((void *)(virt + off), phys, pml4t)) { + if (map_4k_page_rw((void *)(virt + off), phys, rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } diff --git a/loader/src/serial_write.c b/loader/src/serial_write.c new file mode 100644 index 00000000..5271d983 --- /dev/null +++ b/loader/src/serial_write.c @@ -0,0 +1,46 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +/** + * + * @brief Writes a string to the serial. Note that you must initialize + * the serial before you can use it. + * + * + * @param str the string to write to the serial. + */ +void +serial_write(char const *const str) +{ + uint64_t i; + + for (i = 0; str[i] != '\0'; ++i) { + serial_write_c(str[i]); + } +} diff --git a/loader/src/start_vmm.c b/loader/src/start_vmm.c index 9d05abcf..4d649b12 100644 --- a/loader/src/start_vmm.c +++ b/loader/src/start_vmm.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -65,7 +66,6 @@ #include #include #include -#include static int64_t alloc_and_start_the_vmm(struct start_vmm_args_t const *const args) diff --git a/loader/src/start_vmm_per_cpu.c b/loader/src/start_vmm_per_cpu.c index f206d695..0db493cf 100644 --- a/loader/src/start_vmm_per_cpu.c +++ b/loader/src/start_vmm_per_cpu.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -79,11 +81,26 @@ start_vmm_per_cpu(uint32_t const cpu) uint64_t mk_stack_offs; uint64_t mk_stack_virt; - if (((uint64_t)cpu) >= HYPERVISOR_MAX_VPS_PER_VM) { + if (((uint64_t)cpu) >= HYPERVISOR_MAX_PPS) { bferror("cpu out of range"); return LOADER_FAILURE; } + if (CPU_STATUS_STOPPED != g_cpu_status[cpu]) { + bferror("cannot start cpu that is already running/corrupt"); + return LOADER_FAILURE; + } + + if (platform_arch_init()) { + bferror("platform_arch_init failed"); + return LOADER_FAILURE; + } + + if (check_cpu_configuration()) { + bferror("check_cpu_configuration failed"); + return LOADER_FAILURE; + } + mk_stack_offs = (HYPERVISOR_MK_STACK_SIZE + HYPERVISOR_PAGE_SIZE) * cpu; mk_stack_virt = (g_mk_stack_virt + mk_stack_offs); @@ -130,14 +147,14 @@ start_vmm_per_cpu(uint32_t const cpu) goto map_mk_args_failed; } - g_mk_args[cpu]->pp = ((uint16_t)cpu); + g_mk_args[cpu]->ppid = ((uint16_t)cpu); /** - * NOTE: - * - We cannot ask for the total number of CPUs on any AP from UEFI, so - * we only do this for the BSP, and then use the BSP value to get the - * total CPU count from that point on. - */ + * NOTE: + * - We cannot ask for the total number of CPUs on any AP from UEFI, so + * we only do this for the BSP, and then use the BSP value to get the + * total CPU count from that point on. + */ if (((uint64_t)0) == cpu) { g_mk_args[cpu]->online_pps = ((uint16_t)platform_num_online_cpus()); @@ -158,17 +175,16 @@ start_vmm_per_cpu(uint32_t const cpu) g_mk_args[cpu]->rpt = g_mk_root_page_table; g_mk_args[cpu]->rpt_phys = platform_virt_to_phys(g_mk_root_page_table); - ret = get_mk_page_pool_addr(&g_mk_page_pool, HYPERVISOR_DIRECT_MAP_ADDR, &addr); + ret = get_mk_page_pool_addr(&g_mk_page_pool, HYPERVISOR_MK_PAGE_POOL_ADDR, &addr); if (ret) { bferror("get_mk_page_pool_addr failed"); goto get_mk_page_pool_addr_failed; } g_mk_args[cpu]->page_pool.addr = addr; - g_mk_args[cpu]->page_pool.size = g_mk_page_pool.size; - g_mk_args[cpu]->page_pool_base_virt = HYPERVISOR_DIRECT_MAP_ADDR; + g_mk_args[cpu]->page_pool.size = g_mk_page_pool.size / HYPERVISOR_PAGE_SIZE; - ret = get_mk_huge_pool_addr(&g_mk_huge_pool, HYPERVISOR_DIRECT_MAP_ADDR, &addr); + ret = get_mk_huge_pool_addr(&g_mk_huge_pool, HYPERVISOR_MK_HUGE_POOL_ADDR, &addr); if (ret) { bferror("get_mk_huge_pool_addr failed"); goto get_mk_huge_pool_addr_failed; @@ -176,7 +192,6 @@ start_vmm_per_cpu(uint32_t const cpu) g_mk_args[cpu]->huge_pool.addr = addr; g_mk_args[cpu]->huge_pool.size = g_mk_huge_pool.size; - g_mk_args[cpu]->huge_pool_base_virt = HYPERVISOR_DIRECT_MAP_ADDR; #ifdef DEBUG_LOADER dump_mk_stack(&g_mk_stack[cpu], cpu); @@ -186,11 +201,13 @@ start_vmm_per_cpu(uint32_t const cpu) #endif if (demote(g_mk_args[cpu], g_mk_state[cpu], g_root_vp_state[cpu])) { + platform_dump_vmm(); bferror("demote failed"); goto demote_failed; } send_command_report_on(); + g_cpu_status[cpu] = CPU_STATUS_RUNNING; return LOADER_SUCCESS; demote_failed: diff --git a/loader/src/stop_and_free_the_vmm.c b/loader/src/stop_and_free_the_vmm.c index 264d7817..b94046fd 100644 --- a/loader/src/stop_and_free_the_vmm.c +++ b/loader/src/stop_and_free_the_vmm.c @@ -37,10 +37,10 @@ #include #include #include +#include #include #include #include -#include /** * diff --git a/loader/src/stop_vmm_per_cpu.c b/loader/src/stop_vmm_per_cpu.c index f5d035a1..2eedeb3b 100644 --- a/loader/src/stop_vmm_per_cpu.c +++ b/loader/src/stop_vmm_per_cpu.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -52,15 +53,25 @@ int64_t stop_vmm_per_cpu(uint32_t const cpu) { - if (((uint64_t)cpu) >= HYPERVISOR_MAX_VPS_PER_VM) { + if (((uint64_t)cpu) >= HYPERVISOR_MAX_PPS) { bferror("cpu out of range"); return LOADER_FAILURE; } + if (CPU_STATUS_STOPPED == g_cpu_status[cpu]) { + return LOADER_SUCCESS; + } + + if (CPU_STATUS_CORRUPT == g_cpu_status[cpu]) { + bferror("Unable to stop, previous CPU stopped in a corrupt state"); + return LOADER_FAILURE; + } + send_command_report_off(); if (send_command_stop()) { bferror("send_command_stop failed"); + g_cpu_status[cpu] = CPU_STATUS_CORRUPT; return LOADER_FAILURE; } @@ -69,5 +80,6 @@ stop_vmm_per_cpu(uint32_t const cpu) free_mk_state(&g_mk_state[cpu]); free_mk_stack(&g_mk_stack[cpu]); + g_cpu_status[cpu] = CPU_STATUS_STOPPED; return LOADER_SUCCESS; } diff --git a/loader/src/x64/alloc_and_copy_mk_code_aliases.c b/loader/src/x64/alloc_and_copy_mk_code_aliases.c index 858f1a85..c691b21c 100644 --- a/loader/src/x64/alloc_and_copy_mk_code_aliases.c +++ b/loader/src/x64/alloc_and_copy_mk_code_aliases.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #ifdef _MSC_VER @@ -122,6 +124,18 @@ alloc_and_copy_mk_code_aliases(struct code_aliases_t *const a) goto platform_alloc_esr_pf_failed; } + a->serial_write_c = platform_alloc(HYPERVISOR_PAGE_SIZE); + if (((void *)0) == a->serial_write_c) { + bferror("platform_alloc failed"); + goto platform_alloc_esr_pf_failed; + } + + a->serial_write_hex = platform_alloc(HYPERVISOR_PAGE_SIZE); + if (((void *)0) == a->serial_write_hex) { + bferror("platform_alloc failed"); + goto platform_alloc_esr_pf_failed; + } + platform_memcpy(a->demote, demote, HYPERVISOR_PAGE_SIZE); platform_memcpy(a->promote, promote, HYPERVISOR_PAGE_SIZE); platform_memcpy(a->esr_default, esr_default, HYPERVISOR_PAGE_SIZE); @@ -129,6 +143,8 @@ alloc_and_copy_mk_code_aliases(struct code_aliases_t *const a) platform_memcpy(a->esr_gpf, esr_gpf, HYPERVISOR_PAGE_SIZE); platform_memcpy(a->esr_nmi, esr_nmi, HYPERVISOR_PAGE_SIZE); platform_memcpy(a->esr_pf, esr_pf, HYPERVISOR_PAGE_SIZE); + platform_memcpy(a->serial_write_c, serial_write_c, HYPERVISOR_PAGE_SIZE); + platform_memcpy(a->serial_write_hex, serial_write_hex, HYPERVISOR_PAGE_SIZE); return LOADER_SUCCESS; diff --git a/loader/src/x64/alloc_and_copy_mk_state.c b/loader/src/x64/alloc_and_copy_mk_state.c index 277264a0..2ae418dd 100644 --- a/loader/src/x64/alloc_and_copy_mk_state.c +++ b/loader/src/x64/alloc_and_copy_mk_state.c @@ -24,7 +24,7 @@ * SOFTWARE. */ -#include +#include #include #include #include @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include @@ -48,17 +48,23 @@ #include #include -/** @brief defines the default value of rflags */ -#define DEFAULT_RFLAGS ((uint64_t)0x2) +/** @brief defines the default value of rflags */ +#define DEFAULT_RFLAGS ((uint64_t)0x40002) -/** @brief defines the default value of CR0 */ +/** @brief defines the default value of CR0 */ #define DEFAULT_CR0 ((uint64_t)0x80050033) -/** @brief defines the default value of CR4 */ +/** @brief defines the default value of CR4 */ #define DEFAULT_CR4 ((uint64_t)0x003000E0) -/** @brief defines the MSR_IA32_EFER MSR */ +/** @brief defines the default value of CR0 bits that must be off */ +#define DEFAULT_CR0_OFF ((uint64_t)0xFFFFFFFFFFFFFFFF) +/** @brief defines the default value of CR4 bits that must be off */ +// #define DEFAULT_CR4_OFF ((uint64_t)0xFFFFFFFFFF9FFFFF) +#define DEFAULT_CR4_OFF ((uint64_t)0xFFFFFFFFFFFFFFFF) + +/** @brief defines the MSR_IA32_EFER MSR */ #define MSR_IA32_EFER ((uint32_t)0xC0000080) -/** @brief defines the default value of EFER */ +/** @brief defines the default value of EFER */ #define DEFAULT_EFER ((uint64_t)0x00000D01) /** @brief defines the microkernel's CS selector */ @@ -153,13 +159,13 @@ #define ESR_ATTRIB ((uint16_t)0x8E01) /** @brief defines the PAT MSR used by the microkernel */ -#define MK_MSR_IA32_PAT ((uint64_t)0x0606060606060606) +#define MK_MSR_IA32_PAT ((uint64_t)0x0000000600000006) /** @brief defines the STAR MSR used by the microkernel */ #define MK_MSR_IA32_STAR ((uint64_t)0x001B001000000000) /** @brief defines the FMASK MSR used by the microkernel */ -#define MK_MSR_IA32_FMASK ((uint64_t)0xFFFFFFFFFFFFFFFD) +#define MK_MSR_IA32_FMASK ((uint64_t)0xFFFFFFFFFFFBFFFD) /** * @@ -167,7 +173,7 @@ * microkernel. * * - * @param pml4t the mkcrokernel's root page table + * @param rpt the mkcrokernel's root page table * @param mk_elf_file the microkernel's ELF file * @param mk_stack the microkernel's stack * @param mk_stack_virt the microkernel's virtual address of the stack @@ -176,7 +182,7 @@ */ int64_t alloc_and_copy_mk_state( - struct pml4t_t const *const pml4t, + root_page_table_t const *const rpt, struct span_t const *const mk_elf_file, struct span_t const *const mk_stack, uint64_t const mk_stack_virt, @@ -278,11 +284,14 @@ alloc_and_copy_mk_state( * Windows and Linux use these same values, but UEFI doesn't. UEFI * isn't going to generate an NMI, so we should be good during demote, * but in general, this is not safe. - * - Note that UEFI so has CS and SS flipped. This means you cannot use + * - Note that UEFI has CS and SS flipped. This means you cannot use * them in the microkernel as it needs fast syscalls which have the * offsets hardcoded in hardware. * - UEFI also has the issue that TR is never set (it is left to 0), * which means promote will fail if you attempt to set it back to 0. + * - This is not a trivial and should only be fixed if Windows/Linux + * stop using the same CS/SS, or another operating system is added to + * the support list that doesn't have the same CS/SS. */ (*state)->cs_selector = MK_CS_SELECTOR; @@ -639,21 +648,15 @@ alloc_and_copy_mk_state( /* Control Registers */ /**************************************************************************/ - (*state)->cr0 = intrinsic_scr0() | DEFAULT_CR0; - (*state)->cr3 = platform_virt_to_phys(pml4t); - (*state)->cr4 = intrinsic_scr4() | DEFAULT_CR4; + (*state)->cr0 = (intrinsic_scr0() | DEFAULT_CR0) & DEFAULT_CR0_OFF; + (*state)->cr3 = platform_virt_to_phys(rpt); + (*state)->cr4 = (intrinsic_scr4() | DEFAULT_CR4) & DEFAULT_CR4_OFF; if (((uint64_t)0) == (*state)->cr3) { bferror("platform_virt_to_phys failed"); goto platform_virt_to_phys_cr3_failed; } - /** - * TODO: - * - Do a complete analysis of CR0 and CR4 and turn on features if we - * can detect support for them. This includes XSAVE. - */ - /**************************************************************************/ /* MSRs */ /**************************************************************************/ diff --git a/loader/src/x64/alloc_mk_root_page_table.c b/loader/src/x64/alloc_mk_root_page_table.c index cd1eddc6..1a6220fa 100644 --- a/loader/src/x64/alloc_mk_root_page_table.c +++ b/loader/src/x64/alloc_mk_root_page_table.c @@ -25,9 +25,11 @@ */ #include +#include #include #include #include +#include #include /** @@ -35,19 +37,25 @@ * @brief This function allocates the root page table * * - * @param pml4t where to return the resulting root page table + * @param rpt where to return the resulting root page table * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -alloc_mk_root_page_table(struct pml4t_t **const pml4t) +alloc_mk_root_page_table(root_page_table_t **const rpt) { - *pml4t = (struct pml4t_t *)platform_alloc(sizeof(struct pml4t_t)); - if (((void *)0) == *pml4t) { + uint64_t i; + + *rpt = (root_page_table_t *)platform_alloc(sizeof(root_page_table_t)); + if (((void *)0) == *rpt) { bferror("platform_alloc failed"); return LOADER_FAILURE; } - if (map_4k_page_rw(*pml4t, ((uint64_t)0), *pml4t)) { + for (i = 0; i < LOADER_NUM_PML4T_ENTRIES; ++i) { + flush_cache(&((*rpt)->entires[i])); + } + + if (map_4k_page_rw(*rpt, ((uint64_t)0), *rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/alloc_pdpt.c b/loader/src/x64/alloc_pdpt.c index 2188eddf..569365c9 100644 --- a/loader/src/x64/alloc_pdpt.c +++ b/loader/src/x64/alloc_pdpt.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -47,6 +48,7 @@ struct pdpt_t * alloc_pdpt(struct pml4t_t *const pml4t, uint64_t const virt) { + uint64_t i; uint64_t phys; struct pdpt_t *pdpt; struct pml4te_t *pml4te; @@ -63,6 +65,10 @@ alloc_pdpt(struct pml4t_t *const pml4t, uint64_t const virt) goto platform_alloc_pdpt_failed; } + for (i = 0; i < LOADER_NUM_PDPT_ENTRIES; ++i) { + flush_cache(&(pdpt->entires[i])); + } + phys = platform_virt_to_phys(pdpt); if (((uint64_t)0) == phys) { bferror("platform_virt_to_phys_pdpt failed"); @@ -74,6 +80,7 @@ alloc_pdpt(struct pml4t_t *const pml4t, uint64_t const virt) pml4te->p = ((uint64_t)1); pml4te->rw = ((uint64_t)1); + flush_cache(pml4te); return pdpt; platform_virt_to_phys_pdpt_failed: diff --git a/loader/src/x64/alloc_pdt.c b/loader/src/x64/alloc_pdt.c index 76b644dc..25c0829f 100644 --- a/loader/src/x64/alloc_pdt.c +++ b/loader/src/x64/alloc_pdt.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -47,6 +48,7 @@ struct pdt_t * alloc_pdt(struct pdpt_t *const pdpt, uint64_t const virt) { + uint64_t i; uint64_t phys; struct pdt_t *pdt; struct pdpte_t *pdpte; @@ -63,6 +65,10 @@ alloc_pdt(struct pdpt_t *const pdpt, uint64_t const virt) goto platform_alloc_pdt_failed; } + for (i = 0; i < LOADER_NUM_PDT_ENTRIES; ++i) { + flush_cache(&(pdt->entires[i])); + } + phys = platform_virt_to_phys(pdt); if (((uint64_t)0) == phys) { bferror("platform_virt_to_phys_pdt failed"); @@ -74,6 +80,7 @@ alloc_pdt(struct pdpt_t *const pdpt, uint64_t const virt) pdpte->p = ((uint64_t)1); pdpte->rw = ((uint64_t)1); + flush_cache(pdpte); return pdt; platform_virt_to_phys_pdt_failed: diff --git a/loader/src/x64/alloc_pt.c b/loader/src/x64/alloc_pt.c index 78a1da8a..7813a186 100644 --- a/loader/src/x64/alloc_pt.c +++ b/loader/src/x64/alloc_pt.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -47,6 +48,7 @@ struct pt_t * alloc_pt(struct pdt_t *const pdt, uint64_t const virt) { + uint64_t i; uint64_t phys; struct pt_t *pt; struct pdte_t *pdte; @@ -63,6 +65,10 @@ alloc_pt(struct pdt_t *const pdt, uint64_t const virt) goto platform_alloc_pt_failed; } + for (i = 0; i < LOADER_NUM_PT_ENTRIES; ++i) { + flush_cache(&(pt->entires[i])); + } + phys = platform_virt_to_phys(pt); if (((uint64_t)0) == phys) { bferror("platform_virt_to_phys_pt failed"); @@ -74,6 +80,7 @@ alloc_pt(struct pdt_t *const pdt, uint64_t const virt) pdte->p = ((uint64_t)1); pdte->rw = ((uint64_t)1); + flush_cache(pdte); return pt; platform_virt_to_phys_pt_failed: diff --git a/loader/src/x64/amd/check_for_hve_support.c b/loader/src/x64/amd/check_cpu_configuration.c similarity index 80% rename from loader/src/x64/amd/check_for_hve_support.c rename to loader/src/x64/amd/check_cpu_configuration.c index a8bedc70..c66d1069 100644 --- a/loader/src/x64/amd/check_for_hve_support.c +++ b/loader/src/x64/amd/check_cpu_configuration.c @@ -42,13 +42,6 @@ /** @brief defines the CPUID leaf for feature information */ #define CPUID_LEAF_FEATURE ((uint32_t)0x1) -/** @brief defines the CPUID leaf for structured extended feature information */ -#define CPUID_LEAF_STRUCT_EXT_FEATURE ((uint32_t)0x7) -/** @brief define the CPUID feature bit for SMEP */ -#define CPUID_STRUCT_EXT_FEATURE_EBX_SMEP (((uint32_t)1) << ((uint32_t)7)) -/** @brief define the CPUID feature bit for SMAP */ -#define CPUID_STRUCT_EXT_FEATURE_EBX_SMAP (((uint32_t)1) << ((uint32_t)20)) - /** @brief defines the CPUID leaf for feature information */ #define CPUID_LEAF_EXT_FEATURE ((uint32_t)0x80000001) /** @brief define the CPUID feature bit for VMX */ @@ -178,46 +171,14 @@ check_the_configuration_of_efer(void) /** * - * @brief Check if the cpu supports needed SMEP/SMAP. - * - * - * @return Returns 0 on success, LOADER_FAILURE otherwise. - */ -static inline int64_t -check_for_smep_smap(void) -{ - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - - eax = CPUID_LEAF_STRUCT_EXT_FEATURE; - ecx = 0U; - intrinsic_cpuid(&eax, &ebx, &ecx, &edx); - - if ((ebx & CPUID_STRUCT_EXT_FEATURE_EBX_SMEP) == 0U) { - bferror_x32("cpu does not support SMEP", ebx); - return LOADER_FAILURE; - } - - if ((ebx & CPUID_STRUCT_EXT_FEATURE_EBX_SMAP) == 0U) { - bferror_x32("cpu does not support SMAP", ebx); - return LOADER_FAILURE; - } - - return LOADER_SUCCESS; -} - -/** - * - * @brief This function checks to see if AMD SVM support is available on - * the currently running CPU + * @brief This function checks to see if the CPU is supported as well as + * it's system configuration. * * * @return Returns 0 on success */ int64_t -check_for_hve_support(void) +check_cpu_configuration(void) { if (check_for_amd()) { bferror("check_for_amd failed"); @@ -239,10 +200,5 @@ check_for_hve_support(void) return LOADER_FAILURE; } - if (check_for_smep_smap()) { - bferror("check_for_smep_smap failed"); - return LOADER_FAILURE; - } - return LOADER_SUCCESS; } diff --git a/loader/src/x64/amd/disable_hve.c b/loader/src/x64/amd/disable_hve.c index 01bac41e..86f45ddf 100644 --- a/loader/src/x64/amd/disable_hve.c +++ b/loader/src/x64/amd/disable_hve.c @@ -39,7 +39,7 @@ /** * - * @brief Disables AMD SVE + * @brief Disables Hardware Virtualization Extensions */ void disable_hve(void) diff --git a/loader/src/x64/amd/enable_hve.c b/loader/src/x64/amd/enable_hve.c index bece3623..31511428 100644 --- a/loader/src/x64/amd/enable_hve.c +++ b/loader/src/x64/amd/enable_hve.c @@ -41,7 +41,7 @@ /** * - * @brief Enables AMD SVE + * @brief Enables Hardware Virtualization Extensions * * * @param state the mk state save containing the HVE page diff --git a/loader/src/x64/dump_mk_code_aliases.c b/loader/src/x64/dump_mk_code_aliases.c index d7845796..638ebd3e 100644 --- a/loader/src/x64/dump_mk_code_aliases.c +++ b/loader/src/x64/dump_mk_code_aliases.c @@ -34,11 +34,15 @@ * * * @param a the code_aliases_t to output - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_code_aliases(struct code_aliases_t *const a) { + if (((void *)0) == a) { + bferror("a is NULL"); + return; + } + bfdebug("mk code aliases:"); bfdebug_ptr(" - demote", a->demote); bfdebug_ptr(" - promote", a->promote); @@ -47,4 +51,6 @@ dump_mk_code_aliases(struct code_aliases_t *const a) bfdebug_ptr(" - esr_gpf", a->esr_gpf); bfdebug_ptr(" - esr_nmi", a->esr_nmi); bfdebug_ptr(" - esr_pf", a->esr_pf); + bfdebug_ptr(" - serial_write_c", a->serial_write_c); + bfdebug_ptr(" - serial_write_hex", a->serial_write_hex); } diff --git a/loader/src/x64/dump_mk_state.c b/loader/src/x64/dump_mk_state.c index 9da0d6eb..78f01d85 100644 --- a/loader/src/x64/dump_mk_state.c +++ b/loader/src/x64/dump_mk_state.c @@ -35,11 +35,20 @@ * * @param state the mk state to output * @param cpu the CPU that this mk state belongs to - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_mk_state(struct state_save_t *const state, uint32_t const cpu) { + if (((void *)0) == state) { + bferror("state is NULL"); + return; + } + + if (((void *)0) == state->tss) { + bferror("state->tss is NULL"); + return; + } + bfdebug_d32("mk state on cpu", cpu); bfdebug_ptr(" - virt", state); @@ -65,6 +74,7 @@ dump_mk_state(struct state_save_t *const state, uint32_t const cpu) bfdebug_ptr(" - tss", state->tss); bfdebug_ptr(" - ist", state->ist); + bfdebug_x64(" - tss->rsp0", state->tss->rsp0); bfdebug_x64(" - tss->rsp1", state->tss->rsp1); bfdebug_x64(" - tss->rsp2", state->tss->rsp2); diff --git a/loader/src/x64/dump_root_vp_state.c b/loader/src/x64/dump_root_vp_state.c index 6d56c075..877a46bb 100644 --- a/loader/src/x64/dump_root_vp_state.c +++ b/loader/src/x64/dump_root_vp_state.c @@ -35,11 +35,15 @@ * * @param state the root vp state to output * @param cpu the CPU that this root vp state belongs to - * @return 0 on success, LOADER_FAILURE on failure. */ void dump_root_vp_state(struct state_save_t *const state, uint32_t const cpu) { + if (((void *)0) == state) { + bferror("state is NULL"); + return; + } + bfdebug_d32("root vp state on cpu", cpu); bfdebug_ptr(" - virt", state); diff --git a/loader/src/x64/free_mk_code_aliases.c b/loader/src/x64/free_mk_code_aliases.c index 166b403c..aa9a5075 100644 --- a/loader/src/x64/free_mk_code_aliases.c +++ b/loader/src/x64/free_mk_code_aliases.c @@ -47,5 +47,7 @@ free_mk_code_aliases(struct code_aliases_t *const a) platform_free(a->esr_gpf, HYPERVISOR_PAGE_SIZE); platform_free(a->esr_nmi, HYPERVISOR_PAGE_SIZE); platform_free(a->esr_pf, HYPERVISOR_PAGE_SIZE); + platform_free(a->serial_write_c, HYPERVISOR_PAGE_SIZE); + platform_free(a->serial_write_hex, HYPERVISOR_PAGE_SIZE); platform_memset(a, 0, sizeof(struct code_aliases_t)); } diff --git a/loader/src/x64/free_mk_root_page_table.c b/loader/src/x64/free_mk_root_page_table.c index 1810aed5..407e2c05 100644 --- a/loader/src/x64/free_mk_root_page_table.c +++ b/loader/src/x64/free_mk_root_page_table.c @@ -24,30 +24,28 @@ * SOFTWARE. */ -#include -#include #include #include -#include +#include #include /** * - * @brief Releases a previously allocated pml4t_t that was allocated + * @brief Releases a previously allocated root_page_table_t that was allocated * using the alloc_mk_root_page_table function. * * - * @param pml4t the pml4t_t to free. + * @param rpt the root_page_table_t to free. */ void -free_mk_root_page_table(struct pml4t_t **const pml4t) +free_mk_root_page_table(root_page_table_t **const rpt) { - if (((void *)0) == *pml4t) { + if (((void *)0) == *rpt) { return; } - free_pml4t(*pml4t); + free_pml4t(*rpt); - platform_free(*pml4t, sizeof(struct pml4t_t)); - *pml4t = ((void *)0); + platform_free(*rpt, sizeof(root_page_table_t)); + *rpt = ((void *)0); } diff --git a/loader/src/x64/intel/check_for_hve_support.c b/loader/src/x64/intel/check_cpu_configuration.c similarity index 77% rename from loader/src/x64/intel/check_for_hve_support.c rename to loader/src/x64/intel/check_cpu_configuration.c index 868c5680..b7072825 100644 --- a/loader/src/x64/intel/check_for_hve_support.c +++ b/loader/src/x64/intel/check_cpu_configuration.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include /** @brief defines the CPUID leaf for vendor information */ @@ -44,13 +46,6 @@ /** @brief define the CPUID feature bit for VMX */ #define CPUID_FEATURE_ECX_VMX (((uint32_t)1) << ((uint32_t)5)) -/** @brief defines the CPUID leaf for structured extended feature information */ -#define CPUID_LEAF_STRUCT_EXT_FEATURE ((uint32_t)0x7) -/** @brief define the CPUID feature bit for SMEP */ -#define CPUID_STRUCT_EXT_FEATURE_EBX_SMEP (((uint32_t)1) << ((uint32_t)7)) -/** @brief define the CPUID feature bit for SMAP */ -#define CPUID_STRUCT_EXT_FEATURE_EBX_SMAP (((uint32_t)1) << ((uint32_t)20)) - /** @brief defines the MSR address for feature information */ #define MSR_IA32_FEATURE_CTRL ((uint32_t)0x3A) /** @brief defines the MSR feature VMX enabled bit */ @@ -74,6 +69,18 @@ /** @brief defines the EFER_LME MSR field */ #define EFER_LME (((uint64_t)1) << ((uint64_t)8)) +/** @brief defines the MSR_VMX_CR0_FIXED0 MSR */ +#define MSR_VMX_CR0_FIXED0 ((uint32_t)0x00000486) +/** @brief defines the MSR_VMX_CR0_FIXED1 MSR */ +#define MSR_VMX_CR0_FIXED1 ((uint32_t)0x00000487) +/** @brief defines the MSR_VMX_CR4_FIXED0 MSR */ +#define MSR_VMX_CR4_FIXED0 ((uint32_t)0x00000488) +/** @brief defines the MSR_VMX_CR4_FIXED1 MSR */ +#define MSR_VMX_CR4_FIXED1 ((uint32_t)0x00000489) + +/** @brief defines the VME CR4 field */ +#define CR4_VMXE (((uint64_t)1) << ((uint64_t)13)) + /** * * @brief Check we're running on an Intel processor. @@ -216,30 +223,24 @@ check_the_configuration_of_efer(void) /** * - * @brief Check if the cpu supports needed SMEP/SMAP. + * @brief Check the configuration CR0 * * * @return Returns 0 on success, LOADER_FAILURE otherwise. */ static inline int64_t -check_for_smep_smap(void) +check_cr0(void) { - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; + uint64_t cr0 = intrinsic_scr0(); + uint64_t ia32_vmx_cr0_fixed0 = intrinsic_rdmsr(MSR_VMX_CR0_FIXED0); + uint64_t ia32_vmx_cr0_fixed1 = intrinsic_rdmsr(MSR_VMX_CR0_FIXED1); - eax = CPUID_LEAF_STRUCT_EXT_FEATURE; - ecx = 0U; - intrinsic_cpuid(&eax, &ebx, &ecx, &edx); + if (0 != ((~cr0 & ia32_vmx_cr0_fixed0) | (cr0 & ~ia32_vmx_cr0_fixed1))) { + bferror("cr0 is not properly configured"); + bferror_x64(" - cr0", cr0); + bferror_x64(" - ia32_vmx_cr0_fixed0", ia32_vmx_cr0_fixed0); + bferror_x64(" - ia32_vmx_cr0_fixed1", ia32_vmx_cr0_fixed1); - if ((ebx & CPUID_STRUCT_EXT_FEATURE_EBX_SMEP) == 0U) { - bferror_x32("cpu does not support SMEP", ebx); - return LOADER_FAILURE; - } - - if ((ebx & CPUID_STRUCT_EXT_FEATURE_EBX_SMAP) == 0U) { - bferror_x32("cpu does not support SMAP", ebx); return LOADER_FAILURE; } @@ -248,14 +249,40 @@ check_for_smep_smap(void) /** * - * @brief This function checks to see if Intel VT-x support is available on - * the currently running CPU + * @brief Check the configuration CR4 + * + * + * @return Returns 0 on success, LOADER_FAILURE otherwise. + */ +static inline int64_t +check_cr4(void) +{ + uint64_t cr4 = intrinsic_scr4() | CR4_VMXE; + uint64_t ia32_vmx_cr4_fixed0 = intrinsic_rdmsr(MSR_VMX_CR4_FIXED0); + uint64_t ia32_vmx_cr4_fixed1 = intrinsic_rdmsr(MSR_VMX_CR4_FIXED1); + + if (0 != ((~cr4 & ia32_vmx_cr4_fixed0) | (cr4 & ~ia32_vmx_cr4_fixed1))) { + bferror("cr4 is not properly configured"); + bferror_x64(" - cr4", cr4); + bferror_x64(" - ia32_vmx_cr4_fixed0", ia32_vmx_cr4_fixed0); + bferror_x64(" - ia32_vmx_cr4_fixed1", ia32_vmx_cr4_fixed1); + + return LOADER_FAILURE; + } + + return LOADER_SUCCESS; +} + +/** + * + * @brief This function checks to see if the CPU is supported as well as + * it's system configuration. * * * @return Returns 0 on success */ int64_t -check_for_hve_support(void) +check_cpu_configuration(void) { if (check_for_intel()) { bferror("check_for_intel failed"); @@ -282,8 +309,13 @@ check_for_hve_support(void) return LOADER_FAILURE; } - if (check_for_smep_smap()) { - bferror("check_for_smep_smap failed"); + if (check_cr0()) { + bferror("check_cr0 failed"); + return LOADER_FAILURE; + } + + if (check_cr4()) { + bferror("check_cr4 failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/intel/disable_hve.c b/loader/src/x64/intel/disable_hve.c index 64e457e7..730d421c 100644 --- a/loader/src/x64/intel/disable_hve.c +++ b/loader/src/x64/intel/disable_hve.c @@ -35,7 +35,7 @@ /** * - * @brief Disables AMD SVE + * @brief Disables Hardware Virtualization Extensions */ void disable_hve(void) diff --git a/loader/src/x64/intel/enable_hve.c b/loader/src/x64/intel/enable_hve.c index caa467e0..c0e549f7 100644 --- a/loader/src/x64/intel/enable_hve.c +++ b/loader/src/x64/intel/enable_hve.c @@ -46,7 +46,7 @@ /** * - * @brief Enables AMD SVE + * @brief Enables Hardware Virtualization Extensions * * * @param state the mk state save containing the HVE page diff --git a/loader/src/x64/map_4k_page.c b/loader/src/x64/map_4k_page.c index 49f88d88..e5f84fae 100644 --- a/loader/src/x64/map_4k_page.c +++ b/loader/src/x64/map_4k_page.c @@ -27,9 +27,10 @@ #include #include #include -#include +#include #include #include +#include #include #include #include @@ -41,6 +42,7 @@ #include #include #include +#include #include /** @@ -57,33 +59,17 @@ * @param virt the virtual address to map phys to * @param phys the physical address to map * @param flags the p_flags field from the segment associated with this page - * @param pml4t the root page table to place the resulting map + * @param rpt the root page table to place the resulting map * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_4k_page(uint64_t const virt, uint64_t phys, uint32_t const flags, struct pml4t_t *const pml4t) +map_4k_page(uint64_t const virt, uint64_t phys, uint32_t const flags, root_page_table_t *const rpt) { struct pdpt_t *pdpt = ((void *)0); struct pdt_t *pdt = ((void *)0); struct pt_t *pt = ((void *)0); struct pte_t *pte = ((void *)0); - /** - * TODO: - * - We need to map in any page tables that we allocate. The problem is, - * we cannot use a recursive function to do this as it could result - * in a stack overflow in the kernel. Likely, the best option would - * be to convert this function into a private _impl, and provide it - * with a queue that we can push allocated pages to so that the wrapper - * can map any pages that are pushed. This way, as we map, we can - * continue to push pages until the process finally stops. Since this - * code is common between Windows/Linux/UEFI, we will need to implement - * this queue from scratch. For now, we seem to be ok without this - * additional logic, but it is possible that the microkernel could end - * up with a page fault while it is trying to walk page tables as it - * wouldn't have all of the memory properly mapped. - */ - if (((uint64_t)0) == virt) { bferror_x64("virt is NULL", virt); return LOADER_FAILURE; @@ -107,9 +93,9 @@ map_4k_page(uint64_t const virt, uint64_t phys, uint32_t const flags, struct pml return LOADER_FAILURE; } - pdpt = pml4t->tables[pml4to(virt)]; + pdpt = rpt->tables[pml4to(virt)]; if (((void *)0) == pdpt) { - pdpt = alloc_pdpt(pml4t, virt); + pdpt = alloc_pdpt(rpt, virt); } pdt = pdpt->tables[pdpto(virt)]; @@ -140,5 +126,6 @@ map_4k_page(uint64_t const virt, uint64_t phys, uint32_t const flags, struct pml pte->nx = ((uint64_t)1); } + flush_cache(pte); return LOADER_SUCCESS; } diff --git a/loader/src/x64/map_mk_code_aliases.c b/loader/src/x64/map_mk_code_aliases.c index 3bb47f0f..02e7bd9c 100644 --- a/loader/src/x64/map_mk_code_aliases.c +++ b/loader/src/x64/map_mk_code_aliases.c @@ -34,8 +34,10 @@ #include #include #include -#include #include +#include +#include +#include #ifdef _MSC_VER #pragma warning(disable : 4152) @@ -50,11 +52,11 @@ * * @param a a pointer to a code_aliases_t that stores the aliases * being mapped - * @param pml4t the root page table to map the code aliases into + * @param rpt the root page table to map the code aliases into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_mk_code_aliases(struct code_aliases_t const *const a, struct pml4t_t *const pml4t) +map_mk_code_aliases(struct code_aliases_t const *const a, root_page_table_t *const rpt) { uint64_t phys; @@ -73,7 +75,7 @@ map_mk_code_aliases(struct code_aliases_t const *const a, struct pml4t_t *const return LOADER_FAILURE; } - if (map_4k_page_rx(demote, phys, pml4t)) { + if (map_4k_page_rx(demote, phys, rpt)) { bferror("map_4k_page_rx failed"); return LOADER_FAILURE; } @@ -84,7 +86,7 @@ map_mk_code_aliases(struct code_aliases_t const *const a, struct pml4t_t *const return LOADER_FAILURE; } - if (map_4k_page_rx(promote, phys, pml4t)) { + if (map_4k_page_rx(promote, phys, rpt)) { bferror("map_4k_page_rx failed"); return LOADER_FAILURE; } @@ -95,7 +97,7 @@ map_mk_code_aliases(struct code_aliases_t const *const a, struct pml4t_t *const return LOADER_FAILURE; } - if (map_4k_page_rx(esr_default, phys, pml4t)) { + if (map_4k_page_rx(esr_default, phys, rpt)) { bferror("map_4k_page_rx failed"); return LOADER_FAILURE; } @@ -106,7 +108,7 @@ map_mk_code_aliases(struct code_aliases_t const *const a, struct pml4t_t *const return LOADER_FAILURE; } - if (map_4k_page_rx(esr_df, phys, pml4t)) { + if (map_4k_page_rx(esr_df, phys, rpt)) { bferror("map_4k_page_rx failed"); return LOADER_FAILURE; } @@ -117,7 +119,7 @@ map_mk_code_aliases(struct code_aliases_t const *const a, struct pml4t_t *const return LOADER_FAILURE; } - if (map_4k_page_rx(esr_gpf, phys, pml4t)) { + if (map_4k_page_rx(esr_gpf, phys, rpt)) { bferror("map_4k_page_rx failed"); return LOADER_FAILURE; } @@ -128,7 +130,7 @@ map_mk_code_aliases(struct code_aliases_t const *const a, struct pml4t_t *const return LOADER_FAILURE; } - if (map_4k_page_rx(esr_nmi, phys, pml4t)) { + if (map_4k_page_rx(esr_nmi, phys, rpt)) { bferror("map_4k_page_rx failed"); return LOADER_FAILURE; } @@ -139,7 +141,29 @@ map_mk_code_aliases(struct code_aliases_t const *const a, struct pml4t_t *const return LOADER_FAILURE; } - if (map_4k_page_rx(esr_pf, phys, pml4t)) { + if (map_4k_page_rx(esr_pf, phys, rpt)) { + bferror("map_4k_page_rx failed"); + return LOADER_FAILURE; + } + + phys = platform_virt_to_phys(a->serial_write_c); + if (((uint64_t)0) == phys) { + bferror("platform_virt_to_phys failed"); + return LOADER_FAILURE; + } + + if (map_4k_page_rx(serial_write_c, phys, rpt)) { + bferror("map_4k_page_rx failed"); + return LOADER_FAILURE; + } + + phys = platform_virt_to_phys(a->serial_write_hex); + if (((uint64_t)0) == phys) { + bferror("platform_virt_to_phys failed"); + return LOADER_FAILURE; + } + + if (map_4k_page_rx(serial_write_hex, phys, rpt)) { bferror("map_4k_page_rx failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/map_mk_state.c b/loader/src/x64/map_mk_state.c index df02fa18..1c77f47d 100644 --- a/loader/src/x64/map_mk_state.c +++ b/loader/src/x64/map_mk_state.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include /** @@ -38,38 +38,38 @@ * * @param state a pointer to a state_save_t that stores the state * being mapped - * @param pml4t the root page table to map the state into + * @param rpt the root page table to map the state into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_mk_state(struct state_save_t const *const state, struct pml4t_t *const pml4t) +map_mk_state(struct state_save_t const *const state, root_page_table_t *const rpt) { - if (map_4k_page_rw(state, ((uint64_t)0), pml4t)) { + if (map_4k_page_rw(state, ((uint64_t)0), rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } - if (map_4k_page_rw(state->tss, ((uint64_t)0), pml4t)) { + if (map_4k_page_rw(state->tss, ((uint64_t)0), rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } - if (map_4k_page_rw(state->ist, ((uint64_t)0), pml4t)) { + if (map_4k_page_rw(state->ist, ((uint64_t)0), rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } - if (map_4k_page_rw(state->gdtr.base, ((uint64_t)0), pml4t)) { + if (map_4k_page_rw(state->gdtr.base, ((uint64_t)0), rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } - if (map_4k_page_rw(state->idtr.base, ((uint64_t)0), pml4t)) { + if (map_4k_page_rw(state->idtr.base, ((uint64_t)0), rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } - if (map_4k_page_rw(state->hve_page, ((uint64_t)0), pml4t)) { + if (map_4k_page_rw(state->hve_page, ((uint64_t)0), rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/map_root_vp_state.c b/loader/src/x64/map_root_vp_state.c index 5c803646..326e6f04 100644 --- a/loader/src/x64/map_root_vp_state.c +++ b/loader/src/x64/map_root_vp_state.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include /** @@ -38,13 +38,13 @@ * * @param state a pointer to a state_save_t that stores the state * being mapped - * @param pml4t the root page table to map the state into + * @param rpt the root page table to map the state into * @return 0 on success, LOADER_FAILURE on failure. */ int64_t -map_root_vp_state(struct state_save_t const *const state, struct pml4t_t *const pml4t) +map_root_vp_state(struct state_save_t const *const state, root_page_table_t *const rpt) { - if (map_4k_page_rw(state, ((uint64_t)0), pml4t)) { + if (map_4k_page_rw(state, ((uint64_t)0), rpt)) { bferror("map_4k_page_rw failed"); return LOADER_FAILURE; } diff --git a/loader/src/x64/serial_write.c b/loader/src/x64/serial_write.c deleted file mode 100644 index 2dd6c6f4..00000000 --- a/loader/src/x64/serial_write.c +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @copyright - * Copyright (C) 2020 Assured Information Security, Inc. - * - * @copyright - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * @copyright - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * @copyright - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include - -/** @brief defines the line status register */ -#define SERIAL_PORT ((uint16_t)HYPERVISOR_SERIAL_PORT) - -/** @brief defines the line status register */ -#define LSR ((uint16_t)5) -/** @brief defines the transmit FIFO empty bit in the LSR */ -#define LSR_TRANSMIT_FIFO_EMPTY ((uint8_t)(((uint8_t)1) << ((uint8_t)5))) - -/** - * - * @brief Reads a byte from the requested serial port register. - * - * - * @param reg the serial port register to read from - * @return the data read from the requested serial port register - */ -static uint8_t -serial_inb(uint16_t reg) -{ - reg += SERIAL_PORT; - return intrinsic_inb(reg); -} - -/** - * - * @brief Writes a byte to the requested serial port register. - * - * - * @param reg the serial port register to write to - * @param val the byte to write to the requested serial port register - */ -static void -serial_outb(uint16_t reg, uint8_t const val) -{ - reg += SERIAL_PORT; - intrinsic_outb(reg, val); -} - -/** - * - * @brief Writes a string to the serial port. Note that you must initialize - * the serial port before you can use it. - * - * - * @param str the string to write to the serial port. - */ -void -serial_write(char const *const str) -{ - int i; - - while ((serial_inb(LSR) & LSR_TRANSMIT_FIFO_EMPTY) == 0) { - } - - for (i = 0; str[i] != '\0'; ++i) { - serial_outb(0, str[i]); - } -} diff --git a/loader/test/.clang-tidy b/loader/test/.clang-tidy new file mode 100644 index 00000000..82d46de4 --- /dev/null +++ b/loader/test/.clang-tidy @@ -0,0 +1,63 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +Checks: + ' + -*, + bsl-*, + -bsl-template-generic-param, + -bsl-comparison-operators-forbidden, + -bsl-boolean-operators-forbidden, + -bsl-function-noexcept, + -bsl-name-prefixes, + -bsl-name-case, + -bsl-using-ident-unique-namespace, + -bsl-literals-user-defined, + bugprone-*, + -bugprone-branch-clone, + cert-*, + -cert-dcl21-cpp, + -cert-oop54-cpp, + clang-analyzer-*, + -clang-analyzer-core.CallAndMessage, + cppcoreguidelines-*, + -cppcoreguidelines-avoid-non-const-global-variables, + hicpp-*, + -hicpp-function-size, + -hicpp-deprecated-headers,, + misc-*, + -misc-misplaced-const, + -misc-non-private-member-variables-in-classes, + modernize-*, + -modernize-use-default-member-init, + -modernize-deprecated-headers, + performance-*, + readability-*, + -readability-redundant-member-init, + -readability-avoid-const-params-in-decls, + -readability-static-accessed-through-instance, + -readability-function-size + ' +WarningsAsErrors: '*' +HeaderFilterRegex: '.*' +AnalyzeTemporaryDtors: false +FormatStyle: none +UseColor: true diff --git a/loader/test/CMakeLists.txt b/loader/test/CMakeLists.txt new file mode 100644 index 00000000..8b68e929 --- /dev/null +++ b/loader/test/CMakeLists.txt @@ -0,0 +1,243 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +include(${bsl_SOURCE_DIR}/cmake/function/bf_add_test.cmake) + +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + +list(APPEND INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/common_platform +) + +list(APPEND SYSTEM_INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c +) + +list(APPEND COMMON_INCLUDES + ${INCLUDES} + ${CMAKE_CURRENT_LIST_DIR}/common_arch + ${CMAKE_CURRENT_LIST_DIR}/common_arch/interface/c +) + +list(APPEND COMMON_SYSTEM_INCLUDES + ${SYSTEM_INCLUDES} +) + +list(APPEND X64_INCLUDES + ${INCLUDES} + ${CMAKE_CURRENT_LIST_DIR}/../include/x64 + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64 +) + +list(APPEND X64_SYSTEM_INCLUDES + ${SYSTEM_INCLUDES} +) + +list(APPEND AMD_INCLUDES + ${X64_INCLUDES} + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/amd + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/amd +) + +list(APPEND AMD_SYSTEM_INCLUDES + ${X64_SYSTEM_INCLUDES} +) + +list(APPEND INTEL_INCLUDES + ${X64_INCLUDES} + ${CMAKE_CURRENT_LIST_DIR}/../include/x64/intel + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/x64/intel +) + +list(APPEND INTEL_SYSTEM_INCLUDES + ${X64_SYSTEM_INCLUDES} +) + +list(APPEND AARCH64_INCLUDES + ${INCLUDES} + ${CMAKE_CURRENT_LIST_DIR}/../include/arm/aarch64 + ${CMAKE_CURRENT_LIST_DIR}/../include/interface/c/arm/aarch64 +) + +list(APPEND AARCH64_SYSTEM_INCLUDES + ${SYSTEM_INCLUDES} +) + +# ------------------------------------------------------------------------------ +# Definitions +# ------------------------------------------------------------------------------ + +list(APPEND DEFINES + HYPERVISOR_DEBUG_RING_SIZE=0x7FF0 + HYPERVISOR_MAX_EXTENSIONS=2 + HYPERVISOR_MAX_SEGMENTS=3 +) + +# ------------------------------------------------------------------------------ +# Tests +# ------------------------------------------------------------------------------ + +add_subdirectory(alloc_and_copy_ext_elf_files_from_user) +add_subdirectory(alloc_and_copy_mk_elf_file_from_user) +add_subdirectory(alloc_and_copy_mk_elf_segments) +add_subdirectory(alloc_mk_args) +add_subdirectory(alloc_mk_debug_ring) +add_subdirectory(alloc_mk_huge_pool) +add_subdirectory(alloc_mk_page_pool) +add_subdirectory(alloc_mk_stack) +add_subdirectory(dump_ext_elf_files) +add_subdirectory(dump_mk_args) +add_subdirectory(dump_mk_debug_ring) +add_subdirectory(dump_mk_elf_file) +add_subdirectory(dump_mk_elf_segments) +add_subdirectory(dump_mk_huge_pool) +add_subdirectory(dump_mk_page_pool) +add_subdirectory(dump_mk_root_page_table) +add_subdirectory(dump_mk_stack) +add_subdirectory(dump_vmm) +add_subdirectory(free_ext_elf_files) +add_subdirectory(free_mk_args) +add_subdirectory(free_mk_debug_ring) +add_subdirectory(free_mk_elf_file) +add_subdirectory(free_mk_elf_segments) +add_subdirectory(free_mk_huge_pool) +add_subdirectory(free_mk_page_pool) +add_subdirectory(free_mk_stack) +add_subdirectory(g_cpu_status) +add_subdirectory(get_mk_huge_pool_addr) +add_subdirectory(get_mk_page_pool_addr) +add_subdirectory(g_ext_elf_files) +add_subdirectory(g_mk_args) +add_subdirectory(g_mk_code_aliases) +add_subdirectory(g_mk_debug_ring) +add_subdirectory(g_mk_elf_file) +add_subdirectory(g_mk_elf_segments) +add_subdirectory(g_mk_huge_pool) +add_subdirectory(g_mk_page_pool) +add_subdirectory(g_mk_root_page_table) +add_subdirectory(g_mk_stack) +add_subdirectory(g_mk_state) +add_subdirectory(g_root_vp_state) +add_subdirectory(g_vmm_status) +add_subdirectory(loader_fini) +add_subdirectory(loader_init) +add_subdirectory(map_4k_page_rw) +add_subdirectory(map_4k_page_rx) +add_subdirectory(map_ext_elf_files) +add_subdirectory(map_mk_args) +add_subdirectory(map_mk_debug_ring) +add_subdirectory(map_mk_elf_file) +add_subdirectory(map_mk_elf_segments) +add_subdirectory(map_mk_huge_pool) +add_subdirectory(map_mk_page_pool) +add_subdirectory(map_mk_stack) +add_subdirectory(serial_write) +add_subdirectory(start_vmm) +add_subdirectory(start_vmm_per_cpu) +add_subdirectory(stop_and_free_the_vmm) +add_subdirectory(stop_vmm) +add_subdirectory(stop_vmm_per_cpu) + +add_subdirectory(x64/alloc_and_copy_mk_code_aliases) +add_subdirectory(x64/alloc_and_copy_mk_state) +add_subdirectory(x64/alloc_and_copy_root_vp_state) +add_subdirectory(x64/alloc_mk_root_page_table) +add_subdirectory(x64/alloc_pdpt) +add_subdirectory(x64/alloc_pdt) +add_subdirectory(x64/alloc_pt) +add_subdirectory(x64/dump_mk_code_aliases) +add_subdirectory(x64/dump_mk_state) +add_subdirectory(x64/dump_root_vp_state) +add_subdirectory(x64/free_mk_code_aliases) +add_subdirectory(x64/free_mk_root_page_table) +add_subdirectory(x64/free_mk_state) +add_subdirectory(x64/free_pdpt) +add_subdirectory(x64/free_pdt) +add_subdirectory(x64/free_pml4t) +add_subdirectory(x64/free_root_vp_state) +add_subdirectory(x64/get_gdt_descriptor_attrib) +add_subdirectory(x64/get_gdt_descriptor_base) +add_subdirectory(x64/get_gdt_descriptor_limit) +add_subdirectory(x64/map_4k_page) +add_subdirectory(x64/map_mk_code_aliases) +add_subdirectory(x64/map_mk_state) +add_subdirectory(x64/map_root_vp_state) +add_subdirectory(x64/send_command_report_off) +add_subdirectory(x64/send_command_report_on) +add_subdirectory(x64/send_command_stop) +add_subdirectory(x64/serial_init) +add_subdirectory(x64/set_gdt_descriptor) +add_subdirectory(x64/set_idt_descriptor) +add_subdirectory(x64/amd/check_cpu_configuration) +add_subdirectory(x64/amd/disable_hve) +add_subdirectory(x64/amd/enable_hve) +add_subdirectory(x64/intel/check_cpu_configuration) +add_subdirectory(x64/intel/disable_hve) +add_subdirectory(x64/intel/enable_hve) + +add_subdirectory(arm/aarch64/alloc_and_copy_mk_code_aliases) +add_subdirectory(arm/aarch64/alloc_and_copy_mk_state) +add_subdirectory(arm/aarch64/alloc_and_copy_root_vp_state) +add_subdirectory(arm/aarch64/alloc_l1t) +add_subdirectory(arm/aarch64/alloc_l2t) +add_subdirectory(arm/aarch64/alloc_l3t) +add_subdirectory(arm/aarch64/alloc_mk_root_page_table) +add_subdirectory(arm/aarch64/check_cpu_configuration) +add_subdirectory(arm/aarch64/dump_mk_code_aliases) +add_subdirectory(arm/aarch64/dump_mk_state) +add_subdirectory(arm/aarch64/dump_root_vp_state) +add_subdirectory(arm/aarch64/free_l0t) +add_subdirectory(arm/aarch64/free_l1t) +add_subdirectory(arm/aarch64/free_l2t) +add_subdirectory(arm/aarch64/free_mk_code_aliases) +add_subdirectory(arm/aarch64/free_mk_root_page_table) +add_subdirectory(arm/aarch64/free_mk_state) +add_subdirectory(arm/aarch64/free_root_vp_state) +add_subdirectory(arm/aarch64/map_4k_page) +add_subdirectory(arm/aarch64/map_mk_code_aliases) +add_subdirectory(arm/aarch64/map_mk_state) +add_subdirectory(arm/aarch64/map_root_vp_state) +add_subdirectory(arm/aarch64/send_command_report_off) +add_subdirectory(arm/aarch64/send_command_report_on) +add_subdirectory(arm/aarch64/send_command_stop) +add_subdirectory(arm/aarch64/serial_init) + +add_subdirectory(efi/entry) +add_subdirectory(efi/platform) +add_subdirectory(efi/work_on_cpu_callback) + +add_subdirectory(efi/x64/arch_init) +add_subdirectory(efi/x64/arch_locate_protocols) +add_subdirectory(efi/x64/arch_num_online_cpus) +add_subdirectory(efi/x64/arch_work_on_cpu) +add_subdirectory(efi/x64/setup_tss) +add_subdirectory(efi/x64/amd/setup_cr0) +add_subdirectory(efi/x64/amd/setup_cr4) +add_subdirectory(efi/x64/intel/setup_cr0) +add_subdirectory(efi/x64/intel/setup_cr4) + +add_subdirectory(efi/arm/aarch64/arch_init) +add_subdirectory(efi/arm/aarch64/arch_locate_protocols) +add_subdirectory(efi/arm/aarch64/arch_num_online_cpus) +add_subdirectory(efi/arm/aarch64/arch_work_on_cpu) diff --git a/loader/test/alloc_and_copy_ext_elf_files_from_user/CMakeLists.txt b/loader/test/alloc_and_copy_ext_elf_files_from_user/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/alloc_and_copy_ext_elf_files_from_user/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/alloc_and_copy_ext_elf_files_from_user/behavior.cpp b/loader/test/alloc_and_copy_ext_elf_files_from_user/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/alloc_and_copy_ext_elf_files_from_user/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/alloc_and_copy_mk_elf_file_from_user/CMakeLists.txt b/loader/test/alloc_and_copy_mk_elf_file_from_user/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/alloc_and_copy_mk_elf_file_from_user/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/alloc_and_copy_mk_elf_file_from_user/behavior.cpp b/loader/test/alloc_and_copy_mk_elf_file_from_user/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/alloc_and_copy_mk_elf_file_from_user/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/alloc_and_copy_mk_elf_segments/CMakeLists.txt b/loader/test/alloc_and_copy_mk_elf_segments/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/alloc_and_copy_mk_elf_segments/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/alloc_and_copy_mk_elf_segments/behavior.cpp b/loader/test/alloc_and_copy_mk_elf_segments/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/alloc_and_copy_mk_elf_segments/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/alloc_mk_args/CMakeLists.txt b/loader/test/alloc_mk_args/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/alloc_mk_args/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/alloc_mk_args/behavior.cpp b/loader/test/alloc_mk_args/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/alloc_mk_args/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/alloc_mk_debug_ring/CMakeLists.txt b/loader/test/alloc_mk_debug_ring/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/alloc_mk_debug_ring/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/alloc_mk_debug_ring/behavior.cpp b/loader/test/alloc_mk_debug_ring/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/alloc_mk_debug_ring/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/alloc_mk_huge_pool/CMakeLists.txt b/loader/test/alloc_mk_huge_pool/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/alloc_mk_huge_pool/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/alloc_mk_huge_pool/behavior.cpp b/loader/test/alloc_mk_huge_pool/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/alloc_mk_huge_pool/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/alloc_mk_page_pool/CMakeLists.txt b/loader/test/alloc_mk_page_pool/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/alloc_mk_page_pool/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/alloc_mk_page_pool/behavior.cpp b/loader/test/alloc_mk_page_pool/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/alloc_mk_page_pool/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/alloc_mk_stack/CMakeLists.txt b/loader/test/alloc_mk_stack/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/alloc_mk_stack/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/alloc_mk_stack/behavior.cpp b/loader/test/alloc_mk_stack/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/alloc_mk_stack/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/alloc_and_copy_mk_code_aliases/CMakeLists.txt b/loader/test/arm/aarch64/alloc_and_copy_mk_code_aliases/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/alloc_and_copy_mk_code_aliases/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/alloc_and_copy_mk_code_aliases/behavior.cpp b/loader/test/arm/aarch64/alloc_and_copy_mk_code_aliases/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/alloc_and_copy_mk_code_aliases/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/alloc_and_copy_mk_state/CMakeLists.txt b/loader/test/arm/aarch64/alloc_and_copy_mk_state/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/alloc_and_copy_mk_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/alloc_and_copy_mk_state/behavior.cpp b/loader/test/arm/aarch64/alloc_and_copy_mk_state/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/alloc_and_copy_mk_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/alloc_and_copy_root_vp_state/CMakeLists.txt b/loader/test/arm/aarch64/alloc_and_copy_root_vp_state/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/alloc_and_copy_root_vp_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/alloc_and_copy_root_vp_state/behavior.cpp b/loader/test/arm/aarch64/alloc_and_copy_root_vp_state/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/alloc_and_copy_root_vp_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/alloc_l1t/CMakeLists.txt b/loader/test/arm/aarch64/alloc_l1t/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/alloc_l1t/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/alloc_l1t/behavior.cpp b/loader/test/arm/aarch64/alloc_l1t/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/alloc_l1t/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/alloc_l2t/CMakeLists.txt b/loader/test/arm/aarch64/alloc_l2t/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/alloc_l2t/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/alloc_l2t/behavior.cpp b/loader/test/arm/aarch64/alloc_l2t/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/alloc_l2t/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/alloc_l3t/CMakeLists.txt b/loader/test/arm/aarch64/alloc_l3t/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/alloc_l3t/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/alloc_l3t/behavior.cpp b/loader/test/arm/aarch64/alloc_l3t/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/alloc_l3t/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/alloc_mk_root_page_table/CMakeLists.txt b/loader/test/arm/aarch64/alloc_mk_root_page_table/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/alloc_mk_root_page_table/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/alloc_mk_root_page_table/behavior.cpp b/loader/test/arm/aarch64/alloc_mk_root_page_table/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/alloc_mk_root_page_table/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/check_cpu_configuration/CMakeLists.txt b/loader/test/arm/aarch64/check_cpu_configuration/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/check_cpu_configuration/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/check_cpu_configuration/behavior.cpp b/loader/test/arm/aarch64/check_cpu_configuration/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/check_cpu_configuration/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/dump_mk_code_aliases/CMakeLists.txt b/loader/test/arm/aarch64/dump_mk_code_aliases/CMakeLists.txt new file mode 100644 index 00000000..ccf53a37 --- /dev/null +++ b/loader/test/arm/aarch64/dump_mk_code_aliases/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/arm/aarch64/dump_mk_code_aliases.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/dump_mk_code_aliases/behavior.cpp b/loader/test/arm/aarch64/dump_mk_code_aliases/behavior.cpp new file mode 100644 index 00000000..f8a989d2 --- /dev/null +++ b/loader/test/arm/aarch64/dump_mk_code_aliases/behavior.cpp @@ -0,0 +1,76 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_code_aliases.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null a"} = []() { + bsl::ut_then{} = []() { + dump_mk_code_aliases(nullptr); + }; + }; + + bsl::ut_scenario{"success"} = []() { + code_aliases_t a{}; + bsl::ut_then{} = [&]() { + dump_mk_code_aliases(&a); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/dump_mk_state/CMakeLists.txt b/loader/test/arm/aarch64/dump_mk_state/CMakeLists.txt new file mode 100644 index 00000000..21d3f5b7 --- /dev/null +++ b/loader/test/arm/aarch64/dump_mk_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/arm/aarch64/dump_mk_state.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/dump_mk_state/behavior.cpp b/loader/test/arm/aarch64/dump_mk_state/behavior.cpp new file mode 100644 index 00000000..79239cc0 --- /dev/null +++ b/loader/test/arm/aarch64/dump_mk_state/behavior.cpp @@ -0,0 +1,76 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_state.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null state"} = []() { + bsl::ut_then{} = []() { + dump_mk_state(nullptr, {}); + }; + }; + + bsl::ut_scenario{"success"} = []() { + state_save_t state{}; + bsl::ut_then{} = [&]() { + dump_mk_state(&state, {}); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/dump_root_vp_state/CMakeLists.txt b/loader/test/arm/aarch64/dump_root_vp_state/CMakeLists.txt new file mode 100644 index 00000000..489dce24 --- /dev/null +++ b/loader/test/arm/aarch64/dump_root_vp_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/arm/aarch64/dump_root_vp_state.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/dump_root_vp_state/behavior.cpp b/loader/test/arm/aarch64/dump_root_vp_state/behavior.cpp new file mode 100644 index 00000000..bec04564 --- /dev/null +++ b/loader/test/arm/aarch64/dump_root_vp_state/behavior.cpp @@ -0,0 +1,76 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_root_vp_state.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null state"} = []() { + bsl::ut_then{} = []() { + dump_root_vp_state(nullptr, {}); + }; + }; + + bsl::ut_scenario{"success"} = []() { + state_save_t state{}; + bsl::ut_then{} = [&]() { + dump_root_vp_state(&state, {}); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/free_l0t/CMakeLists.txt b/loader/test/arm/aarch64/free_l0t/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/free_l0t/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/free_l0t/behavior.cpp b/loader/test/arm/aarch64/free_l0t/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/free_l0t/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/free_l1t/CMakeLists.txt b/loader/test/arm/aarch64/free_l1t/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/free_l1t/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/free_l1t/behavior.cpp b/loader/test/arm/aarch64/free_l1t/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/free_l1t/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/free_l2t/CMakeLists.txt b/loader/test/arm/aarch64/free_l2t/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/free_l2t/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/free_l2t/behavior.cpp b/loader/test/arm/aarch64/free_l2t/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/free_l2t/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/free_mk_code_aliases/CMakeLists.txt b/loader/test/arm/aarch64/free_mk_code_aliases/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/free_mk_code_aliases/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/free_mk_code_aliases/behavior.cpp b/loader/test/arm/aarch64/free_mk_code_aliases/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/free_mk_code_aliases/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/free_mk_root_page_table/CMakeLists.txt b/loader/test/arm/aarch64/free_mk_root_page_table/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/free_mk_root_page_table/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/free_mk_root_page_table/behavior.cpp b/loader/test/arm/aarch64/free_mk_root_page_table/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/free_mk_root_page_table/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/free_mk_state/CMakeLists.txt b/loader/test/arm/aarch64/free_mk_state/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/free_mk_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/free_mk_state/behavior.cpp b/loader/test/arm/aarch64/free_mk_state/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/free_mk_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/free_root_vp_state/CMakeLists.txt b/loader/test/arm/aarch64/free_root_vp_state/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/free_root_vp_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/free_root_vp_state/behavior.cpp b/loader/test/arm/aarch64/free_root_vp_state/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/free_root_vp_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/map_4k_page/CMakeLists.txt b/loader/test/arm/aarch64/map_4k_page/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/map_4k_page/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/map_4k_page/behavior.cpp b/loader/test/arm/aarch64/map_4k_page/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/map_4k_page/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/map_mk_code_aliases/CMakeLists.txt b/loader/test/arm/aarch64/map_mk_code_aliases/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/map_mk_code_aliases/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/map_mk_code_aliases/behavior.cpp b/loader/test/arm/aarch64/map_mk_code_aliases/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/map_mk_code_aliases/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/map_mk_state/CMakeLists.txt b/loader/test/arm/aarch64/map_mk_state/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/map_mk_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/map_mk_state/behavior.cpp b/loader/test/arm/aarch64/map_mk_state/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/map_mk_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/map_root_vp_state/CMakeLists.txt b/loader/test/arm/aarch64/map_root_vp_state/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/map_root_vp_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/map_root_vp_state/behavior.cpp b/loader/test/arm/aarch64/map_root_vp_state/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/map_root_vp_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/send_command_report_off/CMakeLists.txt b/loader/test/arm/aarch64/send_command_report_off/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/send_command_report_off/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/send_command_report_off/behavior.cpp b/loader/test/arm/aarch64/send_command_report_off/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/send_command_report_off/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/send_command_report_on/CMakeLists.txt b/loader/test/arm/aarch64/send_command_report_on/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/send_command_report_on/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/send_command_report_on/behavior.cpp b/loader/test/arm/aarch64/send_command_report_on/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/send_command_report_on/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/send_command_stop/CMakeLists.txt b/loader/test/arm/aarch64/send_command_stop/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/send_command_stop/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/send_command_stop/behavior.cpp b/loader/test/arm/aarch64/send_command_stop/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/send_command_stop/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/arm/aarch64/serial_init/CMakeLists.txt b/loader/test/arm/aarch64/serial_init/CMakeLists.txt new file mode 100644 index 00000000..aca54568 --- /dev/null +++ b/loader/test/arm/aarch64/serial_init/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AARCH64_INCLUDES} + SYSTEM_INCLUDES ${AARCH64_SYSTEM_INCLUDES} + DEFINES ${AARCH64_DEFINES} +) diff --git a/loader/test/arm/aarch64/serial_init/behavior.cpp b/loader/test/arm/aarch64/serial_init/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/arm/aarch64/serial_init/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/common_arch/interface/c/state_save_t.h b/loader/test/common_arch/interface/c/state_save_t.h new file mode 100644 index 00000000..b0c4e497 --- /dev/null +++ b/loader/test/common_arch/interface/c/state_save_t.h @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef STATE_SAVE_T_H +#define STATE_SAVE_T_H + +/** + * @struct state_save_t + * + * + * @brief Defines a dummy state_save_t for common code that doesn't + * actually access the contents of this arch specific structure. + */ +struct state_save_t +{}; + +#endif diff --git a/loader/test/common_arch/interface/cpp/state_save_t.hpp b/loader/test/common_arch/interface/cpp/state_save_t.hpp new file mode 100644 index 00000000..c8e79440 --- /dev/null +++ b/loader/test/common_arch/interface/cpp/state_save_t.hpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef STATE_SAVE_T_HPP +#define STATE_SAVE_T_HPP + +namespace loader +{ + /// @struct loader::state_save_t + /// + /// + /// @brief Defines a dummy state_save_t for common code that doesn't + /// actually access the contents of this arch specific structure. + /// + struct state_save_t final + {}; +} + +#endif diff --git a/loader/test/common_arch/root_page_table_t.h b/loader/test/common_arch/root_page_table_t.h new file mode 100644 index 00000000..074ac767 --- /dev/null +++ b/loader/test/common_arch/root_page_table_t.h @@ -0,0 +1,35 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ROOT_PAGE_TABLE_T_H +#define ROOT_PAGE_TABLE_T_H + +#include + +/** @brief defines the type for the root page tables for this arch */ +typedef uint64_t root_page_table_t; + +#endif diff --git a/loader/test/common_platform/constants.h b/loader/test/common_platform/constants.h new file mode 100644 index 00000000..99f91422 --- /dev/null +++ b/loader/test/common_platform/constants.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef CONSTANTS_H +#define CONSTANTS_H + +#endif diff --git a/loader/test/common_platform/debug.h b/loader/test/common_platform/debug.h new file mode 100644 index 00000000..8fd2a1f7 --- /dev/null +++ b/loader/test/common_platform/debug.h @@ -0,0 +1,313 @@ +/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include +#include + +/** + * + * @brief Outputs a string to the console + * + * + * @param str the string to output + */ +static inline void +bfdebug(char const *const str) +{ + printf("[BAREFLANK DEBUG] %s\n", str); +} + +/** + * + * @brief Outputs a string and an 8bit hex to the console + * + * + * @param str the string to output + * @param val the 8bit hex value to output +static inline void +bfdebug_x8(char const *const str, uint8_t const val) +{ + printf("[BAREFLANK DEBUG] %s: 0x%x\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an 16bit hex to the console + * + * + * @param str the string to output + * @param val the 16bit hex value to output + */ +static inline void +bfdebug_x16(char const *const str, uint16_t const val) +{ + printf("[BAREFLANK DEBUG] %s: 0x%x\n", str, val); +} + +/** + * + * @brief Outputs a string and an 32bit hex to the console + * + * + * @param str the string to output + * @param val the 32bit hex value to output + */ +static inline void +bfdebug_x32(char const *const str, uint32_t const val) +{ + printf("[BAREFLANK DEBUG] %s: 0x%x\n", str, val); +} + +/** + * + * @brief Outputs a string and an 64bit hex to the console + * + * + * @param str the string to output + * @param val the 64bit hex value to output + */ +static inline void +bfdebug_x64(char const *const str, uint64_t const val) +{ + printf("[BAREFLANK DEBUG] %s: 0x%" PRIx64 "\n", str, val); +} + +/** + * + * @brief Outputs a string and an 8bit dec to the console + * + * + * @param str the string to output + * @param val the 8bit dec value to output +static inline void +bfdebug_d8(char const *const str, uint8_t const val) +{ + printf("[BAREFLANK DEBUG] %s: %d\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an 16bit dec to the console + * + * + * @param str the string to output + * @param val the 16bit dec value to output +static inline void +bfdebug_d16(char const *const str, uint16_t const val) +{ + printf("[BAREFLANK DEBUG] %s: %d\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an 32bit dec to the console + * + * + * @param str the string to output + * @param val the 32bit dec value to output + */ +static inline void +bfdebug_d32(char const *const str, uint32_t const val) +{ + printf("[BAREFLANK DEBUG] %s: %d\n", str, val); +} + +/** + * + * @brief Outputs a string and an 64bit dec to the console + * + * + * @param str the string to output + * @param val the 64bit dec value to output +static inline void +bfdebug_d64(char const *const str, uint64_t const val) +{ + printf("[BAREFLANK DEBUG] %s: %" PRId64 "\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an pointer to the console + * + * + * @param str the string to output + * @param p the pointer to output + */ +static inline void +bfdebug_ptr(char const *const str, void const *const p) +{ + printf("[BAREFLANK DEBUG] %s: %p\n", str, p); +} + +/** + * + * @brief Outputs a string to the console + * + * + * @param str the string to output + */ +static inline void +bferror(char const *const str) +{ + printf("[BAREFLANK ERROR] %s", str); +} + +/** + * + * @brief Outputs a string and an 8bit hex to the console + * + * + * @param str the string to output + * @param val the 8bit hex value to output +static inline void +bferror_x8(char const *const str, uint8_t const val) +{ + printf("[BAREFLANK ERROR] %s: 0x%x\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an 16bit hex to the console + * + * + * @param str the string to output + * @param val the 16bit hex value to output +static inline void +bferror_x16(char const *const str, uint16_t const val) +{ + printf("[BAREFLANK ERROR] %s: 0x%x\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an 32bit hex to the console + * + * + * @param str the string to output + * @param val the 32bit hex value to output +static inline void +bferror_x32(char const *const str, uint32_t const val) +{ + printf("[BAREFLANK ERROR] %s: 0x%x\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an 64bit hex to the console + * + * + * @param str the string to output + * @param val the 64bit hex value to output +static inline void +bferror_x64(char const *const str, uint64_t const val) +{ + printf("[BAREFLANK ERROR] %s: 0x%" PRIx64 "\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an 8bit dec to the console + * + * + * @param str the string to output + * @param val the 8bit dec value to output +static inline void +bferror_d8(char const *const str, uint8_t const val) +{ + printf("[BAREFLANK ERROR] %s: %d\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an 16bit dec to the console + * + * + * @param str the string to output + * @param val the 16bit dec value to output +static inline void +bferror_d16(char const *const str, uint16_t const val) +{ + printf("[BAREFLANK ERROR] %s: %d\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an 32bit dec to the console + * + * + * @param str the string to output + * @param val the 32bit dec value to output +static inline void +bferror_d32(char const *const str, uint32_t const val) +{ + printf("[BAREFLANK ERROR] %s: %d\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an 64bit dec to the console + * + * + * @param str the string to output + * @param val the 64bit dec value to output +static inline void +bferror_d64(char const *const str, uint64_t const val) +{ + printf("[BAREFLANK ERROR] %s: %" PRId64 "\n", str, val); +} + */ + +/** + * + * @brief Outputs a string and an pointer to the console + * + * + * @param str the string to output + * @param p the pointer value to output +static inline void +bferror_ptr(char const *const str, void const *const p) +{ + printf("[BAREFLANK ERROR] %s: %p\n", str, p); +} + */ + +#endif diff --git a/loader/test/common_platform/types.h b/loader/test/common_platform/types.h new file mode 100644 index 00000000..784a7099 --- /dev/null +++ b/loader/test/common_platform/types.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ + +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TYPES_H +#define TYPES_H + +#include +#include + +/** + * @brief Returned by a loader function when a function succeeds. + */ +#define LOADER_SUCCESS ((int64_t)0) + +/** + * @brief Returned by a loader function when an error occurs. Note that + * functions that are responsible for stopping the hypervisor, in general, + * should never return an error. + */ +#define LOADER_FAILURE ((int64_t)-1) + +#endif diff --git a/loader/test/dump_ext_elf_files/CMakeLists.txt b/loader/test/dump_ext_elf_files/CMakeLists.txt new file mode 100644 index 00000000..c0ab09ee --- /dev/null +++ b/loader/test/dump_ext_elf_files/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_ext_elf_files.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/dump_ext_elf_files/behavior.cpp b/loader/test/dump_ext_elf_files/behavior.cpp new file mode 100644 index 00000000..8b64e7e8 --- /dev/null +++ b/loader/test/dump_ext_elf_files/behavior.cpp @@ -0,0 +1,88 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_ext_elf_files.h" +} + +#include +#include +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null files"} = []() { + bsl::ut_then{} = []() { + dump_ext_elf_files(nullptr); + }; + }; + + bsl::ut_scenario{"no extensions"} = []() { + bsl::array files{}; + bsl::ut_then{} = [&]() { + dump_ext_elf_files(files.data()); + }; + }; + + bsl::ut_scenario{"success"} = []() { + bsl::array files{}; + uint8_t data{}; + files.front().addr = &data; + files.front().size = sizeof(data); + bsl::ut_then{} = [&]() { + dump_ext_elf_files(files.data()); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/dump_mk_args/CMakeLists.txt b/loader/test/dump_mk_args/CMakeLists.txt new file mode 100644 index 00000000..b6e7e402 --- /dev/null +++ b/loader/test/dump_mk_args/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_args.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/dump_mk_args/behavior.cpp b/loader/test/dump_mk_args/behavior.cpp new file mode 100644 index 00000000..4c62f398 --- /dev/null +++ b/loader/test/dump_mk_args/behavior.cpp @@ -0,0 +1,86 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_args.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null args"} = []() { + bsl::ut_then{} = []() { + dump_mk_args(nullptr, {}); + }; + }; + + bsl::ut_scenario{"no extensions"} = []() { + mk_args_t args{}; + bsl::ut_then{} = [&]() { + dump_mk_args(&args, {}); + }; + }; + + bsl::ut_scenario{"success"} = []() { + mk_args_t args{}; + uint8_t data{}; + args.ext_elf_files[0].addr = &data; + args.ext_elf_files[0].size = sizeof(data); + bsl::ut_then{} = [&]() { + dump_mk_args(&args, {}); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/dump_mk_debug_ring/CMakeLists.txt b/loader/test/dump_mk_debug_ring/CMakeLists.txt new file mode 100644 index 00000000..7a820b05 --- /dev/null +++ b/loader/test/dump_mk_debug_ring/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_debug_ring.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/dump_mk_debug_ring/behavior.cpp b/loader/test/dump_mk_debug_ring/behavior.cpp new file mode 100644 index 00000000..55df8694 --- /dev/null +++ b/loader/test/dump_mk_debug_ring/behavior.cpp @@ -0,0 +1,76 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_debug_ring.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null debug_ring"} = []() { + bsl::ut_then{} = []() { + dump_mk_debug_ring(nullptr); + }; + }; + + bsl::ut_scenario{"success"} = []() { + debug_ring_t debug_ring{}; + bsl::ut_then{} = [&]() { + dump_mk_debug_ring(&debug_ring); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/dump_mk_elf_file/CMakeLists.txt b/loader/test/dump_mk_elf_file/CMakeLists.txt new file mode 100644 index 00000000..8ad23876 --- /dev/null +++ b/loader/test/dump_mk_elf_file/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_elf_file.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/dump_mk_elf_file/behavior.cpp b/loader/test/dump_mk_elf_file/behavior.cpp new file mode 100644 index 00000000..d4092357 --- /dev/null +++ b/loader/test/dump_mk_elf_file/behavior.cpp @@ -0,0 +1,76 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_elf_file.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null file"} = []() { + bsl::ut_then{} = []() { + dump_mk_elf_file(nullptr); + }; + }; + + bsl::ut_scenario{"success"} = []() { + span_t file{}; + bsl::ut_then{} = [&]() { + dump_mk_elf_file(&file); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/dump_mk_elf_segments/CMakeLists.txt b/loader/test/dump_mk_elf_segments/CMakeLists.txt new file mode 100644 index 00000000..9e7da42b --- /dev/null +++ b/loader/test/dump_mk_elf_segments/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_elf_segments.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/dump_mk_elf_segments/behavior.cpp b/loader/test/dump_mk_elf_segments/behavior.cpp new file mode 100644 index 00000000..a8de6e3a --- /dev/null +++ b/loader/test/dump_mk_elf_segments/behavior.cpp @@ -0,0 +1,88 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_elf_segments.h" +} + +#include +#include +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null segments"} = []() { + bsl::ut_then{} = []() { + dump_mk_elf_segments(nullptr); + }; + }; + + bsl::ut_scenario{"no segments"} = []() { + bsl::array segments{}; + bsl::ut_then{} = [&]() { + dump_mk_elf_segments(segments.data()); + }; + }; + + bsl::ut_scenario{"success"} = []() { + bsl::array segments{}; + uint8_t data{}; + segments.front().addr = &data; + segments.front().size = sizeof(data); + bsl::ut_then{} = [&]() { + dump_mk_elf_segments(segments.data()); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/dump_mk_huge_pool/CMakeLists.txt b/loader/test/dump_mk_huge_pool/CMakeLists.txt new file mode 100644 index 00000000..adce8346 --- /dev/null +++ b/loader/test/dump_mk_huge_pool/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_huge_pool.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/dump_mk_huge_pool/behavior.cpp b/loader/test/dump_mk_huge_pool/behavior.cpp new file mode 100644 index 00000000..547ed95a --- /dev/null +++ b/loader/test/dump_mk_huge_pool/behavior.cpp @@ -0,0 +1,76 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_huge_pool.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null huge_pool"} = []() { + bsl::ut_then{} = []() { + dump_mk_huge_pool(nullptr); + }; + }; + + bsl::ut_scenario{"success"} = []() { + mutable_span_t huge_pool{}; + bsl::ut_then{} = [&]() { + dump_mk_huge_pool(&huge_pool); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/dump_mk_page_pool/CMakeLists.txt b/loader/test/dump_mk_page_pool/CMakeLists.txt new file mode 100644 index 00000000..3361a40b --- /dev/null +++ b/loader/test/dump_mk_page_pool/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_page_pool.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/dump_mk_page_pool/behavior.cpp b/loader/test/dump_mk_page_pool/behavior.cpp new file mode 100644 index 00000000..03759ff9 --- /dev/null +++ b/loader/test/dump_mk_page_pool/behavior.cpp @@ -0,0 +1,76 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_page_pool.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null page_pool"} = []() { + bsl::ut_then{} = []() { + dump_mk_page_pool(nullptr); + }; + }; + + bsl::ut_scenario{"success"} = []() { + mutable_span_t page_pool{}; + bsl::ut_then{} = [&]() { + dump_mk_page_pool(&page_pool); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/dump_mk_root_page_table/CMakeLists.txt b/loader/test/dump_mk_root_page_table/CMakeLists.txt new file mode 100644 index 00000000..59598708 --- /dev/null +++ b/loader/test/dump_mk_root_page_table/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_root_page_table.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/dump_mk_root_page_table/behavior.cpp b/loader/test/dump_mk_root_page_table/behavior.cpp new file mode 100644 index 00000000..6052c3c9 --- /dev/null +++ b/loader/test/dump_mk_root_page_table/behavior.cpp @@ -0,0 +1,76 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_root_page_table.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null rpt"} = []() { + bsl::ut_then{} = []() { + dump_mk_root_page_table(nullptr); + }; + }; + + bsl::ut_scenario{"success"} = []() { + root_page_table_t rpt{}; + bsl::ut_then{} = [&]() { + dump_mk_root_page_table(&rpt); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/dump_mk_stack/CMakeLists.txt b/loader/test/dump_mk_stack/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/dump_mk_stack/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/dump_mk_stack/behavior.cpp b/loader/test/dump_mk_stack/behavior.cpp new file mode 100644 index 00000000..c35545b3 --- /dev/null +++ b/loader/test/dump_mk_stack/behavior.cpp @@ -0,0 +1,76 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null stack"} = []() { + bsl::ut_then{} = []() { + dump_mk_stack(nullptr, {}); + }; + }; + + bsl::ut_scenario{"success"} = []() { + span_t stack{}; + bsl::ut_then{} = [&]() { + dump_mk_stack(&stack, {}); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/dump_vmm/CMakeLists.txt b/loader/test/dump_vmm/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/dump_vmm/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/dump_vmm/behavior.cpp b/loader/test/dump_vmm/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/dump_vmm/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/arm/aarch64/arch_init/CMakeLists.txt b/loader/test/efi/arm/aarch64/arch_init/CMakeLists.txt new file mode 100644 index 00000000..2cbdfed8 --- /dev/null +++ b/loader/test/efi/arm/aarch64/arch_init/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/arm/aarch64/arch_init/behavior.cpp b/loader/test/efi/arm/aarch64/arch_init/behavior.cpp new file mode 100644 index 00000000..51206211 --- /dev/null +++ b/loader/test/efi/arm/aarch64/arch_init/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/arm/aarch64/arch_locate_protocols/CMakeLists.txt b/loader/test/efi/arm/aarch64/arch_locate_protocols/CMakeLists.txt new file mode 100644 index 00000000..2cbdfed8 --- /dev/null +++ b/loader/test/efi/arm/aarch64/arch_locate_protocols/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/arm/aarch64/arch_locate_protocols/behavior.cpp b/loader/test/efi/arm/aarch64/arch_locate_protocols/behavior.cpp new file mode 100644 index 00000000..51206211 --- /dev/null +++ b/loader/test/efi/arm/aarch64/arch_locate_protocols/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/arm/aarch64/arch_num_online_cpus/CMakeLists.txt b/loader/test/efi/arm/aarch64/arch_num_online_cpus/CMakeLists.txt new file mode 100644 index 00000000..2cbdfed8 --- /dev/null +++ b/loader/test/efi/arm/aarch64/arch_num_online_cpus/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/arm/aarch64/arch_num_online_cpus/behavior.cpp b/loader/test/efi/arm/aarch64/arch_num_online_cpus/behavior.cpp new file mode 100644 index 00000000..51206211 --- /dev/null +++ b/loader/test/efi/arm/aarch64/arch_num_online_cpus/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/arm/aarch64/arch_work_on_cpu/CMakeLists.txt b/loader/test/efi/arm/aarch64/arch_work_on_cpu/CMakeLists.txt new file mode 100644 index 00000000..2cbdfed8 --- /dev/null +++ b/loader/test/efi/arm/aarch64/arch_work_on_cpu/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/arm/aarch64/arch_work_on_cpu/behavior.cpp b/loader/test/efi/arm/aarch64/arch_work_on_cpu/behavior.cpp new file mode 100644 index 00000000..51206211 --- /dev/null +++ b/loader/test/efi/arm/aarch64/arch_work_on_cpu/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/entry/CMakeLists.txt b/loader/test/efi/entry/CMakeLists.txt new file mode 100644 index 00000000..840fb9a8 --- /dev/null +++ b/loader/test/efi/entry/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/entry/behavior.cpp b/loader/test/efi/entry/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/efi/entry/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/platform/CMakeLists.txt b/loader/test/efi/platform/CMakeLists.txt new file mode 100644 index 00000000..840fb9a8 --- /dev/null +++ b/loader/test/efi/platform/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/platform/behavior.cpp b/loader/test/efi/platform/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/efi/platform/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/work_on_cpu_callback/CMakeLists.txt b/loader/test/efi/work_on_cpu_callback/CMakeLists.txt new file mode 100644 index 00000000..840fb9a8 --- /dev/null +++ b/loader/test/efi/work_on_cpu_callback/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/work_on_cpu_callback/behavior.cpp b/loader/test/efi/work_on_cpu_callback/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/efi/work_on_cpu_callback/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/x64/amd/setup_cr0/CMakeLists.txt b/loader/test/efi/x64/amd/setup_cr0/CMakeLists.txt new file mode 100644 index 00000000..2cbdfed8 --- /dev/null +++ b/loader/test/efi/x64/amd/setup_cr0/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/x64/amd/setup_cr0/behavior.cpp b/loader/test/efi/x64/amd/setup_cr0/behavior.cpp new file mode 100644 index 00000000..51206211 --- /dev/null +++ b/loader/test/efi/x64/amd/setup_cr0/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/x64/amd/setup_cr4/CMakeLists.txt b/loader/test/efi/x64/amd/setup_cr4/CMakeLists.txt new file mode 100644 index 00000000..2cbdfed8 --- /dev/null +++ b/loader/test/efi/x64/amd/setup_cr4/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/x64/amd/setup_cr4/behavior.cpp b/loader/test/efi/x64/amd/setup_cr4/behavior.cpp new file mode 100644 index 00000000..51206211 --- /dev/null +++ b/loader/test/efi/x64/amd/setup_cr4/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/x64/arch_init/CMakeLists.txt b/loader/test/efi/x64/arch_init/CMakeLists.txt new file mode 100644 index 00000000..7d4ffda5 --- /dev/null +++ b/loader/test/efi/x64/arch_init/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/x64/arch_init/behavior.cpp b/loader/test/efi/x64/arch_init/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/efi/x64/arch_init/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/x64/arch_locate_protocols/CMakeLists.txt b/loader/test/efi/x64/arch_locate_protocols/CMakeLists.txt new file mode 100644 index 00000000..7d4ffda5 --- /dev/null +++ b/loader/test/efi/x64/arch_locate_protocols/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/x64/arch_locate_protocols/behavior.cpp b/loader/test/efi/x64/arch_locate_protocols/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/efi/x64/arch_locate_protocols/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/x64/arch_num_online_cpus/CMakeLists.txt b/loader/test/efi/x64/arch_num_online_cpus/CMakeLists.txt new file mode 100644 index 00000000..7d4ffda5 --- /dev/null +++ b/loader/test/efi/x64/arch_num_online_cpus/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/x64/arch_num_online_cpus/behavior.cpp b/loader/test/efi/x64/arch_num_online_cpus/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/efi/x64/arch_num_online_cpus/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/x64/arch_work_on_cpu/CMakeLists.txt b/loader/test/efi/x64/arch_work_on_cpu/CMakeLists.txt new file mode 100644 index 00000000..7d4ffda5 --- /dev/null +++ b/loader/test/efi/x64/arch_work_on_cpu/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/x64/arch_work_on_cpu/behavior.cpp b/loader/test/efi/x64/arch_work_on_cpu/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/efi/x64/arch_work_on_cpu/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/x64/intel/setup_cr0/CMakeLists.txt b/loader/test/efi/x64/intel/setup_cr0/CMakeLists.txt new file mode 100644 index 00000000..2cbdfed8 --- /dev/null +++ b/loader/test/efi/x64/intel/setup_cr0/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/x64/intel/setup_cr0/behavior.cpp b/loader/test/efi/x64/intel/setup_cr0/behavior.cpp new file mode 100644 index 00000000..51206211 --- /dev/null +++ b/loader/test/efi/x64/intel/setup_cr0/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/x64/intel/setup_cr4/CMakeLists.txt b/loader/test/efi/x64/intel/setup_cr4/CMakeLists.txt new file mode 100644 index 00000000..2cbdfed8 --- /dev/null +++ b/loader/test/efi/x64/intel/setup_cr4/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/x64/intel/setup_cr4/behavior.cpp b/loader/test/efi/x64/intel/setup_cr4/behavior.cpp new file mode 100644 index 00000000..51206211 --- /dev/null +++ b/loader/test/efi/x64/intel/setup_cr4/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/efi/x64/setup_tss/CMakeLists.txt b/loader/test/efi/x64/setup_tss/CMakeLists.txt new file mode 100644 index 00000000..7d4ffda5 --- /dev/null +++ b/loader/test/efi/x64/setup_tss/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/efi/x64/setup_tss/behavior.cpp b/loader/test/efi/x64/setup_tss/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/efi/x64/setup_tss/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/free_ext_elf_files/CMakeLists.txt b/loader/test/free_ext_elf_files/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/free_ext_elf_files/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/free_ext_elf_files/behavior.cpp b/loader/test/free_ext_elf_files/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/free_ext_elf_files/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/free_mk_args/CMakeLists.txt b/loader/test/free_mk_args/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/free_mk_args/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/free_mk_args/behavior.cpp b/loader/test/free_mk_args/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/free_mk_args/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/free_mk_debug_ring/CMakeLists.txt b/loader/test/free_mk_debug_ring/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/free_mk_debug_ring/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/free_mk_debug_ring/behavior.cpp b/loader/test/free_mk_debug_ring/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/free_mk_debug_ring/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/free_mk_elf_file/CMakeLists.txt b/loader/test/free_mk_elf_file/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/free_mk_elf_file/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/free_mk_elf_file/behavior.cpp b/loader/test/free_mk_elf_file/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/free_mk_elf_file/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/free_mk_elf_segments/CMakeLists.txt b/loader/test/free_mk_elf_segments/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/free_mk_elf_segments/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/free_mk_elf_segments/behavior.cpp b/loader/test/free_mk_elf_segments/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/free_mk_elf_segments/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/free_mk_huge_pool/CMakeLists.txt b/loader/test/free_mk_huge_pool/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/free_mk_huge_pool/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/free_mk_huge_pool/behavior.cpp b/loader/test/free_mk_huge_pool/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/free_mk_huge_pool/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/free_mk_page_pool/CMakeLists.txt b/loader/test/free_mk_page_pool/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/free_mk_page_pool/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/free_mk_page_pool/behavior.cpp b/loader/test/free_mk_page_pool/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/free_mk_page_pool/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/free_mk_stack/CMakeLists.txt b/loader/test/free_mk_stack/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/free_mk_stack/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/free_mk_stack/behavior.cpp b/loader/test/free_mk_stack/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/free_mk_stack/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_cpu_status/CMakeLists.txt b/loader/test/g_cpu_status/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_cpu_status/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_cpu_status/behavior.cpp b/loader/test/g_cpu_status/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_cpu_status/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_ext_elf_files/CMakeLists.txt b/loader/test/g_ext_elf_files/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_ext_elf_files/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_ext_elf_files/behavior.cpp b/loader/test/g_ext_elf_files/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_ext_elf_files/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_mk_args/CMakeLists.txt b/loader/test/g_mk_args/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_mk_args/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_mk_args/behavior.cpp b/loader/test/g_mk_args/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_mk_args/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_mk_code_aliases/CMakeLists.txt b/loader/test/g_mk_code_aliases/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_mk_code_aliases/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_mk_code_aliases/behavior.cpp b/loader/test/g_mk_code_aliases/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_mk_code_aliases/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_mk_debug_ring/CMakeLists.txt b/loader/test/g_mk_debug_ring/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_mk_debug_ring/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_mk_debug_ring/behavior.cpp b/loader/test/g_mk_debug_ring/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_mk_debug_ring/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_mk_elf_file/CMakeLists.txt b/loader/test/g_mk_elf_file/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_mk_elf_file/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_mk_elf_file/behavior.cpp b/loader/test/g_mk_elf_file/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_mk_elf_file/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_mk_elf_segments/CMakeLists.txt b/loader/test/g_mk_elf_segments/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_mk_elf_segments/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_mk_elf_segments/behavior.cpp b/loader/test/g_mk_elf_segments/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_mk_elf_segments/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_mk_huge_pool/CMakeLists.txt b/loader/test/g_mk_huge_pool/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_mk_huge_pool/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_mk_huge_pool/behavior.cpp b/loader/test/g_mk_huge_pool/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_mk_huge_pool/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_mk_page_pool/CMakeLists.txt b/loader/test/g_mk_page_pool/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_mk_page_pool/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_mk_page_pool/behavior.cpp b/loader/test/g_mk_page_pool/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_mk_page_pool/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_mk_root_page_table/CMakeLists.txt b/loader/test/g_mk_root_page_table/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_mk_root_page_table/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_mk_root_page_table/behavior.cpp b/loader/test/g_mk_root_page_table/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_mk_root_page_table/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_mk_stack/CMakeLists.txt b/loader/test/g_mk_stack/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_mk_stack/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_mk_stack/behavior.cpp b/loader/test/g_mk_stack/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_mk_stack/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_mk_state/CMakeLists.txt b/loader/test/g_mk_state/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_mk_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_mk_state/behavior.cpp b/loader/test/g_mk_state/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_mk_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_root_vp_state/CMakeLists.txt b/loader/test/g_root_vp_state/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_root_vp_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_root_vp_state/behavior.cpp b/loader/test/g_root_vp_state/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_root_vp_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/g_vmm_status/CMakeLists.txt b/loader/test/g_vmm_status/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/g_vmm_status/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/g_vmm_status/behavior.cpp b/loader/test/g_vmm_status/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/g_vmm_status/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/get_mk_huge_pool_addr/CMakeLists.txt b/loader/test/get_mk_huge_pool_addr/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/get_mk_huge_pool_addr/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/get_mk_huge_pool_addr/behavior.cpp b/loader/test/get_mk_huge_pool_addr/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/get_mk_huge_pool_addr/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/get_mk_page_pool_addr/CMakeLists.txt b/loader/test/get_mk_page_pool_addr/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/get_mk_page_pool_addr/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/get_mk_page_pool_addr/behavior.cpp b/loader/test/get_mk_page_pool_addr/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/get_mk_page_pool_addr/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/loader_fini/CMakeLists.txt b/loader/test/loader_fini/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/loader_fini/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/loader_fini/behavior.cpp b/loader/test/loader_fini/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/loader_fini/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/loader_init/CMakeLists.txt b/loader/test/loader_init/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/loader_init/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/loader_init/behavior.cpp b/loader/test/loader_init/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/loader_init/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/map_4k_page_rw/CMakeLists.txt b/loader/test/map_4k_page_rw/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/map_4k_page_rw/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/map_4k_page_rw/behavior.cpp b/loader/test/map_4k_page_rw/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/map_4k_page_rw/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/map_4k_page_rx/CMakeLists.txt b/loader/test/map_4k_page_rx/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/map_4k_page_rx/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/map_4k_page_rx/behavior.cpp b/loader/test/map_4k_page_rx/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/map_4k_page_rx/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/map_ext_elf_files/CMakeLists.txt b/loader/test/map_ext_elf_files/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/map_ext_elf_files/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/map_ext_elf_files/behavior.cpp b/loader/test/map_ext_elf_files/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/map_ext_elf_files/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/map_mk_args/CMakeLists.txt b/loader/test/map_mk_args/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/map_mk_args/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/map_mk_args/behavior.cpp b/loader/test/map_mk_args/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/map_mk_args/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/map_mk_debug_ring/CMakeLists.txt b/loader/test/map_mk_debug_ring/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/map_mk_debug_ring/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/map_mk_debug_ring/behavior.cpp b/loader/test/map_mk_debug_ring/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/map_mk_debug_ring/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/map_mk_elf_file/CMakeLists.txt b/loader/test/map_mk_elf_file/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/map_mk_elf_file/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/map_mk_elf_file/behavior.cpp b/loader/test/map_mk_elf_file/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/map_mk_elf_file/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/map_mk_elf_segments/CMakeLists.txt b/loader/test/map_mk_elf_segments/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/map_mk_elf_segments/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/map_mk_elf_segments/behavior.cpp b/loader/test/map_mk_elf_segments/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/map_mk_elf_segments/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/map_mk_huge_pool/CMakeLists.txt b/loader/test/map_mk_huge_pool/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/map_mk_huge_pool/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/map_mk_huge_pool/behavior.cpp b/loader/test/map_mk_huge_pool/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/map_mk_huge_pool/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/map_mk_page_pool/CMakeLists.txt b/loader/test/map_mk_page_pool/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/map_mk_page_pool/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/map_mk_page_pool/behavior.cpp b/loader/test/map_mk_page_pool/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/map_mk_page_pool/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/map_mk_stack/CMakeLists.txt b/loader/test/map_mk_stack/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/map_mk_stack/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/map_mk_stack/behavior.cpp b/loader/test/map_mk_stack/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/map_mk_stack/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/serial_write/CMakeLists.txt b/loader/test/serial_write/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/serial_write/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/serial_write/behavior.cpp b/loader/test/serial_write/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/serial_write/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/start_vmm/CMakeLists.txt b/loader/test/start_vmm/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/start_vmm/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/start_vmm/behavior.cpp b/loader/test/start_vmm/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/start_vmm/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/start_vmm_per_cpu/CMakeLists.txt b/loader/test/start_vmm_per_cpu/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/start_vmm_per_cpu/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/start_vmm_per_cpu/behavior.cpp b/loader/test/start_vmm_per_cpu/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/start_vmm_per_cpu/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/stop_and_free_the_vmm/CMakeLists.txt b/loader/test/stop_and_free_the_vmm/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/stop_and_free_the_vmm/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/stop_and_free_the_vmm/behavior.cpp b/loader/test/stop_and_free_the_vmm/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/stop_and_free_the_vmm/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/stop_vmm/CMakeLists.txt b/loader/test/stop_vmm/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/stop_vmm/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/stop_vmm/behavior.cpp b/loader/test/stop_vmm/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/stop_vmm/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/stop_vmm_per_cpu/CMakeLists.txt b/loader/test/stop_vmm_per_cpu/CMakeLists.txt new file mode 100644 index 00000000..6ea3a172 --- /dev/null +++ b/loader/test/stop_vmm_per_cpu/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${COMMON_INCLUDES} + SYSTEM_INCLUDES ${COMMON_SYSTEM_INCLUDES} + DEFINES ${DEFINES} +) diff --git a/loader/test/stop_vmm_per_cpu/behavior.cpp b/loader/test/stop_vmm_per_cpu/behavior.cpp new file mode 100644 index 00000000..ec58ce89 --- /dev/null +++ b/loader/test/stop_vmm_per_cpu/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/alloc_and_copy_mk_code_aliases/CMakeLists.txt b/loader/test/x64/alloc_and_copy_mk_code_aliases/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/alloc_and_copy_mk_code_aliases/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/alloc_and_copy_mk_code_aliases/behavior.cpp b/loader/test/x64/alloc_and_copy_mk_code_aliases/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/alloc_and_copy_mk_code_aliases/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/alloc_and_copy_mk_state/CMakeLists.txt b/loader/test/x64/alloc_and_copy_mk_state/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/alloc_and_copy_mk_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/alloc_and_copy_mk_state/behavior.cpp b/loader/test/x64/alloc_and_copy_mk_state/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/alloc_and_copy_mk_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/alloc_and_copy_root_vp_state/CMakeLists.txt b/loader/test/x64/alloc_and_copy_root_vp_state/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/alloc_and_copy_root_vp_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/alloc_and_copy_root_vp_state/behavior.cpp b/loader/test/x64/alloc_and_copy_root_vp_state/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/alloc_and_copy_root_vp_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/alloc_mk_root_page_table/CMakeLists.txt b/loader/test/x64/alloc_mk_root_page_table/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/alloc_mk_root_page_table/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/alloc_mk_root_page_table/behavior.cpp b/loader/test/x64/alloc_mk_root_page_table/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/alloc_mk_root_page_table/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/alloc_pdpt/CMakeLists.txt b/loader/test/x64/alloc_pdpt/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/alloc_pdpt/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/alloc_pdpt/behavior.cpp b/loader/test/x64/alloc_pdpt/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/alloc_pdpt/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/alloc_pdt/CMakeLists.txt b/loader/test/x64/alloc_pdt/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/alloc_pdt/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/alloc_pdt/behavior.cpp b/loader/test/x64/alloc_pdt/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/alloc_pdt/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/alloc_pt/CMakeLists.txt b/loader/test/x64/alloc_pt/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/alloc_pt/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/alloc_pt/behavior.cpp b/loader/test/x64/alloc_pt/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/alloc_pt/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/amd/check_cpu_configuration/CMakeLists.txt b/loader/test/x64/amd/check_cpu_configuration/CMakeLists.txt new file mode 100644 index 00000000..9b523acd --- /dev/null +++ b/loader/test/x64/amd/check_cpu_configuration/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AMD_INCLUDES} + SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} + DEFINES ${AMD_DEFINES} +) diff --git a/loader/test/x64/amd/check_cpu_configuration/behavior.cpp b/loader/test/x64/amd/check_cpu_configuration/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/x64/amd/check_cpu_configuration/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/amd/disable_hve/CMakeLists.txt b/loader/test/x64/amd/disable_hve/CMakeLists.txt new file mode 100644 index 00000000..9b523acd --- /dev/null +++ b/loader/test/x64/amd/disable_hve/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AMD_INCLUDES} + SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} + DEFINES ${AMD_DEFINES} +) diff --git a/loader/test/x64/amd/disable_hve/behavior.cpp b/loader/test/x64/amd/disable_hve/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/x64/amd/disable_hve/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/amd/enable_hve/CMakeLists.txt b/loader/test/x64/amd/enable_hve/CMakeLists.txt new file mode 100644 index 00000000..9b523acd --- /dev/null +++ b/loader/test/x64/amd/enable_hve/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${AMD_INCLUDES} + SYSTEM_INCLUDES ${AMD_SYSTEM_INCLUDES} + DEFINES ${AMD_DEFINES} +) diff --git a/loader/test/x64/amd/enable_hve/behavior.cpp b/loader/test/x64/amd/enable_hve/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/x64/amd/enable_hve/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/dump_mk_code_aliases/CMakeLists.txt b/loader/test/x64/dump_mk_code_aliases/CMakeLists.txt new file mode 100644 index 00000000..0e72e420 --- /dev/null +++ b/loader/test/x64/dump_mk_code_aliases/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/x64/dump_mk_code_aliases.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/dump_mk_code_aliases/behavior.cpp b/loader/test/x64/dump_mk_code_aliases/behavior.cpp new file mode 100644 index 00000000..b7fac643 --- /dev/null +++ b/loader/test/x64/dump_mk_code_aliases/behavior.cpp @@ -0,0 +1,76 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_code_aliases.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null a"} = []() { + bsl::ut_then{} = []() { + dump_mk_code_aliases(nullptr); + }; + }; + + bsl::ut_scenario{"success"} = []() { + code_aliases_t a{}; + bsl::ut_then{} = [&]() { + dump_mk_code_aliases(&a); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/dump_mk_state/CMakeLists.txt b/loader/test/x64/dump_mk_state/CMakeLists.txt new file mode 100644 index 00000000..ae4d4a4d --- /dev/null +++ b/loader/test/x64/dump_mk_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/x64/dump_mk_state.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/dump_mk_state/behavior.cpp b/loader/test/x64/dump_mk_state/behavior.cpp new file mode 100644 index 00000000..414e0ec1 --- /dev/null +++ b/loader/test/x64/dump_mk_state/behavior.cpp @@ -0,0 +1,85 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_state.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null state"} = []() { + bsl::ut_then{} = []() { + dump_mk_state(nullptr, {}); + }; + }; + + bsl::ut_scenario{"null tss"} = []() { + state_save_t state{}; + bsl::ut_then{} = [&]() { + dump_mk_state(&state, {}); + }; + }; + + bsl::ut_scenario{"success"} = []() { + tss_t tss{}; + state_save_t state{}; + state.tss = &tss; + bsl::ut_then{} = [&]() { + dump_mk_state(&state, {}); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/dump_root_vp_state/CMakeLists.txt b/loader/test/x64/dump_root_vp_state/CMakeLists.txt new file mode 100644 index 00000000..ec4e2b88 --- /dev/null +++ b/loader/test/x64/dump_root_vp_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/x64/dump_root_vp_state.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/dump_root_vp_state/behavior.cpp b/loader/test/x64/dump_root_vp_state/behavior.cpp new file mode 100644 index 00000000..c8bd13ec --- /dev/null +++ b/loader/test/x64/dump_root_vp_state/behavior.cpp @@ -0,0 +1,76 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_root_vp_state.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"null state"} = []() { + bsl::ut_then{} = []() { + dump_root_vp_state(nullptr, {}); + }; + }; + + bsl::ut_scenario{"success"} = []() { + state_save_t state{}; + bsl::ut_then{} = [&]() { + dump_root_vp_state(&state, {}); + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/free_mk_code_aliases/CMakeLists.txt b/loader/test/x64/free_mk_code_aliases/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/free_mk_code_aliases/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/free_mk_code_aliases/behavior.cpp b/loader/test/x64/free_mk_code_aliases/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/free_mk_code_aliases/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/free_mk_root_page_table/CMakeLists.txt b/loader/test/x64/free_mk_root_page_table/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/free_mk_root_page_table/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/free_mk_root_page_table/behavior.cpp b/loader/test/x64/free_mk_root_page_table/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/free_mk_root_page_table/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/free_mk_state/CMakeLists.txt b/loader/test/x64/free_mk_state/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/free_mk_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/free_mk_state/behavior.cpp b/loader/test/x64/free_mk_state/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/free_mk_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/free_pdpt/CMakeLists.txt b/loader/test/x64/free_pdpt/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/free_pdpt/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/free_pdpt/behavior.cpp b/loader/test/x64/free_pdpt/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/free_pdpt/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/free_pdt/CMakeLists.txt b/loader/test/x64/free_pdt/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/free_pdt/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/free_pdt/behavior.cpp b/loader/test/x64/free_pdt/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/free_pdt/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/free_pml4t/CMakeLists.txt b/loader/test/x64/free_pml4t/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/free_pml4t/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/free_pml4t/behavior.cpp b/loader/test/x64/free_pml4t/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/free_pml4t/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/free_root_vp_state/CMakeLists.txt b/loader/test/x64/free_root_vp_state/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/free_root_vp_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/free_root_vp_state/behavior.cpp b/loader/test/x64/free_root_vp_state/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/free_root_vp_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/get_gdt_descriptor_attrib/CMakeLists.txt b/loader/test/x64/get_gdt_descriptor_attrib/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/get_gdt_descriptor_attrib/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/get_gdt_descriptor_attrib/behavior.cpp b/loader/test/x64/get_gdt_descriptor_attrib/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/get_gdt_descriptor_attrib/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/get_gdt_descriptor_base/CMakeLists.txt b/loader/test/x64/get_gdt_descriptor_base/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/get_gdt_descriptor_base/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/get_gdt_descriptor_base/behavior.cpp b/loader/test/x64/get_gdt_descriptor_base/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/get_gdt_descriptor_base/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/get_gdt_descriptor_limit/CMakeLists.txt b/loader/test/x64/get_gdt_descriptor_limit/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/get_gdt_descriptor_limit/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/get_gdt_descriptor_limit/behavior.cpp b/loader/test/x64/get_gdt_descriptor_limit/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/get_gdt_descriptor_limit/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/intel/check_cpu_configuration/CMakeLists.txt b/loader/test/x64/intel/check_cpu_configuration/CMakeLists.txt new file mode 100644 index 00000000..652c46f2 --- /dev/null +++ b/loader/test/x64/intel/check_cpu_configuration/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${INTEL_INCLUDES} + SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} + DEFINES ${INTEL_DEFINES} +) diff --git a/loader/test/x64/intel/check_cpu_configuration/behavior.cpp b/loader/test/x64/intel/check_cpu_configuration/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/x64/intel/check_cpu_configuration/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/intel/disable_hve/CMakeLists.txt b/loader/test/x64/intel/disable_hve/CMakeLists.txt new file mode 100644 index 00000000..652c46f2 --- /dev/null +++ b/loader/test/x64/intel/disable_hve/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${INTEL_INCLUDES} + SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} + DEFINES ${INTEL_DEFINES} +) diff --git a/loader/test/x64/intel/disable_hve/behavior.cpp b/loader/test/x64/intel/disable_hve/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/x64/intel/disable_hve/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/intel/enable_hve/CMakeLists.txt b/loader/test/x64/intel/enable_hve/CMakeLists.txt new file mode 100644 index 00000000..652c46f2 --- /dev/null +++ b/loader/test/x64/intel/enable_hve/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${INTEL_INCLUDES} + SYSTEM_INCLUDES ${INTEL_SYSTEM_INCLUDES} + DEFINES ${INTEL_DEFINES} +) diff --git a/loader/test/x64/intel/enable_hve/behavior.cpp b/loader/test/x64/intel/enable_hve/behavior.cpp new file mode 100644 index 00000000..e9b2950c --- /dev/null +++ b/loader/test/x64/intel/enable_hve/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/map_4k_page/CMakeLists.txt b/loader/test/x64/map_4k_page/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/map_4k_page/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/map_4k_page/behavior.cpp b/loader/test/x64/map_4k_page/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/map_4k_page/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/map_mk_code_aliases/CMakeLists.txt b/loader/test/x64/map_mk_code_aliases/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/map_mk_code_aliases/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/map_mk_code_aliases/behavior.cpp b/loader/test/x64/map_mk_code_aliases/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/map_mk_code_aliases/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/map_mk_state/CMakeLists.txt b/loader/test/x64/map_mk_state/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/map_mk_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/map_mk_state/behavior.cpp b/loader/test/x64/map_mk_state/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/map_mk_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/map_root_vp_state/CMakeLists.txt b/loader/test/x64/map_root_vp_state/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/map_root_vp_state/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/map_root_vp_state/behavior.cpp b/loader/test/x64/map_root_vp_state/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/map_root_vp_state/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/send_command_report_off/CMakeLists.txt b/loader/test/x64/send_command_report_off/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/send_command_report_off/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/send_command_report_off/behavior.cpp b/loader/test/x64/send_command_report_off/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/send_command_report_off/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/send_command_report_on/CMakeLists.txt b/loader/test/x64/send_command_report_on/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/send_command_report_on/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/send_command_report_on/behavior.cpp b/loader/test/x64/send_command_report_on/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/send_command_report_on/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/send_command_stop/CMakeLists.txt b/loader/test/x64/send_command_stop/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/send_command_stop/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/send_command_stop/behavior.cpp b/loader/test/x64/send_command_stop/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/send_command_stop/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/serial_init/CMakeLists.txt b/loader/test/x64/serial_init/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/serial_init/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/serial_init/behavior.cpp b/loader/test/x64/serial_init/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/serial_init/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/set_gdt_descriptor/CMakeLists.txt b/loader/test/x64/set_gdt_descriptor/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/set_gdt_descriptor/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/set_gdt_descriptor/behavior.cpp b/loader/test/x64/set_gdt_descriptor/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/set_gdt_descriptor/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/test/x64/set_idt_descriptor/CMakeLists.txt b/loader/test/x64/set_idt_descriptor/CMakeLists.txt new file mode 100644 index 00000000..f6969d50 --- /dev/null +++ b/loader/test/x64/set_idt_descriptor/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ${CMAKE_CURRENT_LIST_DIR}/../../../src/dump_mk_stack.c +) + +bf_add_test(behavior + SOURCES ${SOURCES} + INCLUDES ${X64_INCLUDES} + SYSTEM_INCLUDES ${X64_SYSTEM_INCLUDES} + DEFINES ${X64_DEFINES} +) diff --git a/loader/test/x64/set_idt_descriptor/behavior.cpp b/loader/test/x64/set_idt_descriptor/behavior.cpp new file mode 100644 index 00000000..9d681b8b --- /dev/null +++ b/loader/test/x64/set_idt_descriptor/behavior.cpp @@ -0,0 +1,73 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +extern "C" +{ +#include "../../../include/dump_mk_stack.h" +} + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"description"} = []() { + bsl::ut_given{} = []() { + bsl::ut_when{} = []() { + bsl::ut_then{} = []() { + bsl::ut_check(true); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return mk::tests(); +} diff --git a/loader/windows/include/platform_interface/c/loader_platform_interface.h b/loader/windows/include/platform_interface/c/loader_platform_interface.h index 0c86293c..bc3594cf 100644 --- a/loader/windows/include/platform_interface/c/loader_platform_interface.h +++ b/loader/windows/include/platform_interface/c/loader_platform_interface.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/windows/include/platform_interface/cpp/loader_platform_interface.hpp b/loader/windows/include/platform_interface/cpp/loader_platform_interface.hpp index e619cf0c..5bb6727c 100644 --- a/loader/windows/include/platform_interface/cpp/loader_platform_interface.hpp +++ b/loader/windows/include/platform_interface/cpp/loader_platform_interface.hpp @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/windows/include/std/stdint.h b/loader/windows/include/std/stdint.h index 76839352..31f9d488 100644 --- a/loader/windows/include/std/stdint.h +++ b/loader/windows/include/std/stdint.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/loader/windows/include/types.h b/loader/windows/include/types.h index 1966538a..2c1ea796 100644 --- a/loader/windows/include/types.h +++ b/loader/windows/include/types.h @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. @@ -29,7 +27,7 @@ #ifndef TYPES_H #define TYPES_H -#include "stdint.h" +#include /** * @brief Returned by a loader function when a function succeeds. diff --git a/loader/windows/loader.inf b/loader/windows/loader.inf index ab30c33c..c739d839 100644 --- a/loader/windows/loader.inf +++ b/loader/windows/loader.inf @@ -8,7 +8,7 @@ Class=System ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} Provider=%ManufacturerName% CatalogFile=loader.cat -DriverVer= ; TODO: set DriverVer in stampinf property pages +DriverVer= ; PnpLockdown=1 [DestinationDirs] diff --git a/loader/windows/loader.vcxproj b/loader/windows/loader.vcxproj index 2ce9eb33..a75b4467 100644 --- a/loader/windows/loader.vcxproj +++ b/loader/windows/loader.vcxproj @@ -10,6 +10,178 @@ x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -30,6 +202,7 @@ + @@ -40,120 +213,114 @@ + + + + + + + + - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - + + + + + + + @@ -199,10 +366,10 @@ DbgengKernelDebugger - $(IncludePath);$(CMAKE_BINARY_DIR)\include;include;include\std;include\platform_interface\c;..\include;..\include\interface\c;..\include\interface\c\bfelf;include\x64;include\x64\amd;..\include\x64;..\include\x64\amd;..\include\interface\c\x64;..\include\interface\c\x64\amd + $(IncludePath);$(CMAKE_BINARY_DIR)\include;include;include\std;include\platform_interface\c;..\include;..\include\interface\c;include\x64;include\x64\amd;..\include\x64;..\include\x64\amd;..\include\interface\c\x64;..\include\interface\c\x64\amd - $(IncludePath);$(CMAKE_BINARY_DIR)\include;include;include\std;include\platform_interface\c;..\include;..\include\interface\c;..\include\interface\c\bfelf;include\x64;include\x64\intel;..\include\x64;..\include\x64\intel;..\include\interface\c\x64;..\include\interface\c\x64\intel + $(IncludePath);$(CMAKE_BINARY_DIR)\include;include;include\std;include\platform_interface\c;..\include;..\include\interface\c;include\x64;include\x64\intel;..\include\x64;..\include\x64\intel;..\include\interface\c\x64;..\include\interface\c\x64\intel diff --git a/loader/windows/src/platform.c b/loader/windows/src/platform.c index 0669865b..f96ca645 100644 --- a/loader/windows/src/platform.c +++ b/loader/windows/src/platform.c @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. @@ -557,3 +555,26 @@ platform_on_each_cpu(platform_per_cpu_func const func, uint32_t const order) return ret; } + +/** + * + * @brief Dumps the contents of the VMM's ring buffer. + */ +void +platform_dump_vmm(void) +{} + +/** + * + * @brief Initializes the archiecture. Some platforms might need per CPU + * initialization logic to get the CPU set up. Most platforms ignore + * calls to this function + * + * + * @return Returns 0 on success, LOADER_FAILURE otherwise + */ +int64_t +platform_arch_init(void) +{ + return LOADER_SUCCESS; +} diff --git a/loader/windows/src/x64/demote.asm b/loader/windows/src/x64/demote.asm index 34d4e08e..57885bd7 100644 --- a/loader/windows/src/x64/demote.asm +++ b/loader/windows/src/x64/demote.asm @@ -22,35 +22,163 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. + ; @brief defines the offset of state_save_t.rax + SS_OFFSET_RAX EQU 000h + ; @brief defines the offset of state_save_t.rbx + SS_OFFSET_RBX EQU 008h + ; @brief defines the offset of state_save_t.rcx + SS_OFFSET_RCX EQU 010h + ; @brief defines the offset of state_save_t.rdx + SS_OFFSET_RDX EQU 018h + ; @brief defines the offset of state_save_t.rbp + SS_OFFSET_RBP EQU 020h + ; @brief defines the offset of state_save_t.rsi + SS_OFFSET_RSI EQU 028h + ; @brief defines the offset of state_save_t.rdi + SS_OFFSET_RDI EQU 030h + ; @brief defines the offset of state_save_t.r8 + SS_OFFSET_R8 EQU 038h + ; @brief defines the offset of state_save_t.r9 + SS_OFFSET_R9 EQU 040h + ; @brief defines the offset of state_save_t.r10 + SS_OFFSET_R10 EQU 048h + ; @brief defines the offset of state_save_t.r11 + SS_OFFSET_R11 EQU 050h + ; @brief defines the offset of state_save_t.r12 + SS_OFFSET_R12 EQU 058h + ; @brief defines the offset of state_save_t.r13 + SS_OFFSET_R13 EQU 060h + ; @brief defines the offset of state_save_t.r14 + SS_OFFSET_R14 EQU 068h + ; @brief defines the offset of state_save_t.r15 + SS_OFFSET_R15 EQU 070h + ; @brief defines the offset of state_save_t.rip + SS_OFFSET_RIP EQU 078h + ; @brief defines the offset of state_save_t.rsp + SS_OFFSET_RSP EQU 080h + ; @brief defines the offset of state_save_t.rflags + SS_OFFSET_RFLAGS EQU 088h + ; @brief defines the offset of state_save_t.gdtr + SS_OFFSET_GDTR EQU 0A0h + ; @brief defines the offset of state_save_t.idtr + SS_OFFSET_IDTR EQU 0B0h + ; @brief defines the offset of state_save_t.es_selector + SS_OFFSET_ES_SELECTOR EQU 0C0h + ; @brief defines the offset of state_save_t.cs_selector + SS_OFFSET_CS_SELECTOR EQU 0D0h + ; @brief defines the offset of state_save_t.ss_selector + SS_OFFSET_SS_SELECTOR EQU 0E0h + ; @brief defines the offset of state_save_t.ds_selector + SS_OFFSET_DS_SELECTOR EQU 0F0h + ; @brief defines the offset of state_save_t.fs_selector + SS_OFFSET_FS_SELECTOR EQU 100h + ; @brief defines the offset of state_save_t.gs_selector + SS_OFFSET_GS_SELECTOR EQU 110h + ; @brief defines the offset of state_save_t.ldtr_selector + SS_OFFSET_LDTR_SELECTOR EQU 120h + ; @brief defines the offset of state_save_t.tr_selector + SS_OFFSET_TR_SELECTOR EQU 130h + ; @brief defines the offset of state_save_t.cr0 + SS_OFFSET_CR0 EQU 140h + ; @brief defines the offset of state_save_t.cr2 + SS_OFFSET_CR2 EQU 150h + ; @brief defines the offset of state_save_t.cr3 + SS_OFFSET_CR3 EQU 158h + ; @brief defines the offset of state_save_t.cr4 + SS_OFFSET_CR4 EQU 160h + ; @brief defines the offset of state_save_t.dr6 + SS_OFFSET_DR6 EQU 1F0h + ; @brief defines the offset of state_save_t.dr7 + SS_OFFSET_DR7 EQU 1F8h + ; @brief defines the offset of state_save_t.ia32_efer + SS_OFFSET_IA32_EFER EQU 240h + ; @brief defines the offset of state_save_t.ia32_star + SS_OFFSET_IA32_STAR EQU 248h + ; @brief defines the offset of state_save_t.ia32_lstar + SS_OFFSET_IA32_LSTAR EQU 250h + ; @brief defines the offset of state_save_t.ia32_cstar + SS_OFFSET_IA32_CSTAR EQU 258h + ; @brief defines the offset of state_save_t.ia32_fmask + SS_OFFSET_IA32_FMASK EQU 260h + ; @brief defines the offset of state_save_t.ia32_fs_base + SS_OFFSET_IA32_FS_BASE EQU 268h + ; @brief defines the offset of state_save_t.ia32_gs_base + SS_OFFSET_IA32_GS_BASE EQU 270h + ; @brief defines the offset of state_save_t.ia32_kernel_gs_base + SS_OFFSET_IA32_KERNEL_GS_BASE EQU 278h + ; @brief defines the offset of state_save_t.ia32_sysenter_cs + SS_OFFSET_IA32_SYSENTER_CS EQU 280h + ; @brief defines the offset of state_save_t.ia32_sysenter_esp + SS_OFFSET_IA32_SYSENTER_ESP EQU 288h + ; @brief defines the offset of state_save_t.ia32_sysenter_eip + SS_OFFSET_IA32_SYSENTER_EIP EQU 290h + ; @brief defines the offset of state_save_t.ia32_pat + SS_OFFSET_IA32_PAT EQU 298h + ; @brief defines the offset of state_save_t.ia32_debugctl + SS_OFFSET_IA32_DEBUGCTL EQU 2A0h + + ; @brief defines MSR_IA32_SYSENTER_CS + MSR_IA32_SYSENTER_CS EQU 00000174h + ; @brief defines MSR_IA32_SYSENTER_ESP + MSR_IA32_SYSENTER_ESP EQU 00000175h + ; @brief defines MSR_IA32_SYSENTER_EIP + MSR_IA32_SYSENTER_EIP EQU 00000176h + ; @brief defines MSR_IA32_DEBUGCTL + MSR_IA32_DEBUGCTL EQU 000001D9h + ; @brief defines MSR_IA32_PAT + MSR_IA32_PAT EQU 00000277h + ; @brief defines MSR_IA32_EFER + MSR_IA32_EFER EQU 0C0000080h + ; @brief defines MSR_IA32_STAR + MSR_IA32_STAR EQU 0C0000081h + ; @brief defines MSR_IA32_LSTAR + MSR_IA32_LSTAR EQU 0C0000082h + ; @brief defines MSR_IA32_CSTAR + MSR_IA32_CSTAR EQU 0C0000083h + ; @brief defines MSR_IA32_FMASK + MSR_IA32_FMASK EQU 0C0000084h + ; @brief defines MSR_IA32_FS_BASE + MSR_IA32_FS_BASE EQU 0C0000100h + ; @brief defines MSR_IA32_GS_BASE + MSR_IA32_GS_BASE EQU 0C0000101h + ; @brief defines MSR_IA32_KERNEL_GS_BASE + MSR_IA32_KERNEL_GS_BASE EQU 0C0000102h + enable_interrupts PROTO disable_interrupts PROTO demote_text SEGMENT ALIGN(1000h) 'CODE' demote PROC + ; ************************************************************************** + ; Report Success On Completion + ; ************************************************************************** + + xor rax, rax + ; ************************************************************************** ; General Purpose Registers ; ************************************************************************** - mov [r8 + 000h], rax - mov [r8 + 008h], rbx - mov [r8 + 010h], rcx - mov [r8 + 018h], r8 - mov [r8 + 020h], rbp - mov [r8 + 028h], rsi - mov [r8 + 030h], rdi - mov [r8 + 038h], r8 - mov [r8 + 040h], r9 - mov [r8 + 048h], r10 - mov [r8 + 050h], r11 - mov [r8 + 058h], r12 - mov [r8 + 060h], r13 - mov [r8 + 068h], r14 - mov [r8 + 070h], r15 + mov [r8 + SS_OFFSET_RAX], rax + mov [r8 + SS_OFFSET_RBX], rbx + mov [r8 + SS_OFFSET_RCX], rcx + mov [r8 + SS_OFFSET_RDX], rdx + mov [r8 + SS_OFFSET_RBP], rbp + mov [r8 + SS_OFFSET_RSI], rsi + mov [r8 + SS_OFFSET_RDI], rdi + mov [r8 + SS_OFFSET_R8], r8 + mov [r8 + SS_OFFSET_R9], r9 + mov [r8 + SS_OFFSET_R10], r10 + mov [r8 + SS_OFFSET_R11], r11 + mov [r8 + SS_OFFSET_R12], r12 + mov [r8 + SS_OFFSET_R13], r13 + mov [r8 + SS_OFFSET_R14], r14 + mov [r8 + SS_OFFSET_R15], r15 - lea rax, [demotion_success] - mov [r8 + 078h], rax - mov [r8 + 080h], rsp + lea rax, [demotion_return] + mov [r8 + SS_OFFSET_RIP], rax + mov [r8 + SS_OFFSET_RSP], rsp ; ************************************************************************** ; Setup @@ -65,9 +193,9 @@ ; ************************************************************************** pushfq - pop [r15 + 088h] - push [r14 + 088h] - popf + pop qword ptr[r15 + SS_OFFSET_RFLAGS] + push qword ptr[r14 + SS_OFFSET_RFLAGS] + popfq ; ************************************************************************** ; IDT @@ -75,168 +203,162 @@ call disable_interrupts - sidt fword ptr[r15 + 0B0h] - lidt fword ptr[r14 + 0B0h] + sidt fword ptr[r15 + SS_OFFSET_IDTR] + lidt fword ptr[r14 + SS_OFFSET_IDTR] ; ************************************************************************** ; MSRs ; ************************************************************************** - mov ecx, 0C0000080h ; EFER + mov ecx, MSR_IA32_EFER rdmsr - mov [r15 + 240h], eax - mov [r15 + 244h], edx - mov eax, [r14 + 240h] - mov edx, [r14 + 244h] + mov [r15 + SS_OFFSET_IA32_EFER + 0h], eax + mov [r15 + SS_OFFSET_IA32_EFER + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_EFER + 0h] + mov edx, [r14 + SS_OFFSET_IA32_EFER + 4h] wrmsr - mov ecx, 0C0000081h ; STAR + mov ecx, MSR_IA32_STAR rdmsr - mov [r15 + 248h], eax - mov [r15 + 24Ch], edx - mov eax, [r14 + 248h] - mov edx, [r14 + 24Ch] + mov [r15 + SS_OFFSET_IA32_STAR + 0h], eax + mov [r15 + SS_OFFSET_IA32_STAR + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_STAR + 0h] + mov edx, [r14 + SS_OFFSET_IA32_STAR + 4h] wrmsr - mov ecx, 0C0000082h ; LSTAR + mov ecx, MSR_IA32_LSTAR rdmsr - mov [r15 + 250h], eax - mov [r15 + 254h], edx - mov eax, [r14 + 250h] - mov edx, [r14 + 254h] + mov [r15 + SS_OFFSET_IA32_LSTAR + 0h], eax + mov [r15 + SS_OFFSET_IA32_LSTAR + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_LSTAR + 0h] + mov edx, [r14 + SS_OFFSET_IA32_LSTAR + 4h] wrmsr - mov ecx, 0C0000083h ; CSTAR + mov ecx, MSR_IA32_CSTAR rdmsr - mov [r15 + 258h], eax - mov [r15 + 25Ch], edx - mov eax, [r14 + 258h] - mov edx, [r14 + 25Ch] + mov [r15 + SS_OFFSET_IA32_CSTAR + 0h], eax + mov [r15 + SS_OFFSET_IA32_CSTAR + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_CSTAR + 0h] + mov edx, [r14 + SS_OFFSET_IA32_CSTAR + 4h] wrmsr - mov ecx, 0C0000084h ; FMASK + mov ecx, MSR_IA32_FMASK rdmsr - mov [r15 + 260h], eax - mov [r15 + 264h], edx - mov eax, [r14 + 260h] - mov edx, [r14 + 264h] + mov [r15 + SS_OFFSET_IA32_FMASK + 0h], eax + mov [r15 + SS_OFFSET_IA32_FMASK + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_FMASK + 0h] + mov edx, [r14 + SS_OFFSET_IA32_FMASK + 4h] wrmsr - mov ecx, 0C0000100h ; FS Base + mov ecx, MSR_IA32_FS_BASE rdmsr - mov [r15 + 268h], eax - mov [r15 + 26Ch], edx - mov eax, [r14 + 268h] - mov edx, [r14 + 26Ch] + mov [r15 + SS_OFFSET_IA32_FS_BASE + 0h], eax + mov [r15 + SS_OFFSET_IA32_FS_BASE + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_FS_BASE + 0h] + mov edx, [r14 + SS_OFFSET_IA32_FS_BASE + 4h] wrmsr - mov ecx, 0C0000101h ; GS Base + mov ecx, MSR_IA32_GS_BASE rdmsr - mov [r15 + 270h], eax - mov [r15 + 274h], edx - mov eax, [r14 + 270h] - mov edx, [r14 + 274h] + mov [r15 + SS_OFFSET_IA32_GS_BASE + 0h], eax + mov [r15 + SS_OFFSET_IA32_GS_BASE + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_GS_BASE + 0h] + mov edx, [r14 + SS_OFFSET_IA32_GS_BASE + 4h] wrmsr - mov ecx, 0C0000102h ; Kernel GS Base + mov ecx, MSR_IA32_KERNEL_GS_BASE rdmsr - mov [r15 + 278h], eax - mov [r15 + 27Ch], edx - mov eax, [r14 + 278h] - mov edx, [r14 + 27Ch] + mov [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0h], eax + mov [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0h] + mov edx, [r14 + SS_OFFSET_IA32_KERNEL_GS_BASE + 4h] wrmsr - mov ecx, 00000174h ; SYSENTER_CS + mov ecx, MSR_IA32_SYSENTER_CS rdmsr - mov [r15 + 280h], eax - mov [r15 + 284h], edx - mov eax, [r14 + 280h] - mov edx, [r14 + 284h] + mov [r15 + SS_OFFSET_IA32_SYSENTER_CS + 0h], eax + mov [r15 + SS_OFFSET_IA32_SYSENTER_CS + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_SYSENTER_CS + 0h] + mov edx, [r14 + SS_OFFSET_IA32_SYSENTER_CS + 4h] wrmsr - mov ecx, 00000175h ; SYSENTER_ESP + mov ecx, MSR_IA32_SYSENTER_ESP rdmsr - mov [r15 + 288h], eax - mov [r15 + 28Ch], edx - mov eax, [r14 + 288h] - mov edx, [r14 + 28Ch] + mov [r15 + SS_OFFSET_IA32_SYSENTER_ESP + 0h], eax + mov [r15 + SS_OFFSET_IA32_SYSENTER_ESP + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_SYSENTER_ESP + 0h] + mov edx, [r14 + SS_OFFSET_IA32_SYSENTER_ESP + 4h] wrmsr - mov ecx, 00000176h ; SYSENTER_EIP + mov ecx, MSR_IA32_SYSENTER_EIP rdmsr - mov [r15 + 290h], eax - mov [r15 + 294h], edx - mov eax, [r14 + 290h] - mov edx, [r14 + 294h] + mov [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0h], eax + mov [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_SYSENTER_EIP + 0h] + mov edx, [r14 + SS_OFFSET_IA32_SYSENTER_EIP + 4h] wrmsr - mov ecx, 00000277h ; PAT + mov ecx, MSR_IA32_PAT rdmsr - mov [r15 + 298h], eax - mov [r15 + 29Ch], edx - mov eax, [r14 + 298h] - mov edx, [r14 + 29Ch] + mov [r15 + SS_OFFSET_IA32_PAT + 0h], eax + mov [r15 + SS_OFFSET_IA32_PAT + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_PAT + 0h] + mov edx, [r14 + SS_OFFSET_IA32_PAT + 4h] wrmsr - mov ecx, 000001D9h ; DEBUGCTL + mov ecx, MSR_IA32_DEBUGCTL rdmsr - mov [r15 + 2A0h], eax - mov [r15 + 2A4h], edx - mov eax, [r14 + 2A0h] - mov edx, [r14 + 2A4h] + mov [r15 + SS_OFFSET_IA32_DEBUGCTL + 0h], eax + mov [r15 + SS_OFFSET_IA32_DEBUGCTL + 4h], edx + mov eax, [r14 + SS_OFFSET_IA32_DEBUGCTL + 0h] + mov edx, [r14 + SS_OFFSET_IA32_DEBUGCTL + 4h] wrmsr ; ************************************************************************** ; GDT ; ************************************************************************** - sgdt fword ptr[r15 + 0A0h] - lgdt fword ptr[r14 + 0A0h] + sgdt fword ptr[r15 + SS_OFFSET_GDTR] + lgdt fword ptr[r14 + SS_OFFSET_GDTR] mov dx, es - mov [r15 + 0C0h], dx - mov dx, [r14 + 0C0h] + mov [r15 + SS_OFFSET_ES_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_ES_SELECTOR] mov es, dx mov dx, cs - mov [r15 + 0D0h], dx - mov ax, [r14 + 0D0h] + mov [r15 + SS_OFFSET_CS_SELECTOR], dx + mov ax, [r14 + SS_OFFSET_CS_SELECTOR] push rax mov dx, ss - mov [r15 + 0E0h], dx - mov dx, [r14 + 0E0h] + mov [r15 + SS_OFFSET_SS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_SS_SELECTOR] mov ss, dx mov dx, ds - mov [r15 + 0F0h], dx - mov dx, [r14 + 0F0h] + mov [r15 + SS_OFFSET_DS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_DS_SELECTOR] mov ds, dx mov dx, fs - mov [r15 + 100h], dx - mov dx, [r14 + 100h] + mov [r15 + SS_OFFSET_FS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_FS_SELECTOR] mov fs, dx mov dx, gs - mov [r15 + 110h], dx - mov dx, [r14 + 110h] + mov [r15 + SS_OFFSET_GS_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_GS_SELECTOR] mov gs, dx - mov ecx, 000001D9h - xor rax, rax - xor rdx, rdx - mov ax, [r14 + 110h] - wrmsr - sldt dx - mov [r15 + 120h], dx - mov dx, [r14 + 120h] + mov [r15 + SS_OFFSET_LDTR_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_LDTR_SELECTOR] lldt dx str dx - mov [r15 + 130h], dx - mov dx, [r14 + 130h] + mov [r15 + SS_OFFSET_TR_SELECTOR], dx + mov dx, [r14 + SS_OFFSET_TR_SELECTOR] ltr dx lea rax, [gdt_and_cs_loaded] @@ -251,39 +373,43 @@ gdt_and_cs_loaded: ; ************************************************************************** mov rax, cr0 - mov [r15 + 140h], rax - mov rax, [r14 + 140h] + mov [r15 + SS_OFFSET_CR0], rax + mov rax, [r14 + SS_OFFSET_CR0] mov cr0, rax mov rax, cr2 - mov [r15 + 150h], rax - mov rax, [r14 + 150h] + mov [r15 + SS_OFFSET_CR2], rax + mov rax, [r14 + SS_OFFSET_CR2] mov cr2, rax mov rax, cr4 - mov [r15 + 160h], rax - mov rax, [r14 + 160h] + mov [r15 + SS_OFFSET_CR4], rax + mov rax, [r14 + SS_OFFSET_CR4] mov cr4, rax mov rax, cr3 - mov [r15 + 158h], rax - mov rax, [r14 + 158h] + mov [r15 + SS_OFFSET_CR3], rax + mov rax, [r14 + SS_OFFSET_CR3] mov cr3, rax - mov rsp, [r14 + 080h] + ; ************************************************************************** + ; Stack + ; ************************************************************************** + + mov rsp, [r14 + SS_OFFSET_RSP] ; ************************************************************************** ; Debug Registers ; ************************************************************************** mov rax, dr6 - mov [r15 + 1F0h], rax - mov rax, [r14 + 1F0h] + mov [r15 + SS_OFFSET_DR6], rax + mov rax, [r14 + SS_OFFSET_DR6] mov dr6, rax mov rax, dr7 - mov [r15 + 1F8h], rax - mov rax, [r14 + 1F8h] + mov [r15 + SS_OFFSET_DR7], rax + mov rax, [r14 + SS_OFFSET_DR7] mov dr7, rax ; ************************************************************************** @@ -291,11 +417,11 @@ gdt_and_cs_loaded: ; ************************************************************************** mov rdi, r13 - push [r14 + 078h] + push qword ptr[r14 + SS_OFFSET_RIP] ret int 3 -demotion_success: +demotion_return: ; NOTE: diff --git a/loader/windows/src/x64/esr_default.asm b/loader/windows/src/x64/esr_default.asm index 04ee9dcc..05e14a32 100644 --- a/loader/windows/src/x64/esr_default.asm +++ b/loader/windows/src/x64/esr_default.asm @@ -22,27 +22,50 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. + serial_write_c PROTO + esr_default_text SEGMENT ALIGN(1000h) 'CODE' esr_default PROC - mov rdx, 03F8h - mov rax, 45h - out dx, al + mov rcx, 'e' + call serial_write_c - mov rdx, 03F8h - mov rax, 53h - out dx, al + mov rcx, 's' + call serial_write_c - mov rdx, 03F8h - mov rax, 52h - out dx, al + mov rcx, 'r' + call serial_write_c + + mov rcx, '_' + call serial_write_c + + mov rcx, 'd' + call serial_write_c + + mov rcx, 'e' + call serial_write_c + + mov rcx, 'f' + call serial_write_c + + mov rcx, 'a' + call serial_write_c + + mov rcx, 'u' + call serial_write_c + + mov rcx, 'l' + call serial_write_c + + mov rcx, 't' + call serial_write_c + + mov rcx, '\n' + call serial_write_c cli hlt - ret - int 3 - esr_default ENDP esr_default_text ENDS end diff --git a/loader/windows/src/x64/esr_df.asm b/loader/windows/src/x64/esr_df.asm index fe56136a..6d4903c2 100644 --- a/loader/windows/src/x64/esr_df.asm +++ b/loader/windows/src/x64/esr_df.asm @@ -22,39 +22,35 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. + serial_write_c PROTO + esr_df_text SEGMENT ALIGN(1000h) 'CODE' esr_df PROC - mov rdx, 03F8h - mov rax, 45h - out dx, al + mov rcx, 'e' + call serial_write_c - mov rdx, 03F8h - mov rax, 53h - out dx, al + mov rcx, 's' + call serial_write_c - mov rdx, 03F8h - mov rax, 52h - out dx, al + mov rcx, 'r' + call serial_write_c - mov rdx, 03F8h - mov rax, 20h - out dx, al + mov rcx, '_' + call serial_write_c - mov rdx, 03F8h - mov rax, 44h - out dx, al + mov rcx, 'd' + call serial_write_c - mov rdx, 03F8h - mov rax, 46h - out dx, al + mov rcx, 'f' + call serial_write_c + + mov rcx, '\n' + call serial_write_c cli hlt - ret - int 3 - esr_df ENDP esr_df_text ENDS end diff --git a/loader/windows/src/x64/esr_gpf.asm b/loader/windows/src/x64/esr_gpf.asm index b27b727a..eb1285cd 100644 --- a/loader/windows/src/x64/esr_gpf.asm +++ b/loader/windows/src/x64/esr_gpf.asm @@ -22,43 +22,38 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. + serial_write_c PROTO + esr_gpf_text SEGMENT ALIGN(1000h) 'CODE' esr_gpf PROC - mov rdx, 03F8h - mov rax, 45h - out dx, al + mov rcx, 'e' + call serial_write_c - mov rdx, 03F8h - mov rax, 53h - out dx, al + mov rcx, 's' + call serial_write_c - mov rdx, 03F8h - mov rax, 52h - out dx, al + mov rcx, 'r' + call serial_write_c - mov rdx, 03F8h - mov rax, 20h - out dx, al + mov rcx, '_' + call serial_write_c - mov rdx, 03F8h - mov rax, 47h - out dx, al + mov rcx, 'g' + call serial_write_c - mov rdx, 03F8h - mov rax, 50h - out dx, al + mov rcx, 'p' + call serial_write_c - mov rdx, 03F8h - mov rax, 46h - out dx, al + mov rcx, 'f' + call serial_write_c + + mov rcx, '\n' + call serial_write_c cli hlt - ret - int 3 - esr_gpf ENDP esr_gpf_text ENDS end diff --git a/loader/windows/src/x64/esr_nmi.asm b/loader/windows/src/x64/esr_nmi.asm index f22b82f5..922e8864 100644 --- a/loader/windows/src/x64/esr_nmi.asm +++ b/loader/windows/src/x64/esr_nmi.asm @@ -22,6 +22,9 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. + ; @brief defines the offset of state_save_t.ia32_debugctl + SS_OFFSET_NMI EQU 318h + esr_nmi_text SEGMENT ALIGN(1000h) 'CODE' esr_nmi PROC @@ -34,7 +37,7 @@ push rdx mov rax, 1h - mov [r15 + 318h], rax + mov [r15 + SS_OFFSET_NMI], rax pop rdx pop rax diff --git a/loader/windows/src/x64/esr_pf.asm b/loader/windows/src/x64/esr_pf.asm index 4a9fabc5..ed4c1507 100644 --- a/loader/windows/src/x64/esr_pf.asm +++ b/loader/windows/src/x64/esr_pf.asm @@ -22,32 +22,31 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. + serial_write_c PROTO + esr_pf_text SEGMENT ALIGN(1000h) 'CODE' esr_pf PROC - mov rdx, 03F8h - mov rax, 45h - out dx, al + mov rcx, 'e' + call serial_write_c - mov rdx, 03F8h - mov rax, 53h - out dx, al + mov rcx, 's' + call serial_write_c - mov rdx, 03F8h - mov rax, 52h - out dx, al + mov rcx, 'r' + call serial_write_c - mov rdx, 03F8h - mov rax, 20h - out dx, al + mov rcx, '_' + call serial_write_c - mov rdx, 03F8h - mov rax, 50h - out dx, al + mov rcx, 'p' + call serial_write_c - mov rdx, 03F8h - mov rax, 46h - out dx, al + mov rcx, 'f' + call serial_write_c + + mov rcx, '\n' + call serial_write_c cli hlt diff --git a/loader/windows/src/x64/flush_cache.asm b/loader/windows/src/x64/flush_cache.asm new file mode 100644 index 00000000..e6bdf380 --- /dev/null +++ b/loader/windows/src/x64/flush_cache.asm @@ -0,0 +1,34 @@ +; @copyright +; Copyright (C) 2020 Assured Information Security, Inc. +; +; @copyright +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; @copyright +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; @copyright +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + + .code + + flush_cache PROC + + clflush [rcx] + ret + int 3 + + flush_cache ENDP + end diff --git a/loader/windows/src/x64/intrinsic_sgdt.asm b/loader/windows/src/x64/intrinsic_sgdt.asm index e506b828..38007d9e 100644 --- a/loader/windows/src/x64/intrinsic_sgdt.asm +++ b/loader/windows/src/x64/intrinsic_sgdt.asm @@ -26,7 +26,7 @@ intrinsic_sgdt PROC - sgdt [rcx] + sgdt fword ptr[rcx] ret int 3 diff --git a/loader/windows/src/x64/intrinsic_sidt.asm b/loader/windows/src/x64/intrinsic_sidt.asm index 738d1999..061a88f8 100644 --- a/loader/windows/src/x64/intrinsic_sidt.asm +++ b/loader/windows/src/x64/intrinsic_sidt.asm @@ -26,7 +26,7 @@ intrinsic_sidt PROC - sidt [rcx] + sidt fword ptr[rcx] ret int 3 diff --git a/loader/windows/src/x64/promote.asm b/loader/windows/src/x64/promote.asm index ad6c7476..f35f25d3 100644 --- a/loader/windows/src/x64/promote.asm +++ b/loader/windows/src/x64/promote.asm @@ -22,6 +22,130 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. + ; @brief defines the offset of state_save_t.rax + SS_OFFSET_RAX EQU 000h + ; @brief defines the offset of state_save_t.rbx + SS_OFFSET_RBX EQU 008h + ; @brief defines the offset of state_save_t.rcx + SS_OFFSET_RCX EQU 010h + ; @brief defines the offset of state_save_t.rdx + SS_OFFSET_RDX EQU 018h + ; @brief defines the offset of state_save_t.rbp + SS_OFFSET_RBP EQU 020h + ; @brief defines the offset of state_save_t.rsi + SS_OFFSET_RSI EQU 028h + ; @brief defines the offset of state_save_t.rdi + SS_OFFSET_RDI EQU 030h + ; @brief defines the offset of state_save_t.r8 + SS_OFFSET_R8 EQU 038h + ; @brief defines the offset of state_save_t.r9 + SS_OFFSET_R9 EQU 040h + ; @brief defines the offset of state_save_t.r10 + SS_OFFSET_R10 EQU 048h + ; @brief defines the offset of state_save_t.r11 + SS_OFFSET_R11 EQU 050h + ; @brief defines the offset of state_save_t.r12 + SS_OFFSET_R12 EQU 058h + ; @brief defines the offset of state_save_t.r13 + SS_OFFSET_R13 EQU 060h + ; @brief defines the offset of state_save_t.r14 + SS_OFFSET_R14 EQU 068h + ; @brief defines the offset of state_save_t.r15 + SS_OFFSET_R15 EQU 070h + ; @brief defines the offset of state_save_t.rip + SS_OFFSET_RIP EQU 078h + ; @brief defines the offset of state_save_t.rsp + SS_OFFSET_RSP EQU 080h + ; @brief defines the offset of state_save_t.rflags + SS_OFFSET_RFLAGS EQU 088h + ; @brief defines the offset of state_save_t.gdtr + SS_OFFSET_GDTR EQU 0A0h + ; @brief defines the offset of state_save_t.idtr + SS_OFFSET_IDTR EQU 0B0h + ; @brief defines the offset of state_save_t.es_selector + SS_OFFSET_ES_SELECTOR EQU 0C0h + ; @brief defines the offset of state_save_t.cs_selector + SS_OFFSET_CS_SELECTOR EQU 0D0h + ; @brief defines the offset of state_save_t.ss_selector + SS_OFFSET_SS_SELECTOR EQU 0E0h + ; @brief defines the offset of state_save_t.ds_selector + SS_OFFSET_DS_SELECTOR EQU 0F0h + ; @brief defines the offset of state_save_t.fs_selector + SS_OFFSET_FS_SELECTOR EQU 100h + ; @brief defines the offset of state_save_t.gs_selector + SS_OFFSET_GS_SELECTOR EQU 110h + ; @brief defines the offset of state_save_t.ldtr_selector + SS_OFFSET_LDTR_SELECTOR EQU 120h + ; @brief defines the offset of state_save_t.tr_selector + SS_OFFSET_TR_SELECTOR EQU 130h + ; @brief defines the offset of state_save_t.cr0 + SS_OFFSET_CR0 EQU 140h + ; @brief defines the offset of state_save_t.cr2 + SS_OFFSET_CR2 EQU 150h + ; @brief defines the offset of state_save_t.cr3 + SS_OFFSET_CR3 EQU 158h + ; @brief defines the offset of state_save_t.cr4 + SS_OFFSET_CR4 EQU 160h + ; @brief defines the offset of state_save_t.dr6 + SS_OFFSET_DR6 EQU 1F0h + ; @brief defines the offset of state_save_t.dr7 + SS_OFFSET_DR7 EQU 1F8h + ; @brief defines the offset of state_save_t.ia32_efer + SS_OFFSET_IA32_EFER EQU 240h + ; @brief defines the offset of state_save_t.ia32_star + SS_OFFSET_IA32_STAR EQU 248h + ; @brief defines the offset of state_save_t.ia32_lstar + SS_OFFSET_IA32_LSTAR EQU 250h + ; @brief defines the offset of state_save_t.ia32_cstar + SS_OFFSET_IA32_CSTAR EQU 258h + ; @brief defines the offset of state_save_t.ia32_fmask + SS_OFFSET_IA32_FMASK EQU 260h + ; @brief defines the offset of state_save_t.ia32_fs_base + SS_OFFSET_IA32_FS_BASE EQU 268h + ; @brief defines the offset of state_save_t.ia32_gs_base + SS_OFFSET_IA32_GS_BASE EQU 270h + ; @brief defines the offset of state_save_t.ia32_kernel_gs_base + SS_OFFSET_IA32_KERNEL_GS_BASE EQU 278h + ; @brief defines the offset of state_save_t.ia32_sysenter_cs + SS_OFFSET_IA32_SYSENTER_CS EQU 280h + ; @brief defines the offset of state_save_t.ia32_sysenter_esp + SS_OFFSET_IA32_SYSENTER_ESP EQU 288h + ; @brief defines the offset of state_save_t.ia32_sysenter_eip + SS_OFFSET_IA32_SYSENTER_EIP EQU 290h + ; @brief defines the offset of state_save_t.ia32_pat + SS_OFFSET_IA32_PAT EQU 298h + ; @brief defines the offset of state_save_t.ia32_debugctl + SS_OFFSET_IA32_DEBUGCTL EQU 2A0h + ; @brief defines the offset of state_save_t.nmi + SS_OFFSET_NMI EQU 318h + + ; @brief defines MSR_IA32_SYSENTER_CS + MSR_IA32_SYSENTER_CS EQU 00000174h + ; @brief defines MSR_IA32_SYSENTER_ESP + MSR_IA32_SYSENTER_ESP EQU 00000175h + ; @brief defines MSR_IA32_SYSENTER_EIP + MSR_IA32_SYSENTER_EIP EQU 00000176h + ; @brief defines MSR_IA32_DEBUGCTL + MSR_IA32_DEBUGCTL EQU 000001D9h + ; @brief defines MSR_IA32_PAT + MSR_IA32_PAT EQU 00000277h + ; @brief defines MSR_IA32_EFER + MSR_IA32_EFER EQU 0C0000080h + ; @brief defines MSR_IA32_STAR + MSR_IA32_STAR EQU 0C0000081h + ; @brief defines MSR_IA32_LSTAR + MSR_IA32_LSTAR EQU 0C0000082h + ; @brief defines MSR_IA32_CSTAR + MSR_IA32_CSTAR EQU 0C0000083h + ; @brief defines MSR_IA32_FMASK + MSR_IA32_FMASK EQU 0C0000084h + ; @brief defines MSR_IA32_FS_BASE + MSR_IA32_FS_BASE EQU 0C0000100h + ; @brief defines MSR_IA32_GS_BASE + MSR_IA32_GS_BASE EQU 0C0000101h + ; @brief defines MSR_IA32_KERNEL_GS_BASE + MSR_IA32_KERNEL_GS_BASE EQU 0C0000102h + enable_interrupts PROTO disable_interrupts PROTO @@ -32,10 +156,10 @@ ; Debug Registers ; ************************************************************************** - mov rax, [r15 + 1F8h] + mov rax, [r15 + SS_OFFSET_DR7] mov dr7, rax - mov rax, [r15 + 1F0h] + mov rax, [r15 + SS_OFFSET_DR6] mov dr6, rax ; ************************************************************************** @@ -53,27 +177,31 @@ ; - Finally, we need to load a new stack pointer once we load the new ; CR3 so that we can push/pop as needed - mov rax, [r15 + 158h] + mov rax, [r15 + SS_OFFSET_CR3] and rax, 0FFFFFFFFFFFFF000h mov cr3, rax - mov rax, [r15 + 160h] + mov rax, [r15 + SS_OFFSET_CR4] and rax, 0FFFFFFFFFFFFFF7Fh mov cr4, rax - mov rax, [r15 + 158h] + mov rax, [r15 + SS_OFFSET_CR3] mov cr3, rax - mov rax, [r15 + 160h] + mov rax, [r15 + SS_OFFSET_CR4] mov cr4, rax - mov rax, [r15 + 150h] + mov rax, [r15 + SS_OFFSET_CR2] mov cr2, rax - mov rax, [r15 + 140h] + mov rax, [r15 + SS_OFFSET_CR0] mov cr0, rax - mov rsp, [r15 + 080h] + ; ************************************************************************** + ; Stack + ; ************************************************************************** + + mov rsp, [r15 + SS_OFFSET_RSP] ; ************************************************************************** ; Clear TSS Busy @@ -117,30 +245,30 @@ ; in the platform logic to mark the GDT as read/write just in case ; this code needs to execute. - lgdt fword ptr[r15 + 0A0h] + lgdt fword ptr[r15 + SS_OFFSET_GDTR] - mov dx, [r15 + 0C0h] + mov dx, [r15 + SS_OFFSET_ES_SELECTOR] mov es, dx - mov ax, [r15 + 0D0h] + mov ax, [r15 + SS_OFFSET_CS_SELECTOR] push rax - mov dx, [r15 + 0E0h] + mov dx, [r15 + SS_OFFSET_SS_SELECTOR] mov ss, dx - mov dx, [r15 + 0F0h] + mov dx, [r15 + SS_OFFSET_DS_SELECTOR] mov ds, dx - mov dx, [r15 + 100h] + mov dx, [r15 + SS_OFFSET_FS_SELECTOR] mov fs, dx - mov dx, [r15 + 110h] + mov dx, [r15 + SS_OFFSET_GS_SELECTOR] mov gs, dx - mov dx, [r15 + 120h] + mov dx, [r15 + SS_OFFSET_LDTR_SELECTOR] lldt dx - mov dx, [r15 + 130h] + mov dx, [r15 + SS_OFFSET_TR_SELECTOR] ltr dx lea rax, [gdt_and_cs_loaded] @@ -154,82 +282,82 @@ gdt_and_cs_loaded: ; MSRs ; ************************************************************************** - mov ecx, 000001D9h ; DEBUGCTL - mov eax, [r15 + 2A0h] - mov edx, [r15 + 2A4h] + mov ecx, MSR_IA32_DEBUGCTL + mov eax, [r15 + SS_OFFSET_IA32_DEBUGCTL + 0h] + mov edx, [r15 + SS_OFFSET_IA32_DEBUGCTL + 4h] wrmsr - mov ecx, 00000277h ; PAT - mov eax, [r15 + 298h] - mov edx, [r15 + 29Ch] + mov ecx, MSR_IA32_PAT + mov eax, [r15 + SS_OFFSET_IA32_PAT + 0h] + mov edx, [r15 + SS_OFFSET_IA32_PAT + 4h] wrmsr - mov ecx, 00000176h ; SYSENTER_EIP - mov eax, [r15 + 290h] - mov edx, [r15 + 294h] + mov ecx, MSR_IA32_SYSENTER_EIP + mov eax, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0h] + mov edx, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 4h] wrmsr - mov ecx, 00000175h ; SYSENTER_ESP - mov eax, [r15 + 288h] - mov edx, [r15 + 28Ch] + mov ecx, MSR_IA32_SYSENTER_EIP + mov eax, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 0h] + mov edx, [r15 + SS_OFFSET_IA32_SYSENTER_EIP + 4h] wrmsr - mov ecx, 00000174h ; SYSENTER_CS - mov eax, [r15 + 280h] - mov edx, [r15 + 284h] + mov ecx, MSR_IA32_SYSENTER_CS + mov eax, [r15 + SS_OFFSET_IA32_SYSENTER_CS + 0h] + mov edx, [r15 + SS_OFFSET_IA32_SYSENTER_CS + 4h] wrmsr - mov ecx, 0C0000102h ; Kernel GS Base - mov eax, [r15 + 278h] - mov edx, [r15 + 27Ch] + mov ecx, MSR_IA32_KERNEL_GS_BASE + mov eax, [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 0h] + mov edx, [r15 + SS_OFFSET_IA32_KERNEL_GS_BASE + 4h] wrmsr - mov ecx, 0C0000101h ; GS Base - mov eax, [r15 + 270h] - mov edx, [r15 + 274h] + mov ecx, MSR_IA32_GS_BASE + mov eax, [r15 + SS_OFFSET_IA32_GS_BASE + 0h] + mov edx, [r15 + SS_OFFSET_IA32_GS_BASE + 4h] wrmsr - mov ecx, 0C0000100h ; FS Base - mov eax, [r15 + 268h] - mov edx, [r15 + 26Ch] + mov ecx, MSR_IA32_FS_BASE + mov eax, [r15 + SS_OFFSET_IA32_FS_BASE + 0h] + mov edx, [r15 + SS_OFFSET_IA32_FS_BASE + 4h] wrmsr - mov ecx, 0C0000084h ; FMASK - mov eax, [r15 + 260h] - mov edx, [r15 + 264h] + mov ecx, MSR_IA32_FMASK + mov eax, [r15 + SS_OFFSET_IA32_FMASK + 0h] + mov edx, [r15 + SS_OFFSET_IA32_FMASK + 4h] wrmsr - mov ecx, 0C0000083h ; CSTAR - mov eax, [r15 + 258h] - mov edx, [r15 + 25Ch] + mov ecx, MSR_IA32_CSTAR + mov eax, [r15 + SS_OFFSET_IA32_CSTAR + 0h] + mov edx, [r15 + SS_OFFSET_IA32_CSTAR + 4h] wrmsr - mov ecx, 0C0000082h ; LSTAR - mov eax, [r15 + 250h] - mov edx, [r15 + 254h] + mov ecx, MSR_IA32_LSTAR + mov eax, [r15 + SS_OFFSET_IA32_LSTAR + 0h] + mov edx, [r15 + SS_OFFSET_IA32_LSTAR + 4h] wrmsr - mov ecx, 0C0000081h ; STAR - mov eax, [r15 + 248h] - mov edx, [r15 + 24Ch] + mov ecx, MSR_IA32_STAR + mov eax, [r15 + SS_OFFSET_IA32_STAR + 0h] + mov edx, [r15 + SS_OFFSET_IA32_STAR + 4h] wrmsr - mov ecx, 0C0000080h ; EFER - mov eax, [r15 + 240h] - mov edx, [r15 + 244h] + mov ecx, MSR_IA32_EFER + mov eax, [r15 + SS_OFFSET_IA32_EFER + 0h] + mov edx, [r15 + SS_OFFSET_IA32_EFER + 4h] wrmsr ; ************************************************************************** ; IDT ; ************************************************************************** - lidt fword ptr[r15 + 0B0h] + lidt fword ptr[r15 + SS_OFFSET_IDTR] ; ************************************************************************** ; NMIs ; ************************************************************************** - mov rax, [r15 + 318h] + mov rax, [r15 + SS_OFFSET_NMI] cmp rax, 1h jne nmis_complete @@ -241,32 +369,32 @@ nmis_complete: ; Flags ; ************************************************************************** - push [r15 + 088h] + push qword ptr[r15 + SS_OFFSET_RFLAGS] popfq ; ************************************************************************** ; General Purpose Registers ; ************************************************************************** - mov rax, [r15 + 078h] + mov rax, [r15 + SS_OFFSET_RIP] push rax - mov r14, [r15 + 068h] - mov r13, [r15 + 060h] - mov r12, [r15 + 058h] - mov r11, [r15 + 050h] - mov r10, [r15 + 048h] - mov r9, [r15 + 040h] - mov r8, [r15 + 038h] - mov rdi, [r15 + 030h] - mov rsi, [r15 + 028h] - mov rbp, [r15 + 020h] - mov rdx, [r15 + 018h] - mov rcx, [r15 + 010h] - mov rbx, [r15 + 008h] - mov rax, [r15 + 000h] + mov r14, [r15 + SS_OFFSET_R14] + mov r13, [r15 + SS_OFFSET_R13] + mov r12, [r15 + SS_OFFSET_R12] + mov r11, [r15 + SS_OFFSET_R11] + mov r10, [r15 + SS_OFFSET_R10] + mov r9, [r15 + SS_OFFSET_R9] + mov r8, [r15 + SS_OFFSET_R8] + mov rdi, [r15 + SS_OFFSET_RDI] + mov rsi, [r15 + SS_OFFSET_RSI] + mov rbp, [r15 + SS_OFFSET_RBP] + mov rdx, [r15 + SS_OFFSET_RDX] + mov rcx, [r15 + SS_OFFSET_RCX] + mov rbx, [r15 + SS_OFFSET_RBX] + mov rax, [r15 + SS_OFFSET_RAX] - mov r15, [r15 + 070h] + mov r15, [r15 + SS_OFFSET_R15] call enable_interrupts ret diff --git a/loader/windows/src/x64/serial_write_c.asm b/loader/windows/src/x64/serial_write_c.asm new file mode 100644 index 00000000..56e6d4c2 --- /dev/null +++ b/loader/windows/src/x64/serial_write_c.asm @@ -0,0 +1,53 @@ +; @copyright +; Copyright (C) 2020 Assured Information Security, Inc. +; +; @copyright +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; @copyright +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; @copyright +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +include constants_masm.h + + serial_write_c_text SEGMENT ALIGN(1000h) 'CODE' + serial_write_c PROC + + push rax + push rdx + +wait_for_ffio_empty: + mov rdx, HYPERVISOR_SERIAL_PORT + add rdx, 5 + in al, dx + + and al, 20h + cmp al, 0h + jz wait_for_ffio_empty + + mov rdx, HYPERVISOR_SERIAL_PORT + mov rax, rcx + out dx, al + + pop rdx + pop rax + ret + int 3 + + serial_write_c ENDP + serial_write_c_text ENDS + end diff --git a/loader/windows/src/x64/serial_write_hex.asm b/loader/windows/src/x64/serial_write_hex.asm new file mode 100644 index 00000000..efd88fcb --- /dev/null +++ b/loader/windows/src/x64/serial_write_hex.asm @@ -0,0 +1,143 @@ +; @copyright +; Copyright (C) 2020 Assured Information Security, Inc. +; +; @copyright +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; @copyright +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; @copyright +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + + serial_write_c PROTO + + serial_write_hex_text SEGMENT ALIGN(1000h) 'CODE' + serial_write_hex PROC + push rdx + + mov rdx, rcx + + mov rcx, 30h + call serial_write_c + + mov rcx, 78h + call serial_write_c + + mov rcx, rdx + shr rcx, 60 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 56 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 52 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 48 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 44 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 40 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 36 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 32 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 28 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 24 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 20 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 16 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 12 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 8 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + shr rcx, 4 + and rcx, 0FFh + call serial_write_hex_digit + + mov rcx, rdx + and rcx, 0FFh + call serial_write_hex_digit + + pop rdx + ret + int 3 + +serial_write_hex_digit: + + cmp rcx, 9 + jg serial_write_hex_digit_a_to_f + + add rcx, 30h + call serial_write_c + + ret + int 3 + +serial_write_hex_digit_a_to_f: + + add rcx, 37h + call serial_write_c + + ret + int 3 + + serial_write_hex ENDP + serial_write_hex_text ENDS + end diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 8c11d4b3..fecbf129 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -19,37 +19,79 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -include(${CMAKE_CURRENT_LIST_DIR}/../cmake/function/hypervisor_add_header_depends.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/function/hypervisor_target_source.cmake) add_library(runtime) -target_include_directories(runtime PRIVATE - ../syscall/include/cpp/ -) - -target_include_directories(runtime SYSTEM PRIVATE - ${CMAKE_BINARY_DIR}/include -) +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ target_include_directories(runtime PUBLIC - include + src ) +# ------------------------------------------------------------------------------ +# Headers +# ------------------------------------------------------------------------------ + list(APPEND HEADERS - ${CMAKE_CURRENT_LIST_DIR}/include/bsl/cstdio.hpp - ${CMAKE_CURRENT_LIST_DIR}/include/bsl/details/print_thread_id.hpp - ${CMAKE_CURRENT_LIST_DIR}/include/bsl/details/putc_stderr.hpp - ${CMAKE_CURRENT_LIST_DIR}/include/bsl/details/putc_stdout.hpp - ${CMAKE_CURRENT_LIST_DIR}/include/bsl/details/puts_stderr.hpp - ${CMAKE_CURRENT_LIST_DIR}/include/bsl/details/puts_stdout.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/bsl/cstdio.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/bsl/details/print_thread_id.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/bsl/details/putc_stderr.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/bsl/details/putc_stdout.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/bsl/details/puts_stderr.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/bsl/details/puts_stdout.hpp ) -target_sources(runtime PRIVATE - src/_start.cpp +# ------------------------------------------------------------------------------ +# Definitions +# ------------------------------------------------------------------------------ + +target_compile_definitions(runtime PUBLIC + HYPERVISOR_START_NAME=_start + HYPERVISOR_STACK_CHK_FAIL_NAME=__stack_chk_fail + HYPERVISOR_STACK_CHK_GUARD_NAME=__stack_chk_guard + HYPERVISOR_MEMCPY_NAME=memcpy + HYPERVISOR_MEMSET_NAME=memset + HYPERVISOR_PRINT_THREAD_ID_NAME=print_thread_id + HYPERVISOR_PUTC_STDERR_NAME=putc_stderr + HYPERVISOR_PUTC_STDOUT_NAME=putc_stdout + HYPERVISOR_PUTS_STDERR_NAME=puts_stderr + HYPERVISOR_PUTS_STDOUT_NAME=puts_stdout ) -hypervisor_add_header_depends(src/_start.cpp ${HEADERS}) +# ------------------------------------------------------------------------------ +# Sources +# ------------------------------------------------------------------------------ -target_link_libraries(runtime PUBLIC +hypervisor_target_source(runtime src/__stack_chk_fail.cpp ${HEADERS}) + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + hypervisor_target_source(runtime src/x64/_start.S ${HEADERS}) + hypervisor_target_source(runtime src/x64/__stack_chk_guard.S ${HEADERS}) + hypervisor_target_source(runtime src/x64/memcpy.S ${HEADERS}) + hypervisor_target_source(runtime src/x64/memset.S ${HEADERS}) +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + hypervisor_target_source(runtime src/arm/aarch64/_start.S ${HEADERS}) + hypervisor_target_source(runtime src/arm/aarch64/__stack_chk_guard.S ${HEADERS}) + hypervisor_target_source(runtime src/arm/aarch64/memcpy.S ${HEADERS}) + hypervisor_target_source(runtime src/arm/aarch64/memset.S ${HEADERS}) +endif() + +# ------------------------------------------------------------------------------ +# Libraries +# ------------------------------------------------------------------------------ + +target_link_libraries(runtime PRIVATE bsl + syscall ) + +# ------------------------------------------------------------------------------ +# Install +# ------------------------------------------------------------------------------ + +install(TARGETS runtime DESTINATION lib) diff --git a/runtime/src/__stack_chk_fail.cpp b/runtime/src/__stack_chk_fail.cpp new file mode 100644 index 00000000..f1ac7313 --- /dev/null +++ b/runtime/src/__stack_chk_fail.cpp @@ -0,0 +1,43 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +#include + +namespace mk +{ + /// + /// @brief Called when a stack overflow occurs + /// + extern "C" void + // NOLINTNEXTLINE(bsl-documentation) + HYPERVISOR_STACK_CHK_FAIL_NAME() noexcept + { + bsl::print() << bsl::red << "...\n\n" << bsl::rst; + bsl::error() << "Stack Overflow Detected!!!\n"; + + syscall::bf_control_op_exit_impl(); + } +} diff --git a/runtime/src/_start.cpp b/runtime/src/_start.cpp deleted file mode 100644 index 78916387..00000000 --- a/runtime/src/_start.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/// @copyright -/// Copyright (C) 2020 Assured Information Security, Inc. -/// -/// @copyright -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// @copyright -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// @copyright -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -/// SOFTWARE. - -#include - -#include -#include -#include - -extern "C" -{ - /// @brief provides the stack guard - constinit bsl::uintmax __stack_chk_guard{0xDEADBEEFDEADBEEF}; // NOLINT - - /// - /// @brief Used to detect if stack corruption occurs. - /// - void - __stack_chk_fail() noexcept // NOLINT - { - bsl::fputs("stack smashing detected\n"); - syscall::bf_control_op_exit(); - } - - /// TODO: - /// - Find out how the compiler is compiling memset and memcpy and make - /// sure there isn't a faster way to implement these (without SSE). - /// - - /// - /// @brief Same as std::memset. - /// - /// - /// @param dst a pointer to the memory to set - /// @param ch the value to set the memory to - /// @param num the total number of bytes to set - /// @return Returns the same result as std::memset. - /// - [[maybe_unused]] extern "C" auto - memset(void *const dst, bsl::char_type const ch, bsl::uintmax const num) noexcept -> void * - { - return bsl::builtin_memset(dst, ch, num); - } - - /// - /// @brief Same as std::memcpy. - /// - /// - /// @param dst a pointer to the memory to copy to - /// @param src a pointer to the memory to copy from - /// @param count the total number of bytes to copy - /// @return Returns the same result as std::memcpy. - /// - [[maybe_unused]] extern "C" auto - memcpy(void *const dst, void const *const src, bsl::uintmax const count) noexcept -> void * - { - return bsl::builtin_memcpy(dst, src, count); - } -} - -namespace runtime -{ - /// - /// @brief Implements the extension's main entry point - /// - /// - /// @param version the version of the spec implemented by the - /// microkernel. This can be used to ensure the extension and the - /// microkernel speak the same ABI. - /// - extern "C" void ext_main_entry(bsl::safe_uint32 const &version) noexcept; - - /// - /// @brief Provides the _start function - /// - /// - /// @param version the version of the spec implemented by the - /// microkernel. This can be used to ensure the extension and the - /// microkernel speak the same ABI. - /// - extern "C" void - _start(bsl::uint32 const version) noexcept - { - ext_main_entry(version); - } -} diff --git a/runtime/src/arm/aarch64/__stack_chk_fail.S b/runtime/src/arm/aarch64/__stack_chk_fail.S new file mode 100644 index 00000000..e1494123 --- /dev/null +++ b/runtime/src/arm/aarch64/__stack_chk_fail.S @@ -0,0 +1,37 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl HYPERVISOR_STACK_CHK_FAIL_NAME + .type HYPERVISOR_STACK_CHK_FAIL_NAME, @function +HYPERVISOR_STACK_CHK_FAIL_NAME: + + bl msg_stack_chk_fail + bl bf_control_op_exit_impl + ret + + .size HYPERVISOR_STACK_CHK_FAIL_NAME, .-HYPERVISOR_STACK_CHK_FAIL_NAME diff --git a/runtime/src/arm/aarch64/__stack_chk_guard.S b/runtime/src/arm/aarch64/__stack_chk_guard.S new file mode 100644 index 00000000..0866de09 --- /dev/null +++ b/runtime/src/arm/aarch64/__stack_chk_guard.S @@ -0,0 +1,31 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .rodata + + .globl HYPERVISOR_STACK_CHK_GUARD_NAME +HYPERVISOR_STACK_CHK_GUARD_NAME: + .quad 0xDEADBEEFDEADBEEF diff --git a/runtime/src/arm/aarch64/_start.S b/runtime/src/arm/aarch64/_start.S new file mode 100644 index 00000000..ee0b4b7e --- /dev/null +++ b/runtime/src/arm/aarch64/_start.S @@ -0,0 +1,37 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl HYPERVISOR_START_NAME + .type HYPERVISOR_START_NAME, @function +HYPERVISOR_START_NAME: + + bl ext_main_entry + bl bf_control_op_exit_impl + ret + + .size HYPERVISOR_START_NAME, .-HYPERVISOR_START_NAME diff --git a/runtime/src/arm/aarch64/memcpy.S b/runtime/src/arm/aarch64/memcpy.S new file mode 100644 index 00000000..f4f47e77 --- /dev/null +++ b/runtime/src/arm/aarch64/memcpy.S @@ -0,0 +1,243 @@ +/* + * memcpy - copy memory area + * + * Copyright (c) 2012-2020, Arm Limited. + * SPDX-License-Identifier: MIT + */ + +/* Assumptions: + * + * ARMv8-a, AArch64, unaligned accesses. + * + */ + +#define L(l) .L ## l + +#define dstin x0 +#define src x1 +#define count x2 +#define dst x3 +#define srcend x4 +#define dstend x5 +#define A_l x6 +#define A_lw w6 +#define A_h x7 +#define B_l x8 +#define B_lw w8 +#define B_h x9 +#define C_l x10 +#define C_lw w10 +#define C_h x11 +#define D_l x12 +#define D_h x13 +#define E_l x14 +#define E_h x15 +#define F_l x16 +#define F_h x17 +#define G_l count +#define G_h dst +#define H_l src +#define H_h srcend +#define tmp1 x14 + +/* This implementation handles overlaps and supports both memcpy and memmove + from a single entry point. It uses unaligned accesses and branchless + sequences to keep the code small, simple and improve performance. + + Copies are split into 3 main cases: small copies of up to 32 bytes, medium + copies of up to 128 bytes, and large copies. The overhead of the overlap + check is negligible since it is only required for large copies. + + Large copies use a software pipelined loop processing 64 bytes per iteration. + The destination pointer is 16-byte aligned to minimize unaligned accesses. + The loop tail is handled by always copying 64 bytes from the end. +*/ + + .text + + .global memcpy + .type memcpy, @function +memcpy: + + add srcend, src, count + add dstend, dstin, count + cmp count, 128 + b.hi L(copy_long) + cmp count, 32 + b.hi L(copy32_128) + + /* Small copies: 0..32 bytes. */ + cmp count, 16 + b.lo L(copy16) + ldp A_l, A_h, [src] + ldp D_l, D_h, [srcend, -16] + stp A_l, A_h, [dstin] + stp D_l, D_h, [dstend, -16] + ret + + /* Copy 8-15 bytes. */ +L(copy16): + tbz count, 3, L(copy8) + ldr A_l, [src] + ldr A_h, [srcend, -8] + str A_l, [dstin] + str A_h, [dstend, -8] + ret + + .p2align 3 + /* Copy 4-7 bytes. */ +L(copy8): + tbz count, 2, L(copy4) + ldr A_lw, [src] + ldr B_lw, [srcend, -4] + str A_lw, [dstin] + str B_lw, [dstend, -4] + ret + + /* Copy 0..3 bytes using a branchless sequence. */ +L(copy4): + cbz count, L(copy0) + lsr tmp1, count, 1 + ldrb A_lw, [src] + ldrb C_lw, [srcend, -1] + ldrb B_lw, [src, tmp1] + strb A_lw, [dstin] + strb B_lw, [dstin, tmp1] + strb C_lw, [dstend, -1] +L(copy0): + ret + + .p2align 4 + /* Medium copies: 33..128 bytes. */ +L(copy32_128): + ldp A_l, A_h, [src] + ldp B_l, B_h, [src, 16] + ldp C_l, C_h, [srcend, -32] + ldp D_l, D_h, [srcend, -16] + cmp count, 64 + b.hi L(copy128) + stp A_l, A_h, [dstin] + stp B_l, B_h, [dstin, 16] + stp C_l, C_h, [dstend, -32] + stp D_l, D_h, [dstend, -16] + ret + + .p2align 4 + /* Copy 65..128 bytes. */ +L(copy128): + ldp E_l, E_h, [src, 32] + ldp F_l, F_h, [src, 48] + cmp count, 96 + b.ls L(copy96) + ldp G_l, G_h, [srcend, -64] + ldp H_l, H_h, [srcend, -48] + stp G_l, G_h, [dstend, -64] + stp H_l, H_h, [dstend, -48] +L(copy96): + stp A_l, A_h, [dstin] + stp B_l, B_h, [dstin, 16] + stp E_l, E_h, [dstin, 32] + stp F_l, F_h, [dstin, 48] + stp C_l, C_h, [dstend, -32] + stp D_l, D_h, [dstend, -16] + ret + + .p2align 4 + /* Copy more than 128 bytes. */ +L(copy_long): + /* Use backwards copy if there is an overlap. */ + sub tmp1, dstin, src + cbz tmp1, L(copy0) + cmp tmp1, count + b.lo L(copy_long_backwards) + + /* Copy 16 bytes and then align dst to 16-byte alignment. */ + + ldp D_l, D_h, [src] + and tmp1, dstin, 15 + bic dst, dstin, 15 + sub src, src, tmp1 + add count, count, tmp1 /* Count is now 16 too large. */ + ldp A_l, A_h, [src, 16] + stp D_l, D_h, [dstin] + ldp B_l, B_h, [src, 32] + ldp C_l, C_h, [src, 48] + ldp D_l, D_h, [src, 64]! + subs count, count, 128 + 16 /* Test and readjust count. */ + b.ls L(copy64_from_end) + +L(loop64): + stp A_l, A_h, [dst, 16] + ldp A_l, A_h, [src, 16] + stp B_l, B_h, [dst, 32] + ldp B_l, B_h, [src, 32] + stp C_l, C_h, [dst, 48] + ldp C_l, C_h, [src, 48] + stp D_l, D_h, [dst, 64]! + ldp D_l, D_h, [src, 64]! + subs count, count, 64 + b.hi L(loop64) + + /* Write the last iteration and copy 64 bytes from the end. */ +L(copy64_from_end): + ldp E_l, E_h, [srcend, -64] + stp A_l, A_h, [dst, 16] + ldp A_l, A_h, [srcend, -48] + stp B_l, B_h, [dst, 32] + ldp B_l, B_h, [srcend, -32] + stp C_l, C_h, [dst, 48] + ldp C_l, C_h, [srcend, -16] + stp D_l, D_h, [dst, 64] + stp E_l, E_h, [dstend, -64] + stp A_l, A_h, [dstend, -48] + stp B_l, B_h, [dstend, -32] + stp C_l, C_h, [dstend, -16] + ret + + .p2align 4 + + /* Large backwards copy for overlapping copies. + Copy 16 bytes and then align dst to 16-byte alignment. */ +L(copy_long_backwards): + ldp D_l, D_h, [srcend, -16] + and tmp1, dstend, 15 + sub srcend, srcend, tmp1 + sub count, count, tmp1 + ldp A_l, A_h, [srcend, -16] + stp D_l, D_h, [dstend, -16] + ldp B_l, B_h, [srcend, -32] + ldp C_l, C_h, [srcend, -48] + ldp D_l, D_h, [srcend, -64]! + sub dstend, dstend, tmp1 + subs count, count, 128 + b.ls L(copy64_from_start) + +L(loop64_backwards): + stp A_l, A_h, [dstend, -16] + ldp A_l, A_h, [srcend, -16] + stp B_l, B_h, [dstend, -32] + ldp B_l, B_h, [srcend, -32] + stp C_l, C_h, [dstend, -48] + ldp C_l, C_h, [srcend, -48] + stp D_l, D_h, [dstend, -64]! + ldp D_l, D_h, [srcend, -64]! + subs count, count, 64 + b.hi L(loop64_backwards) + + /* Write the last iteration and copy 64 bytes from the start. */ +L(copy64_from_start): + ldp G_l, G_h, [src, 48] + stp A_l, A_h, [dstend, -16] + ldp A_l, A_h, [src, 32] + stp B_l, B_h, [dstend, -32] + ldp B_l, B_h, [src, 16] + stp C_l, C_h, [dstend, -48] + ldp C_l, C_h, [src] + stp D_l, D_h, [dstend, -64] + stp G_l, G_h, [dstin, 48] + stp A_l, A_h, [dstin, 32] + stp B_l, B_h, [dstin, 16] + stp C_l, C_h, [dstin] + ret + +.size memcpy, .-memcpy diff --git a/runtime/src/arm/aarch64/memset.S b/runtime/src/arm/aarch64/memset.S new file mode 100644 index 00000000..533145c4 --- /dev/null +++ b/runtime/src/arm/aarch64/memset.S @@ -0,0 +1,183 @@ +/* + * memset - fill memory with a constant byte + * + * Copyright (c) 2012, Arm Limited. + * SPDX-License-Identifier: MIT + */ + +/* Assumptions: + * + * ARMv8-a, AArch64, unaligned accesses + * + */ + +#define L(l) .L ## l + +#define dstin x0 +#define val x1 +#define valw w1 +#define count x2 +#define dst x3 +#define dstend x4 +#define tmp1 x5 +#define tmp1w w5 +#define tmp2 x6 +#define tmp2w w6 +#define zva_len x7 +#define zva_lenw w7 + + .text + + .global memset + .type memset, @function +memset: + + dup v0.16B, valw + add dstend, dstin, count + + cmp count, 96 + b.hi L(set_long) + cmp count, 16 + b.hs L(set_medium) + mov val, v0.D[0] + + /* Set 0..15 bytes. */ + tbz count, 3, 1f + str val, [dstin] + str val, [dstend, -8] + ret + nop +1: tbz count, 2, 2f + str valw, [dstin] + str valw, [dstend, -4] + ret +2: cbz count, 3f + strb valw, [dstin] + tbz count, 1, 3f + strh valw, [dstend, -2] +3: ret + + /* Set 17..96 bytes. */ +L(set_medium): + str q0, [dstin] + tbnz count, 6, L(set96) + str q0, [dstend, -16] + tbz count, 5, 1f + str q0, [dstin, 16] + str q0, [dstend, -32] +1: ret + + .p2align 4 + /* Set 64..96 bytes. Write 64 bytes from the start and + 32 bytes from the end. */ +L(set96): + str q0, [dstin, 16] + stp q0, q0, [dstin, 32] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 + nop +L(set_long): + and valw, valw, 255 + bic dst, dstin, 15 + str q0, [dstin] + cmp count, 256 + ccmp valw, 0, 0, cs + b.eq L(try_zva) +L(no_zva): + sub count, dstend, dst /* Count is 16 too large. */ + add dst, dst, 16 + sub count, count, 64 + 16 /* Adjust count and bias for loop. */ +1: stp q0, q0, [dst], 64 + stp q0, q0, [dst, -32] +L(tail64): + subs count, count, 64 + b.hi 1b +2: stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 +L(try_zva): + mrs tmp1, dczid_el0 + tbnz tmp1w, 4, L(no_zva) + and tmp1w, tmp1w, 15 + cmp tmp1w, 4 /* ZVA size is 64 bytes. */ + b.ne L(zva_128) + + /* Write the first and last 64 byte aligned block using stp rather + than using DC ZVA. This is faster on some cores. + */ +L(zva_64): + str q0, [dst, 16] + stp q0, q0, [dst, 32] + bic dst, dst, 63 + stp q0, q0, [dst, 64] + stp q0, q0, [dst, 96] + sub count, dstend, dst /* Count is now 128 too large. */ + sub count, count, 128+64+64 /* Adjust count and bias for loop. */ + add dst, dst, 128 + nop +1: dc zva, dst + add dst, dst, 64 + subs count, count, 64 + b.hi 1b + stp q0, q0, [dst, 0] + stp q0, q0, [dst, 32] + stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + + .p2align 3 +L(zva_128): + cmp tmp1w, 5 /* ZVA size is 128 bytes. */ + b.ne L(zva_other) + + str q0, [dst, 16] + stp q0, q0, [dst, 32] + stp q0, q0, [dst, 64] + stp q0, q0, [dst, 96] + bic dst, dst, 127 + sub count, dstend, dst /* Count is now 128 too large. */ + sub count, count, 128+128 /* Adjust count and bias for loop. */ + add dst, dst, 128 +1: dc zva, dst + add dst, dst, 128 + subs count, count, 128 + b.hi 1b + stp q0, q0, [dstend, -128] + stp q0, q0, [dstend, -96] + stp q0, q0, [dstend, -64] + stp q0, q0, [dstend, -32] + ret + +L(zva_other): + mov tmp2w, 4 + lsl zva_lenw, tmp2w, tmp1w + add tmp1, zva_len, 64 /* Max alignment bytes written. */ + cmp count, tmp1 + blo L(no_zva) + + sub tmp2, zva_len, 1 + add tmp1, dst, zva_len + add dst, dst, 16 + subs count, tmp1, dst /* Actual alignment bytes to write. */ + bic tmp1, tmp1, tmp2 /* Aligned dc zva start address. */ + beq 2f +1: stp q0, q0, [dst], 64 + stp q0, q0, [dst, -32] + subs count, count, 64 + b.hi 1b +2: mov dst, tmp1 + sub count, dstend, tmp1 /* Remaining bytes to write. */ + subs count, count, zva_len + b.lo 4f +3: dc zva, dst + add dst, dst, zva_len + subs count, count, zva_len + b.hs 3b +4: add count, count, zva_len + b L(tail64) + +.size memset, .-memset diff --git a/runtime/include/bsl/cstdio.hpp b/runtime/src/bsl/cstdio.hpp similarity index 96% rename from runtime/include/bsl/cstdio.hpp rename to runtime/src/bsl/cstdio.hpp index 7edcc9ae..2c2463ee 100644 --- a/runtime/include/bsl/cstdio.hpp +++ b/runtime/src/bsl/cstdio.hpp @@ -25,7 +25,7 @@ #ifndef BSL_CSTDIO_HPP #define BSL_CSTDIO_HPP -#include +#include #include #include @@ -38,7 +38,7 @@ namespace bsl /// /// @param c the character to output /// - inline void + constexpr void fputc(bsl::char_type const c) noexcept { syscall::bf_debug_op_write_c(c); @@ -50,7 +50,7 @@ namespace bsl /// /// @param str the string to output /// - inline void + constexpr void fputs(bsl::cstr_type const str) noexcept { syscall::bf_debug_op_write_str(str); diff --git a/runtime/src/bsl/details/print_thread_id.hpp b/runtime/src/bsl/details/print_thread_id.hpp new file mode 100644 index 00000000..bef58645 --- /dev/null +++ b/runtime/src/bsl/details/print_thread_id.hpp @@ -0,0 +1,67 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef RUNTIME_BSL_DETAILS_PRINT_THREAD_ID_HPP +#define RUNTIME_BSL_DETAILS_PRINT_THREAD_ID_HPP + +#include + +#include +#include +#include + +namespace bsl::details +{ + /// + /// @brief Outputs the current thread ID info + /// + /// + /// @tparam T the type of outputter provided + /// @param o the outputter + /// + template + constexpr void + HYPERVISOR_PRINT_THREAD_ID_NAME(out const o) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + o << bsl::rst << " [" // -- + << bsl::cyn << bsl::fmt{"04x", syscall::bf_tls_extid_impl()} // -- + << bsl::rst << ":" // -- + << bsl::cyn << bsl::fmt{"04x", syscall::bf_tls_vmid_impl()} // -- + << bsl::rst << ":" // -- + << bsl::cyn << bsl::fmt{"04x", syscall::bf_tls_vpid_impl()} // -- + << bsl::rst << ":" // -- + << bsl::cyn << bsl::fmt{"04x", syscall::bf_tls_vpsid_impl()} // -- + << bsl::rst << ":" // -- + << bsl::cyn << bsl::fmt{"04x", syscall::bf_tls_ppid_impl()} // -- + << bsl::rst << ":" // -- + << bsl::blu << "US" // -- + << bsl::rst << ']'; // -- + } +} + +#endif diff --git a/runtime/include/bsl/details/putc_stderr.hpp b/runtime/src/bsl/details/putc_stderr.hpp similarity index 91% rename from runtime/include/bsl/details/putc_stderr.hpp rename to runtime/src/bsl/details/putc_stderr.hpp index 092611db..05a65ea6 100644 --- a/runtime/include/bsl/details/putc_stderr.hpp +++ b/runtime/src/bsl/details/putc_stderr.hpp @@ -25,8 +25,9 @@ #ifndef RUNTIME_BSL_DETAILS_PUTC_STDERR_HPP #define RUNTIME_BSL_DETAILS_PUTC_STDERR_HPP +#include "../cstdio.hpp" + #include -#include namespace bsl::details { @@ -36,8 +37,9 @@ namespace bsl::details /// /// @param c the character to output to stderr /// - inline void - putc_stderr(char_type const c) noexcept + constexpr void + /// NOLINTNEXTLINE(bsl-documentation) + HYPERVISOR_PUTC_STDERR_NAME(char_type const c) noexcept { bsl::fputc(c); } diff --git a/runtime/include/bsl/details/putc_stdout.hpp b/runtime/src/bsl/details/putc_stdout.hpp similarity index 91% rename from runtime/include/bsl/details/putc_stdout.hpp rename to runtime/src/bsl/details/putc_stdout.hpp index 9a7d174d..5557e8e3 100644 --- a/runtime/include/bsl/details/putc_stdout.hpp +++ b/runtime/src/bsl/details/putc_stdout.hpp @@ -25,8 +25,9 @@ #ifndef RUNTIME_BSL_DETAILS_PUTC_STDOUT_HPP #define RUNTIME_BSL_DETAILS_PUTC_STDOUT_HPP +#include "../cstdio.hpp" + #include -#include namespace bsl::details { @@ -36,8 +37,9 @@ namespace bsl::details /// /// @param c the character to output to stdout /// - inline void - putc_stdout(char_type const c) noexcept + constexpr void + /// NOLINTNEXTLINE(bsl-documentation) + HYPERVISOR_PUTC_STDOUT_NAME(char_type const c) noexcept { bsl::fputc(c); } diff --git a/runtime/include/bsl/details/puts_stderr.hpp b/runtime/src/bsl/details/puts_stderr.hpp similarity index 91% rename from runtime/include/bsl/details/puts_stderr.hpp rename to runtime/src/bsl/details/puts_stderr.hpp index 1c015827..32bbe13c 100644 --- a/runtime/include/bsl/details/puts_stderr.hpp +++ b/runtime/src/bsl/details/puts_stderr.hpp @@ -25,7 +25,8 @@ #ifndef RUNTIME_BSL_DETAILS_PUTS_STDERR_HPP #define RUNTIME_BSL_DETAILS_PUTS_STDERR_HPP -#include +#include "../cstdio.hpp" + #include namespace bsl::details @@ -36,8 +37,9 @@ namespace bsl::details /// /// @param str the string to output to stderr /// - inline void - puts_stderr(cstr_type const str) noexcept + constexpr void + /// NOLINTNEXTLINE(bsl-documentation) + HYPERVISOR_PUTS_STDERR_NAME(cstr_type const str) noexcept { bsl::fputs(str); } diff --git a/runtime/include/bsl/details/puts_stdout.hpp b/runtime/src/bsl/details/puts_stdout.hpp similarity index 91% rename from runtime/include/bsl/details/puts_stdout.hpp rename to runtime/src/bsl/details/puts_stdout.hpp index 5bb98392..ff7a24a8 100644 --- a/runtime/include/bsl/details/puts_stdout.hpp +++ b/runtime/src/bsl/details/puts_stdout.hpp @@ -25,7 +25,8 @@ #ifndef RUNTIME_BSL_DETAILS_PUTS_STDOUT_HPP #define RUNTIME_BSL_DETAILS_PUTS_STDOUT_HPP -#include +#include "../cstdio.hpp" + #include namespace bsl::details @@ -36,8 +37,9 @@ namespace bsl::details /// /// @param str the string to output to stdout /// - inline void - puts_stdout(cstr_type const str) noexcept + constexpr void + /// NOLINTNEXTLINE(bsl-documentation) + HYPERVISOR_PUTS_STDOUT_NAME(cstr_type const str) noexcept { bsl::fputs(str); } diff --git a/runtime/src/x64/__stack_chk_guard.S b/runtime/src/x64/__stack_chk_guard.S new file mode 100644 index 00000000..e31484b3 --- /dev/null +++ b/runtime/src/x64/__stack_chk_guard.S @@ -0,0 +1,32 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .rodata + .intel_syntax noprefix + + .globl HYPERVISOR_STACK_CHK_GUARD_NAME +HYPERVISOR_STACK_CHK_GUARD_NAME: + .quad 0xDEADBEEFDEADBEEF diff --git a/runtime/src/x64/_start.S b/runtime/src/x64/_start.S new file mode 100644 index 00000000..06effa29 --- /dev/null +++ b/runtime/src/x64/_start.S @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl HYPERVISOR_START_NAME + .type HYPERVISOR_START_NAME, @function +HYPERVISOR_START_NAME: + + call ext_main_entry + call bf_control_op_exit_impl + + xor rax, rax + ret + int 3 + + .size HYPERVISOR_START_NAME, .-HYPERVISOR_START_NAME diff --git a/runtime/src/x64/memcpy.S b/runtime/src/x64/memcpy.S new file mode 100644 index 00000000..4c80c15c --- /dev/null +++ b/runtime/src/x64/memcpy.S @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl HYPERVISOR_MEMCPY_NAME + .type HYPERVISOR_MEMCPY_NAME, @function +HYPERVISOR_MEMCPY_NAME: + + mov rax, rdi + mov rcx, rdx + rep movsb + + ret + int 3 + + .size HYPERVISOR_MEMCPY_NAME, .-HYPERVISOR_MEMCPY_NAME diff --git a/runtime/src/x64/memset.S b/runtime/src/x64/memset.S new file mode 100644 index 00000000..ad098a17 --- /dev/null +++ b/runtime/src/x64/memset.S @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl HYPERVISOR_MEMSET_NAME + .type HYPERVISOR_MEMSET_NAME, @function +HYPERVISOR_MEMSET_NAME: + + mov r10, rdi + mov rax, rsi + mov rcx, rdx + rep stosb + mov rax, r10 + + ret + int 3 + + .size HYPERVISOR_MEMSET_NAME, .-HYPERVISOR_MEMSET_NAME diff --git a/runtime/test/.clang-tidy b/runtime/test/.clang-tidy new file mode 100644 index 00000000..b51628e8 --- /dev/null +++ b/runtime/test/.clang-tidy @@ -0,0 +1,56 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +Checks: + ' + -*, + bsl-*, + -bsl-template-generic-param, + -bsl-literals-user-defined, + -bsl-lambda-implicit-capture, + -bsl-using-ident-unique-namespace, + -bsl-name-prefixes, + bugprone-*, + -bugprone-branch-clone, + cert-*, + -cert-dcl21-cpp, + -cert-oop54-cpp, + clang-analyzer-*, + -clang-analyzer-core.CallAndMessage, + cppcoreguidelines-*, + -cppcoreguidelines-avoid-non-const-global-variables, + hicpp-*, + misc-*, + -misc-misplaced-const, + -misc-non-private-member-variables-in-classes, + modernize-*, + -modernize-use-default-member-init, + performance-*, + readability-*, + -readability-redundant-member-init, + -readability-avoid-const-params-in-decls, + -readability-static-accessed-through-instance + ' +WarningsAsErrors: '*' +HeaderFilterRegex: '.*' +AnalyzeTemporaryDtors: false +FormatStyle: none +UseColor: true diff --git a/runtime/test/CMakeLists.txt b/runtime/test/CMakeLists.txt new file mode 100644 index 00000000..942e21c0 --- /dev/null +++ b/runtime/test/CMakeLists.txt @@ -0,0 +1,83 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +include(${bsl_SOURCE_DIR}/cmake/function/bf_add_test.cmake) + +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + +list(APPEND INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../mocks +) + +list(APPEND SYSTEM_INCLUDES + ${CMAKE_SOURCE_DIR}/syscall/include/cpp + ${CMAKE_SOURCE_DIR}/syscall/mocks/cpp +) + +# ------------------------------------------------------------------------------ +# Definitions +# ------------------------------------------------------------------------------ + +list(APPEND DEFINES + HYPERVISOR_START_NAME=ut_start + HYPERVISOR_STACK_CHK_FAIL_NAME=ut_stack_chk_fail + HYPERVISOR_STACK_CHK_GUARD_NAME=ut_stack_chk_guard + HYPERVISOR_MEMCPY_NAME=ut_memcpy + HYPERVISOR_MEMSET_NAME=ut_memset + HYPERVISOR_PRINT_THREAD_ID_NAME=ut_print_thread_id + HYPERVISOR_PUTC_STDERR_NAME=ut_putc_stderr + HYPERVISOR_PUTC_STDOUT_NAME=ut_putc_stdout + HYPERVISOR_PUTS_STDERR_NAME=ut_puts_stderr + HYPERVISOR_PUTS_STDOUT_NAME=ut_puts_stdout +) + +# ------------------------------------------------------------------------------ +# Tests +# ------------------------------------------------------------------------------ + +add_subdirectory(src/bsl/cstdio) +add_subdirectory(src/bsl/details/print_thread_id) +add_subdirectory(src/bsl/details/putc_stderr) +add_subdirectory(src/bsl/details/putc_stdout) +add_subdirectory(src/bsl/details/puts_stderr) +add_subdirectory(src/bsl/details/puts_stdout) +add_subdirectory(src/__stack_chk_fail) + +# NOTE: +# - We want to make sure that memcpy and memset are working properly as these +# are hand written in assembly. We only need these to support SYSV, so for +# now they are only tests under Linux, which is fine because CI will always +# have a Linux component. +# - The bigger issue is that we have to test this code on each arch which is +# something that we try to avoid under unit tests. Since we currently do not +# have an ARM based CI environment, this code must be manually tested on ARM +# for now. For now this is not much of an issue as the code that we are using +# for ARM was actually written by ARM, not us. +# + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + add_subdirectory(src/_start) + add_subdirectory(src/__stack_chk_guard) + add_subdirectory(src/memcpy) + add_subdirectory(src/memset) +endif() diff --git a/runtime/test/src/__stack_chk_fail/CMakeLists.txt b/runtime/test/src/__stack_chk_fail/CMakeLists.txt new file mode 100644 index 00000000..1f979d82 --- /dev/null +++ b/runtime/test/src/__stack_chk_fail/CMakeLists.txt @@ -0,0 +1,26 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +list(APPEND SOURCES + ../../../src/__stack_chk_fail.cpp +) + +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES} SOURCES ${SOURCES}) diff --git a/runtime/test/src/__stack_chk_fail/behavior.cpp b/runtime/test/src/__stack_chk_fail/behavior.cpp new file mode 100644 index 00000000..3fe05127 --- /dev/null +++ b/runtime/test/src/__stack_chk_fail/behavior.cpp @@ -0,0 +1,78 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +#include + +namespace mk +{ + /// + /// @brief Defines a prototype for the __stack_chk_fail function + /// + extern "C" void ut_stack_chk_fail() noexcept; + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"__stack_chk_fail executes properly"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + ut_stack_chk_fail(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(syscall::g_bf_control_op_exit_impl_executed); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/runtime/test/src/__stack_chk_guard/CMakeLists.txt b/runtime/test/src/__stack_chk_guard/CMakeLists.txt new file mode 100644 index 00000000..ca89a72c --- /dev/null +++ b/runtime/test/src/__stack_chk_guard/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + list(APPEND SOURCES + ../../../src/x64/__stack_chk_guard.S + ) +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + list(APPEND SOURCES + ../../../src/arm/aarch64/__stack_chk_guard.S + ) +endif() + +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES} SOURCES ${SOURCES}) diff --git a/runtime/test/src/__stack_chk_guard/behavior.cpp b/runtime/test/src/__stack_chk_guard/behavior.cpp new file mode 100644 index 00000000..36fa132f --- /dev/null +++ b/runtime/test/src/__stack_chk_guard/behavior.cpp @@ -0,0 +1,77 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include +#include + +namespace mk +{ + extern "C" + { + /// @brief defines an extern of __stack_chk_guard + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + extern bsl::uintmax ut_stack_chk_guard; + } + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"__stack_chk_guard is the right value"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + constexpr auto expected{0xDEADBEEFDEADBEEF_umax}; + bsl::ut_check(ut_stack_chk_guard == expected); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/runtime/test/src/_start/CMakeLists.txt b/runtime/test/src/_start/CMakeLists.txt new file mode 100644 index 00000000..3a15f7ab --- /dev/null +++ b/runtime/test/src/_start/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + list(APPEND SOURCES + ../../../src/x64/_start.S + ) +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + list(APPEND SOURCES + ../../../src/arm/aarch64/_start.S + ) +endif() + +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES} SOURCES ${SOURCES}) diff --git a/runtime/test/src/_start/behavior.cpp b/runtime/test/src/_start/behavior.cpp new file mode 100644 index 00000000..84e00f36 --- /dev/null +++ b/runtime/test/src/_start/behavior.cpp @@ -0,0 +1,100 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// @brief stores when ext_main_entry have been executed + constinit bool g_ext_main_entry_executed{}; + /// @brief stores when bf_control_op_exit_impl have been executed + constinit bool g_bf_control_op_exit_impl_executed{}; + + /// + /// @brief Defines a prototype for the _start function + /// + extern "C" void ut_start() noexcept; + + /// + /// @brief Defines a mock of the ext_main_entry function + /// + extern "C" void + ext_main_entry() noexcept + { + g_ext_main_entry_executed = true; + } + + /// + /// @brief Defines a mock of the bf_control_op_exit_impl function + /// + extern "C" void + bf_control_op_exit_impl() noexcept + { + g_bf_control_op_exit_impl_executed = true; + } + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"_start executes properly"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + ut_start(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_ext_main_entry_executed); + bsl::ut_check(g_bf_control_op_exit_impl_executed); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/runtime/test/src/bsl/cstdio/CMakeLists.txt b/runtime/test/src/bsl/cstdio/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/runtime/test/src/bsl/cstdio/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/runtime/test/src/bsl/cstdio/behavior.cpp b/runtime/test/src/bsl/cstdio/behavior.cpp new file mode 100644 index 00000000..37bd3c9e --- /dev/null +++ b/runtime/test/src/bsl/cstdio/behavior.cpp @@ -0,0 +1,78 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/bsl/cstdio.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"fputc executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + bsl::fputc('*'); + }; + }; + }; + + bsl::ut_scenario{"fputs executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + bsl::fputs("the answer is 42"); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/runtime/test/src/bsl/cstdio/requirements.cpp b/runtime/test/src/bsl/cstdio/requirements.cpp new file mode 100644 index 00000000..4ea3cda6 --- /dev/null +++ b/runtime/test/src/bsl/cstdio/requirements.cpp @@ -0,0 +1,51 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/bsl/cstdio.hpp" + +#include +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(bsl::fputc('*'))); + static_assert(noexcept(bsl::fputs("the answer is 42"))); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/runtime/test/src/bsl/details/print_thread_id/CMakeLists.txt b/runtime/test/src/bsl/details/print_thread_id/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/runtime/test/src/bsl/details/print_thread_id/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/runtime/test/src/bsl/details/print_thread_id/behavior.cpp b/runtime/test/src/bsl/details/print_thread_id/behavior.cpp new file mode 100644 index 00000000..0e43e957 --- /dev/null +++ b/runtime/test/src/bsl/details/print_thread_id/behavior.cpp @@ -0,0 +1,71 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/bsl/details/print_thread_id.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"print_thread_id executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::details::out_type o{}; + bsl::ut_then{} = [&]() noexcept { + bsl::details::ut_print_thread_id(o); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/runtime/test/src/bsl/details/print_thread_id/requirements.cpp b/runtime/test/src/bsl/details/print_thread_id/requirements.cpp new file mode 100644 index 00000000..fbb93dbf --- /dev/null +++ b/runtime/test/src/bsl/details/print_thread_id/requirements.cpp @@ -0,0 +1,51 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/bsl/details/print_thread_id.hpp" + +#include +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::details::out_type o{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(bsl::details::ut_print_thread_id(o))); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/runtime/test/src/bsl/details/putc_stderr/CMakeLists.txt b/runtime/test/src/bsl/details/putc_stderr/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/runtime/test/src/bsl/details/putc_stderr/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/runtime/test/src/bsl/details/putc_stderr/behavior.cpp b/runtime/test/src/bsl/details/putc_stderr/behavior.cpp new file mode 100644 index 00000000..ce4f15e0 --- /dev/null +++ b/runtime/test/src/bsl/details/putc_stderr/behavior.cpp @@ -0,0 +1,70 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/bsl/details/putc_stderr.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"putc_stderr executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + bsl::details::ut_putc_stderr('*'); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/runtime/test/src/bsl/details/putc_stderr/requirements.cpp b/runtime/test/src/bsl/details/putc_stderr/requirements.cpp new file mode 100644 index 00000000..7ca8c7df --- /dev/null +++ b/runtime/test/src/bsl/details/putc_stderr/requirements.cpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/bsl/details/putc_stderr.hpp" + +#include +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(bsl::details::ut_putc_stderr({}))); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/runtime/test/src/bsl/details/putc_stdout/CMakeLists.txt b/runtime/test/src/bsl/details/putc_stdout/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/runtime/test/src/bsl/details/putc_stdout/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/runtime/test/src/bsl/details/putc_stdout/behavior.cpp b/runtime/test/src/bsl/details/putc_stdout/behavior.cpp new file mode 100644 index 00000000..56958fd4 --- /dev/null +++ b/runtime/test/src/bsl/details/putc_stdout/behavior.cpp @@ -0,0 +1,70 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/bsl/details/putc_stdout.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"putc_stdout executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + bsl::details::ut_putc_stdout('*'); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/runtime/test/src/bsl/details/putc_stdout/requirements.cpp b/runtime/test/src/bsl/details/putc_stdout/requirements.cpp new file mode 100644 index 00000000..1b755335 --- /dev/null +++ b/runtime/test/src/bsl/details/putc_stdout/requirements.cpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/bsl/details/putc_stdout.hpp" + +#include +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(bsl::details::ut_putc_stdout({}))); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/runtime/test/src/bsl/details/puts_stderr/CMakeLists.txt b/runtime/test/src/bsl/details/puts_stderr/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/runtime/test/src/bsl/details/puts_stderr/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/runtime/test/src/bsl/details/puts_stderr/behavior.cpp b/runtime/test/src/bsl/details/puts_stderr/behavior.cpp new file mode 100644 index 00000000..7eb72bcd --- /dev/null +++ b/runtime/test/src/bsl/details/puts_stderr/behavior.cpp @@ -0,0 +1,70 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/bsl/details/puts_stderr.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"puts_stderr executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + bsl::details::ut_puts_stderr(""); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/runtime/test/src/bsl/details/puts_stderr/requirements.cpp b/runtime/test/src/bsl/details/puts_stderr/requirements.cpp new file mode 100644 index 00000000..505c0d12 --- /dev/null +++ b/runtime/test/src/bsl/details/puts_stderr/requirements.cpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/bsl/details/puts_stderr.hpp" + +#include +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(bsl::details::ut_puts_stderr(""))); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/runtime/test/src/bsl/details/puts_stdout/CMakeLists.txt b/runtime/test/src/bsl/details/puts_stdout/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/runtime/test/src/bsl/details/puts_stdout/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/runtime/test/src/bsl/details/puts_stdout/behavior.cpp b/runtime/test/src/bsl/details/puts_stdout/behavior.cpp new file mode 100644 index 00000000..3d8e7104 --- /dev/null +++ b/runtime/test/src/bsl/details/puts_stdout/behavior.cpp @@ -0,0 +1,70 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/bsl/details/puts_stdout.hpp" + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"puts_stdout executes"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + bsl::details::ut_puts_stdout(""); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/runtime/test/src/bsl/details/puts_stdout/requirements.cpp b/runtime/test/src/bsl/details/puts_stdout/requirements.cpp new file mode 100644 index 00000000..e72bc4f1 --- /dev/null +++ b/runtime/test/src/bsl/details/puts_stdout/requirements.cpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../../src/bsl/details/puts_stdout.hpp" + +#include +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(bsl::details::ut_puts_stdout(""))); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/runtime/test/src/memcpy/CMakeLists.txt b/runtime/test/src/memcpy/CMakeLists.txt new file mode 100644 index 00000000..6da5445d --- /dev/null +++ b/runtime/test/src/memcpy/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + list(APPEND SOURCES + ../../../src/x64/memcpy.S + ) +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + list(APPEND SOURCES + ../../../src/arm/aarch64/memcpy.S + ) +endif() + +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES} SOURCES ${SOURCES}) diff --git a/runtime/test/src/memcpy/behavior.cpp b/runtime/test/src/memcpy/behavior.cpp new file mode 100644 index 00000000..e96c3909 --- /dev/null +++ b/runtime/test/src/memcpy/behavior.cpp @@ -0,0 +1,282 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Provides the prototype for memcpy + /// + /// + /// @param dst pointer to the destination array where the content is to + /// be copied, type-casted to a pointer of type void*. + /// @param src pointer to the source of data to be copied, type-casted to + /// a pointer of type const void*. + /// @param num number of bytes to copy. + /// @return Returns dst + /// + extern "C" [[nodiscard]] auto + ut_memcpy(void *const dst, void const *const src, bsl::uintmax const num) noexcept -> void *; + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"copy an array of size 1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{1_umax}; + bsl::array data_dst{}; + bsl::array data_src{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_u8}; + for (auto const elem : data_src) { + *elem.data = val.get(); + } + bsl::discard( + ut_memcpy(data_dst.data(), data_src.data(), data_src.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == val); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 15 (unaligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{15_umax}; + bsl::array data_dst{}; + bsl::array data_src{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_u8}; + for (auto const elem : data_src) { + *elem.data = val.get(); + } + bsl::discard( + ut_memcpy(data_dst.data(), data_src.data(), data_src.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == val); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 16 (aligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{16_umax}; + bsl::array data_dst{}; + bsl::array data_src{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_u8}; + for (auto const elem : data_src) { + *elem.data = val.get(); + } + bsl::discard( + ut_memcpy(data_dst.data(), data_src.data(), data_src.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == val); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 31 (unaligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{31_umax}; + bsl::array data_dst{}; + bsl::array data_src{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_u8}; + for (auto const elem : data_src) { + *elem.data = val.get(); + } + bsl::discard( + ut_memcpy(data_dst.data(), data_src.data(), data_src.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == val); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 32 (aligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{32_umax}; + bsl::array data_dst{}; + bsl::array data_src{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_u8}; + for (auto const elem : data_src) { + *elem.data = val.get(); + } + bsl::discard( + ut_memcpy(data_dst.data(), data_src.data(), data_src.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == val); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 127 (unaligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{127_umax}; + bsl::array data_dst{}; + bsl::array data_src{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_u8}; + for (auto const elem : data_src) { + *elem.data = val.get(); + } + bsl::discard( + ut_memcpy(data_dst.data(), data_src.data(), data_src.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == val); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 128 (aligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{128_umax}; + bsl::array data_dst{}; + bsl::array data_src{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_u8}; + for (auto const elem : data_src) { + *elem.data = val.get(); + } + bsl::discard( + ut_memcpy(data_dst.data(), data_src.data(), data_src.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == val); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 0xFFFFF (unaligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{0xFFFFF_umax}; + bsl::array data_dst{}; + bsl::array data_src{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_u8}; + for (auto const elem : data_src) { + *elem.data = val.get(); + } + bsl::discard( + ut_memcpy(data_dst.data(), data_src.data(), data_src.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == val); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 0x100000 (aligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{0x100000_umax}; + bsl::array data_dst{}; + bsl::array data_src{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_u8}; + for (auto const elem : data_src) { + *elem.data = val.get(); + } + bsl::discard( + ut_memcpy(data_dst.data(), data_src.data(), data_src.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == val); + } + }; + }; + }; + }; + + bsl::ut_scenario{"memcpy return"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{1_umax}; + bsl::array data_dst{}; + bsl::array data_src{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check( + ut_memcpy(data_dst.data(), data_src.data(), data_src.size_bytes().get()) == + data_dst.data()); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/runtime/test/src/memset/CMakeLists.txt b/runtime/test/src/memset/CMakeLists.txt new file mode 100644 index 00000000..45c5960a --- /dev/null +++ b/runtime/test/src/memset/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + list(APPEND SOURCES + ../../../src/x64/memset.S + ) +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + list(APPEND SOURCES + ../../../src/arm/aarch64/memset.S + ) +endif() + +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES} SOURCES ${SOURCES}) diff --git a/runtime/test/src/memset/behavior.cpp b/runtime/test/src/memset/behavior.cpp new file mode 100644 index 00000000..5487b356 --- /dev/null +++ b/runtime/test/src/memset/behavior.cpp @@ -0,0 +1,246 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include +#include +#include +#include +#include +#include +#include + +namespace mk +{ + /// + /// @brief Provides the prototype for memset + /// + /// + /// @param dst pointer to the block of memory to fill. + /// @param val value to be set. The value is passed as an int, but the + /// function fills the block of memory using the unsigned char + /// conversion of this value. + /// @param num number of bytes to be set to the val. + /// @return Returns dst + /// + extern "C" [[nodiscard]] auto + ut_memset(void *const dst, bsl::int32 const val, bsl::uintmax const num) noexcept -> void *; + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"copy an array of size 1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{1_umax}; + bsl::array data_dst{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_i32}; + bsl::discard( + ut_memset(data_dst.data(), val.get(), data_dst.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == bsl::to_u8(val)); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 15 (unaligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{15_umax}; + bsl::array data_dst{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_i32}; + bsl::discard( + ut_memset(data_dst.data(), val.get(), data_dst.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == bsl::to_u8(val)); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 16 (aligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{16_umax}; + bsl::array data_dst{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_i32}; + bsl::discard( + ut_memset(data_dst.data(), val.get(), data_dst.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == bsl::to_u8(val)); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 31 (unaligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{31_umax}; + bsl::array data_dst{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_i32}; + bsl::discard( + ut_memset(data_dst.data(), val.get(), data_dst.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == bsl::to_u8(val)); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 32 (aligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{32_umax}; + bsl::array data_dst{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_i32}; + bsl::discard( + ut_memset(data_dst.data(), val.get(), data_dst.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == bsl::to_u8(val)); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 127 (unaligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{127_umax}; + bsl::array data_dst{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_i32}; + bsl::discard( + ut_memset(data_dst.data(), val.get(), data_dst.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == bsl::to_u8(val)); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 128 (aligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{128_umax}; + bsl::array data_dst{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_i32}; + bsl::discard( + ut_memset(data_dst.data(), val.get(), data_dst.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == bsl::to_u8(val)); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 0xFFFFF (unaligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{0xFFFFF_umax}; + bsl::array data_dst{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_i32}; + bsl::discard( + ut_memset(data_dst.data(), val.get(), data_dst.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == bsl::to_u8(val)); + } + }; + }; + }; + }; + + bsl::ut_scenario{"copy an array of size 0x100000 (aligned)"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{0x100000_umax}; + bsl::array data_dst{}; + bsl::ut_when{} = [&]() noexcept { + constexpr auto val{42_i32}; + bsl::discard( + ut_memset(data_dst.data(), val.get(), data_dst.size_bytes().get())); + bsl::ut_then{} = [&]() noexcept { + for (auto const elem : bsl::as_const(data_dst)) { + bsl::ut_check(*elem.data == bsl::to_u8(val)); + } + }; + }; + }; + }; + + bsl::ut_scenario{"memset return"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + constexpr auto size{1_umax}; + bsl::array data_dst{}; + bsl::ut_then{} = [&]() noexcept { + constexpr auto val{42_i32}; + bsl::ut_check( + ut_memset(data_dst.data(), val.get(), data_dst.size_bytes().get()) == + data_dst.data()); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/syscall/CMakeLists.txt b/syscall/CMakeLists.txt index 5557297b..e2445dbd 100644 --- a/syscall/CMakeLists.txt +++ b/syscall/CMakeLists.txt @@ -19,98 +19,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -if (NOT CMAKE_PROJECT_NAME STREQUAL "hypervisor_microkernel") - add_library(syscall) - - target_include_directories(syscall PUBLIC - include/cpp/ - ) - - target_sources(syscall PRIVATE - src/x64/bf_callback_op_register_bootstrap_impl.S - src/x64/bf_callback_op_register_fail_impl.S - src/x64/bf_callback_op_register_vmexit_impl.S - src/x64/bf_callback_op_wait_impl.S - src/x64/bf_control_op_exit_impl.S - src/x64/bf_debug_op_dump_vm_impl.S - src/x64/bf_debug_op_dump_vmexit_log_impl.S - src/x64/bf_debug_op_dump_vp_impl.S - src/x64/bf_debug_op_dump_vps_impl.S - src/x64/bf_debug_op_out_impl.S - src/x64/bf_debug_op_write_c_impl.S - src/x64/bf_debug_op_write_str_impl.S - src/x64/bf_handle_op_close_handle_impl.S - src/x64/bf_handle_op_open_handle_impl.S - src/x64/bf_intrinsic_op_read_msr_impl.S - src/x64/bf_intrinsic_op_write_msr_impl.S - src/x64/bf_mem_op_alloc_page_impl.S - src/x64/bf_mem_op_virt_to_phys_impl.S - src/x64/bf_tls_rax_impl.S - src/x64/bf_tls_rbx_impl.S - src/x64/bf_tls_rcx_impl.S - src/x64/bf_tls_rdx_impl.S - src/x64/bf_tls_rbp_impl.S - src/x64/bf_tls_rsi_impl.S - src/x64/bf_tls_rdi_impl.S - src/x64/bf_tls_r8_impl.S - src/x64/bf_tls_r9_impl.S - src/x64/bf_tls_r10_impl.S - src/x64/bf_tls_r11_impl.S - src/x64/bf_tls_r12_impl.S - src/x64/bf_tls_r13_impl.S - src/x64/bf_tls_r14_impl.S - src/x64/bf_tls_r15_impl.S - src/x64/bf_tls_set_rax_impl.S - src/x64/bf_tls_set_rbx_impl.S - src/x64/bf_tls_set_rcx_impl.S - src/x64/bf_tls_set_rdx_impl.S - src/x64/bf_tls_set_rbp_impl.S - src/x64/bf_tls_set_rsi_impl.S - src/x64/bf_tls_set_rdi_impl.S - src/x64/bf_tls_set_r8_impl.S - src/x64/bf_tls_set_r9_impl.S - src/x64/bf_tls_set_r10_impl.S - src/x64/bf_tls_set_r11_impl.S - src/x64/bf_tls_set_r12_impl.S - src/x64/bf_tls_set_r13_impl.S - src/x64/bf_tls_set_r14_impl.S - src/x64/bf_tls_set_r15_impl.S - src/x64/bf_tls_thread_id_impl.S - src/x64/bf_vm_op_create_vm_impl.S - src/x64/bf_vm_op_destroy_vm_impl.S - src/x64/bf_vp_op_create_vp_impl.S - src/x64/bf_vp_op_destroy_vp_impl.S - src/x64/bf_vps_op_advance_ip_and_run_current_impl.S - src/x64/bf_vps_op_advance_ip_impl.S - src/x64/bf_vps_op_create_vps_impl.S - src/x64/bf_vps_op_destroy_vps_impl.S - src/x64/bf_vps_op_init_as_root_impl.S - src/x64/bf_vps_op_promote_impl.S - src/x64/bf_vps_op_read_reg_impl.S - src/x64/bf_vps_op_read8_impl.S - src/x64/bf_vps_op_read16_impl.S - src/x64/bf_vps_op_read32_impl.S - src/x64/bf_vps_op_read64_impl.S - src/x64/bf_vps_op_run_impl.S - src/x64/bf_vps_op_run_current_impl.S - src/x64/bf_vps_op_write_reg_impl.S - src/x64/bf_vps_op_write8_impl.S - src/x64/bf_vps_op_write16_impl.S - src/x64/bf_vps_op_write32_impl.S - src/x64/bf_vps_op_write64_impl.S - ) - - target_link_libraries(syscall PUBLIC - bsl - ) +if(CMAKE_PROJECT_NAME STREQUAL "hypervisor_microkernel") + include(mk_lib.cmake) else() - add_library(syscall INTERFACE) - - target_include_directories(syscall INTERFACE - include/cpp/ - ) - - target_link_libraries(syscall INTERFACE - bsl - ) + include(ext_lib_cpp.cmake) endif() diff --git a/syscall/ext_lib_cpp.cmake b/syscall/ext_lib_cpp.cmake new file mode 100644 index 00000000..a63bb751 --- /dev/null +++ b/syscall/ext_lib_cpp.cmake @@ -0,0 +1,248 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/function/hypervisor_target_source.cmake) + +add_library(syscall) + +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + +target_include_directories(syscall PUBLIC + include/cpp + src/cpp +) + +# ------------------------------------------------------------------------------ +# Headers +# ------------------------------------------------------------------------------ + +list(APPEND HEADERS + ${CMAKE_CURRENT_LIST_DIR}/include/cpp/bf_constants.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/cpp/bf_reg_t.hpp + ${CMAKE_CURRENT_LIST_DIR}/include/cpp/bf_types.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/cpp/bf_control_ops.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/cpp/bf_debug_ops.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/cpp/bf_syscall_impl.hpp + ${CMAKE_CURRENT_LIST_DIR}/src/cpp/bf_syscall_t.hpp +) + +# ------------------------------------------------------------------------------ +# Sources +# ------------------------------------------------------------------------------ + +if(HYPERVISOR_TARGET_ARCH STREQUAL "AuthenticAMD" OR HYPERVISOR_TARGET_ARCH STREQUAL "GenuineIntel") + hypervisor_target_source(syscall src/x64/bf_callback_op_register_bootstrap_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_callback_op_register_fail_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_callback_op_register_vmexit_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_control_op_exit_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_control_op_wait_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_debug_op_dump_ext_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_debug_op_dump_huge_pool_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_debug_op_dump_page_pool_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_debug_op_dump_vm_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_debug_op_dump_vmexit_log_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_debug_op_dump_vp_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_debug_op_dump_vps_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_debug_op_out_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_debug_op_write_c_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_debug_op_write_str_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_handle_op_close_handle_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_handle_op_open_handle_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_intrinsic_op_invept_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_intrinsic_op_invlpga_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_intrinsic_op_invvpid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_intrinsic_op_rdmsr_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_intrinsic_op_wrmsr_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_mem_op_alloc_heap_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_mem_op_alloc_huge_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_mem_op_alloc_page_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_mem_op_free_huge_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_mem_op_free_page_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_extid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_online_pps_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_ppid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_rax_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_rbx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_rcx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_rdx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_rbp_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_rsi_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_rdi_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_r8_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_r9_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_r10_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_r11_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_r12_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_r13_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_r14_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_r15_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_rax_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_rbx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_rcx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_rdx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_rbp_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_rsi_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_rdi_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_r8_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_r9_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_r10_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_r11_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_r12_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_r13_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_r14_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_set_r15_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_thread_id_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_vmid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_vpid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_tls_vpsid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vm_op_create_vm_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vm_op_destroy_vm_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vp_op_create_vp_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vp_op_destroy_vp_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vp_op_migrate_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_advance_ip_and_run_current_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_advance_ip_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_clear_vps_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_create_vps_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_destroy_vps_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_init_as_root_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_promote_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_read_reg_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_read8_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_read16_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_read32_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_read64_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_run_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_run_current_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_write_reg_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_write8_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_write16_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_write32_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/x64/bf_vps_op_write64_impl.S ${HEADERS}) +endif() + +if(HYPERVISOR_TARGET_ARCH STREQUAL "aarch64") + hypervisor_target_source(syscall src/arm/aarch64/bf_callback_op_register_bootstrap_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_callback_op_register_fail_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_callback_op_register_vmexit_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_control_op_exit_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_control_op_wait_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_debug_op_dump_ext_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_debug_op_dump_huge_pool_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_debug_op_dump_page_pool_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_debug_op_dump_vm_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_debug_op_dump_vmexit_log_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_debug_op_dump_vp_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_debug_op_dump_vps_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_debug_op_out_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_debug_op_write_c_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_debug_op_write_str_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_handle_op_close_handle_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_handle_op_open_handle_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_intrinsic_op_invept_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_intrinsic_op_invlpga_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_intrinsic_op_invvpid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_intrinsic_op_rdmsr_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_intrinsic_op_wrmsr_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_mem_op_alloc_heap_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_mem_op_alloc_huge_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_mem_op_alloc_page_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_mem_op_free_huge_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_mem_op_free_page_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_extid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_online_pps_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_ppid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_rax_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_rbx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_rcx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_rdx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_rbp_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_rsi_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_rdi_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_r8_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_r9_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_r10_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_r11_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_r12_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_r13_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_r14_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_r15_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_rax_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_rbx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_rcx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_rdx_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_rbp_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_rsi_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_rdi_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_r8_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_r9_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_r10_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_r11_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_r12_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_r13_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_r14_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_set_r15_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_thread_id_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_vmid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_vpid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_tls_vpsid_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vm_op_create_vm_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vm_op_destroy_vm_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vp_op_create_vp_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vp_op_destroy_vp_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vp_op_migrate_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_advance_ip_and_run_current_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_advance_ip_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_clear_vps_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_create_vps_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_destroy_vps_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_init_as_root_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_promote_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_read_reg_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_read8_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_read16_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_read32_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_read64_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_run_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_run_current_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_write_reg_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_write8_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_write16_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_write32_impl.S ${HEADERS}) + hypervisor_target_source(syscall src/arm/aarch64/bf_vps_op_write64_impl.S ${HEADERS}) +endif() + +# ------------------------------------------------------------------------------ +# Libraries +# ------------------------------------------------------------------------------ + +target_link_libraries(syscall PUBLIC + bsl + hypervisor +) + +# ------------------------------------------------------------------------------ +# Install +# ------------------------------------------------------------------------------ + +install(TARGETS syscall DESTINATION lib) diff --git a/syscall/include/cpp/bf_constants.hpp b/syscall/include/cpp/bf_constants.hpp new file mode 100644 index 00000000..ce5f2c1a --- /dev/null +++ b/syscall/include/cpp/bf_constants.hpp @@ -0,0 +1,430 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef BF_CONSTANTS_HPP +#define BF_CONSTANTS_HPP + +#include + +#include + +namespace syscall +{ + // ------------------------------------------------------------------------- + // Special IDs + // ------------------------------------------------------------------------- + + /// @brief Defines an invalid ID for an extension, VM, VP and VPS + constexpr auto BF_INVALID_ID{0xFFFF_u16}; + + /// @brief Defines the bootstrap physical processor ID + constexpr auto BF_BS_PPID{0x0_u16}; + + /// @brief Defines the root virtual machine ID + constexpr auto BF_ROOT_VMID{0x0_u16}; + + // ------------------------------------------------------------------------- + // Syscall Status Codes + // ------------------------------------------------------------------------- + + /// @brief Used to indicated that the syscall returned successfully + constexpr auto BF_STATUS_SUCCESS{0x0000000000000000_u64}; + /// @brief Indicates an unknown error occurred + constexpr auto BF_STATUS_FAILURE_UNKNOWN{0xDEAD000000010001_u64}; + /// @brief Indicates the syscall is unsupported + constexpr auto BF_STATUS_FAILURE_INVALID_HANDLE{0xDEAD000000020001_u64}; + /// @brief Indicates the provided handle is invalid + constexpr auto BF_STATUS_FAILURE_UNSUPPORTED{0xDEAD000000040001_u64}; + /// @brief Indicates the extension is not allowed to execute this syscall + constexpr auto BF_STATUS_INVALID_PERM_EXT{0xDEAD000000010002_u64}; + /// @brief Indicates the policy engine denied the syscall + constexpr auto BF_STATUS_INVALID_PERM_DENIED{0xDEAD000000020002_u64}; + /// @brief Indicates param 0 is invalid + constexpr auto BF_STATUS_INVALID_PARAMS0{0xDEAD000000010003_u64}; + /// @brief Indicates param 1 is invalid + constexpr auto BF_STATUS_INVALID_PARAMS1{0xDEAD000000020003_u64}; + /// @brief Indicates param 2 is invalid + constexpr auto BF_STATUS_INVALID_PARAMS2{0xDEAD000000040003_u64}; + /// @brief Indicates param 3 is invalid + constexpr auto BF_STATUS_INVALID_PARAMS3{0xDEAD000000080003_u64}; + /// @brief Indicates param 4 is invalid + constexpr auto BF_STATUS_INVALID_PARAMS4{0xDEAD000000100003_u64}; + /// @brief Indicates param 5 is invalid + constexpr auto BF_STATUS_INVALID_PARAMS5{0xDEAD000000200003_u64}; + + // ------------------------------------------------------------------------- + // Syscall Inputs + // ------------------------------------------------------------------------- + + /// @brief Defines the BF_SYSCALL_SIG field for RAX + constexpr auto BF_HYPERCALL_SIG_VAL{0x6642000000000000_u64}; + /// @brief Defines a mask for BF_SYSCALL_SIG + constexpr auto BF_HYPERCALL_SIG_MASK{0xFFFF000000000000_u64}; + /// @brief Defines a mask for BF_SYSCALL_FLAGS + constexpr auto BF_HYPERCALL_FLAGS_MASK{0x0000FFFF00000000_u64}; + /// @brief Defines a mask for BF_SYSCALL_OP + constexpr auto BF_HYPERCALL_OPCODE_MASK{0xFFFF0000FFFF0000_u64}; + /// @brief Defines a mask for BF_SYSCALL_OP (with no signature added) + constexpr auto BF_HYPERCALL_OPCODE_NOSIG_MASK{0x00000000FFFF0000_u64}; + /// @brief Defines a mask for BF_SYSCALL_IDX + constexpr auto BF_HYPERCALL_INDEX_MASK{0x000000000000FFFF_u64}; + + /// + /// @brief n/a + /// + /// + /// @param rax n/a + /// @return n/a + /// + [[nodiscard]] constexpr auto + bf_syscall_sig(bf_uint64_t const &rax) noexcept -> bf_uint64_t + { + return rax & BF_HYPERCALL_SIG_MASK; + } + + /// + /// @brief n/a + /// + /// + /// @param rax n/a + /// @return n/a + /// + [[nodiscard]] constexpr auto + bf_syscall_flags(bf_uint64_t const &rax) noexcept -> bf_uint64_t + { + return rax & BF_HYPERCALL_FLAGS_MASK; + } + + /// + /// @brief n/a + /// + /// + /// @param rax n/a + /// @return n/a + /// + [[nodiscard]] constexpr auto + bf_syscall_opcode(bf_uint64_t const &rax) noexcept -> bf_uint64_t + { + return rax & BF_HYPERCALL_OPCODE_MASK; + } + + /// + /// @brief n/a + /// + /// + /// @param rax n/a + /// @return n/a + /// + [[nodiscard]] constexpr auto + bf_syscall_opcode_nosig(bf_uint64_t const &rax) noexcept -> bf_uint64_t + { + return rax & BF_HYPERCALL_OPCODE_NOSIG_MASK; + } + + /// + /// @brief n/a + /// + /// + /// @param rax n/a + /// @return n/a + /// + [[nodiscard]] constexpr auto + bf_syscall_index(bf_uint64_t const &rax) noexcept -> bf_uint64_t + { + return rax & BF_HYPERCALL_INDEX_MASK; + } + + // ------------------------------------------------------------------------- + // Specification IDs + // ------------------------------------------------------------------------- + + /// @brief Defines the ID for version #1 of this spec + constexpr auto BF_SPEC_ID1_VAL{0x31236642_u32}; + + /// @brief Defines the mask for checking support for version #1 of this spec + constexpr auto BF_SPEC_ID1_MASK{0x2_u32}; + + /// @brief Defines the value likely returned by bf_handle_op_version + constexpr auto BF_ALL_SPECS_SUPPORTED_VAL{0x2_u32}; + + /// + /// @brief n/a + /// + /// + /// @param version n/a + /// @return n/a + /// + [[nodiscard]] constexpr auto + bf_is_spec1_supported(bf_uint32_t const &version) noexcept -> bool + { + return (!(version & BF_SPEC_ID1_MASK).is_zero()); + } + + // ------------------------------------------------------------------------- + // Syscall Opcodes - Control Support + // ------------------------------------------------------------------------- + + /// @brief Defines the syscall opcode for bf_control_op + constexpr auto BF_CONTROL_OP_VAL{0x6642000000000000_u64}; + /// @brief Defines the syscall opcode for bf_control_op (nosig) + constexpr auto BF_CONTROL_OP_NOSIG_VAL{0x0000000000000000_u64}; + + // ------------------------------------------------------------------------- + // Syscall Opcodes - Handle Support + // ------------------------------------------------------------------------- + + /// @brief Defines the syscall opcode for bf_handle_op + constexpr auto BF_HANDLE_OP_VAL{0x6642000000010000_u64}; + /// @brief Defines the syscall opcode for bf_handle_op (nosig) + constexpr auto BF_HANDLE_OP_NOSIG_VAL{0x0000000000010000_u64}; + + // ------------------------------------------------------------------------- + // Syscall Opcodes - Debug Support + // ------------------------------------------------------------------------- + + /// @brief Defines the syscall opcode for bf_debug_op + constexpr auto BF_DEBUG_OP_VAL{0x6642000000020000_u64}; + /// @brief Defines the syscall opcode for bf_debug_op (nosig) + constexpr auto BF_DEBUG_OP_NOSIG_VAL{0x00000000000020000_u64}; + + // ------------------------------------------------------------------------- + // Syscall Opcodes - Callback Support + // ------------------------------------------------------------------------- + + /// @brief Defines the syscall opcode for bf_callback_op + constexpr auto BF_CALLBACK_OP_VAL{0x6642000000030000_u64}; + /// @brief Defines the syscall opcode for bf_callback_op (nosig) + constexpr auto BF_CALLBACK_OP_NOSIG_VAL{0x0000000000030000_u64}; + + // ------------------------------------------------------------------------- + // Syscall Opcodes - VM Support + // ------------------------------------------------------------------------- + + /// @brief Defines the syscall opcode for bf_vm_op + constexpr auto BF_VM_OP_VAL{0x6642000000040000_u64}; + /// @brief Defines the syscall opcode for bf_vm_op (nosig) + constexpr auto BF_VM_OP_NOSIG_VAL{0x0000000000040000_u64}; + + // ------------------------------------------------------------------------- + // Syscall Opcodes - VP Support + // ------------------------------------------------------------------------- + + /// @brief Defines the syscall opcode for bf_vp_op + constexpr auto BF_VP_OP_VAL{0x6642000000050000_u64}; + /// @brief Defines the syscall opcode for bf_vp_op (nosig) + constexpr auto BF_VP_OP_NOSIG_VAL{0x0000000000050000_u64}; + + // ------------------------------------------------------------------------- + // Syscall Opcodes - VPS Support + // ------------------------------------------------------------------------- + + /// @brief Defines the syscall opcode for bf_vps_op + constexpr auto BF_VPS_OP_VAL{0x6642000000060000_u64}; + /// @brief Defines the syscall opcode for bf_vps_op (nosig) + constexpr auto BF_VPS_OP_NOSIG_VAL{0x0000000000060000_u64}; + + // ------------------------------------------------------------------------- + // Syscall Opcodes - Intrinsic Support + // ------------------------------------------------------------------------- + + /// @brief Defines the syscall opcode for bf_intrinsic_op + constexpr auto BF_INTRINSIC_OP_VAL{0x6642000000070000_u64}; + /// @brief Defines the syscall opcode for bf_intrinsic_op (nosig) + constexpr auto BF_INTRINSIC_OP_NOSIG_VAL{0x0000000000070000_u64}; + + // ------------------------------------------------------------------------- + // Syscall Opcodes - Mem Support + // ------------------------------------------------------------------------- + + /// @brief Defines the syscall opcode for bf_mem_op + constexpr auto BF_MEM_OP_VAL{0x6642000000080000_u64}; + /// @brief Defines the syscall opcode for bf_mem_op (nosig) + constexpr auto BF_MEM_OP_NOSIG_VAL{0x0000000000080000_u64}; + + // ------------------------------------------------------------------------- + // TLS Offsets + // ------------------------------------------------------------------------- + + /// @brief stores the offset for rax + constexpr auto TLS_OFFSET_RAX{0x800_u64}; + /// @brief stores the offset for rbx + constexpr auto TLS_OFFSET_RBX{0x808_u64}; + /// @brief stores the offset for rcx + constexpr auto TLS_OFFSET_RCX{0x810_u64}; + /// @brief stores the offset for rdx + constexpr auto TLS_OFFSET_RDX{0x818_u64}; + /// @brief stores the offset for rbp + constexpr auto TLS_OFFSET_RBP{0x820_u64}; + /// @brief stores the offset for rsi + constexpr auto TLS_OFFSET_RSI{0x828_u64}; + /// @brief stores the offset for rdi + constexpr auto TLS_OFFSET_RDI{0x830_u64}; + /// @brief stores the offset for r8 + constexpr auto TLS_OFFSET_R8{0x838_u64}; + /// @brief stores the offset for r9 + constexpr auto TLS_OFFSET_R9{0x840_u64}; + /// @brief stores the offset for r10 + constexpr auto TLS_OFFSET_R10{0x848_u64}; + /// @brief stores the offset for r11 + constexpr auto TLS_OFFSET_R11{0x850_u64}; + /// @brief stores the offset for r12 + constexpr auto TLS_OFFSET_R12{0x858_u64}; + /// @brief stores the offset for r13 + constexpr auto TLS_OFFSET_R13{0x860_u64}; + /// @brief stores the offset for r14 + constexpr auto TLS_OFFSET_R14{0x868_u64}; + /// @brief stores the offset for r15 + constexpr auto TLS_OFFSET_R15{0x870_u64}; + /// @brief stores the offset of the active extid + constexpr auto TLS_OFFSET_ACTIVE_EXTID{0xFF0_u64}; + /// @brief stores the offset of the active vmid + constexpr auto TLS_OFFSET_ACTIVE_VMID{0xFF2_u64}; + /// @brief stores the offset of the active vpid + constexpr auto TLS_OFFSET_ACTIVE_VPID{0xFF4_u64}; + /// @brief stores the offset of the active vpsid + constexpr auto TLS_OFFSET_ACTIVE_VPSID{0xFF6_u64}; + /// @brief stores the offset of the active ppid + constexpr auto TLS_OFFSET_ACTIVE_PPID{0xFF8_u64}; + /// @brief stores the number of PPs that are online + constexpr auto TLS_OFFSET_ONLINE_PPS{0xFFA_u64}; + + // ------------------------------------------------------------------------- + // Syscall Indexes + // ------------------------------------------------------------------------- + + // clang-format off + + /// @brief Defines the syscall index for bf_control_op_exit + constexpr auto BF_CONTROL_OP_EXIT_IDX_VAL{0x0000000000000000_u64}; + /// @brief Defines the syscall index for bf_control_op_wait + constexpr auto BF_CONTROL_OP_WAIT_IDX_VAL{0x0000000000000001_u64}; + + /// @brief Defines the syscall index for bf_handle_op_open_handle + constexpr auto BF_HANDLE_OP_OPEN_HANDLE_IDX_VAL{0x0000000000000000_u64}; + /// @brief Defines the syscall index for bf_handle_op_close_handle + constexpr auto BF_HANDLE_OP_CLOSE_HANDLE_IDX_VAL{0x0000000000000001_u64}; + + /// @brief Defines the syscall index for bf_debug_op_out + constexpr auto BF_DEBUG_OP_OUT_IDX_VAL{0x0000000000000000_u64}; + /// @brief Defines the syscall index for bf_debug_op_dump_vm + constexpr auto BF_DEBUG_OP_DUMP_VM_IDX_VAL{0x0000000000000001_u64}; + /// @brief Defines the syscall index for bf_debug_op_dump_vp + constexpr auto BF_DEBUG_OP_DUMP_VP_IDX_VAL{0x0000000000000002_u64}; + /// @brief Defines the syscall index for bf_debug_op_dump_vps + constexpr auto BF_DEBUG_OP_DUMP_VPS_IDX_VAL{0x0000000000000003_u64}; + /// @brief Defines the syscall index for bf_debug_op_dump_vmexit_log + constexpr auto BF_DEBUG_OP_DUMP_VMEXIT_LOG_IDX_VAL{0x0000000000000004_u64}; + /// @brief Defines the syscall index for bf_debug_op_write_c + constexpr auto BF_DEBUG_OP_WRITE_C_IDX_VAL{0x0000000000000005_u64}; + /// @brief Defines the syscall index for bf_debug_op_write_str + constexpr auto BF_DEBUG_OP_WRITE_STR_IDX_VAL{0x0000000000000006_u64}; + /// @brief Defines the syscall index for bf_debug_op_dump_ext + constexpr auto BF_DEBUG_OP_DUMP_EXT_IDX_VAL{0x0000000000000007_u64}; + /// @brief Defines the syscall index for bf_debug_op_dump_page_pool + constexpr auto BF_DEBUG_OP_DUMP_PAGE_POOL_IDX_VAL{0x0000000000000008_u64}; + /// @brief Defines the syscall index for bf_debug_op_dump_huge_pool + constexpr auto BF_DEBUG_OP_DUMP_HUGE_POOL_IDX_VAL{0x0000000000000009_u64}; + + /// @brief Defines the syscall index for bf_callback_op_register_bootstrap + constexpr auto BF_CALLBACK_OP_REGISTER_BOOTSTRAP_IDX_VAL{0x0000000000000002_u64}; + /// @brief Defines the syscall index for bf_callback_op_register_vmexit + constexpr auto BF_CALLBACK_OP_REGISTER_VMEXIT_IDX_VAL{0x0000000000000003_u64}; + /// @brief Defines the syscall index for bf_callback_op_register_fail + constexpr auto BF_CALLBACK_OP_REGISTER_FAIL_IDX_VAL{0x0000000000000004_u64}; + + /// @brief Defines the syscall index for bf_vm_op_create_vm + constexpr auto BF_VM_OP_CREATE_VM_IDX_VAL{0x0000000000000000_u64}; + /// @brief Defines the syscall index for bf_vm_op_destroy_vm + constexpr auto BF_VM_OP_DESTROY_VM_IDX_VAL{0x0000000000000001_u64}; + + /// @brief Defines the syscall index for bf_vp_op_create_vp + constexpr auto BF_VP_OP_CREATE_VP_IDX_VAL{0x0000000000000000_u64}; + /// @brief Defines the syscall index for bf_vp_op_destroy_vp + constexpr auto BF_VP_OP_DESTROY_VP_IDX_VAL{0x0000000000000001_u64}; + /// @brief Defines the syscall index for bf_vp_op_migrate + constexpr auto BF_VP_OP_MIGRATE_IDX_VAL{0x0000000000000002_u64}; + + /// @brief Defines the syscall index for bf_vps_op_create_vps + constexpr auto BF_VPS_OP_CREATE_VPS_IDX_VAL{0x0000000000000000_u64}; + /// @brief Defines the syscall index for bf_vps_op_destroy_vps + constexpr auto BF_VPS_OP_DESTROY_VPS_IDX_VAL{0x0000000000000001_u64}; + /// @brief Defines the syscall index for bf_vps_op_init_as_root + constexpr auto BF_VPS_OP_INIT_AS_ROOT_IDX_VAL{0x0000000000000002_u64}; + /// @brief Defines the syscall index for bf_vps_op_read8 + constexpr auto BF_VPS_OP_READ8_IDX_VAL{0x0000000000000003_u64}; + /// @brief Defines the syscall index for bf_vps_op_read16 + constexpr auto BF_VPS_OP_READ16_IDX_VAL{0x0000000000000004_u64}; + /// @brief Defines the syscall index for bf_vps_op_read32 + constexpr auto BF_VPS_OP_READ32_IDX_VAL{0x0000000000000005_u64}; + /// @brief Defines the syscall index for bf_vps_op_read64 + constexpr auto BF_VPS_OP_READ64_IDX_VAL{0x0000000000000006_u64}; + /// @brief Defines the syscall index for bf_vps_op_write + constexpr auto BF_VPS_OP_WRITE8_IDX_VAL{0x0000000000000007_u64}; + /// @brief Defines the syscall index for bf_vps_op_write + constexpr auto BF_VPS_OP_WRITE16_IDX_VAL{0x0000000000000008_u64}; + /// @brief Defines the syscall index for bf_vps_op_write + constexpr auto BF_VPS_OP_WRITE32_IDX_VAL{0x0000000000000009_u64}; + /// @brief Defines the syscall index for bf_vps_op_write + constexpr auto BF_VPS_OP_WRITE64_IDX_VAL{0x000000000000000A_u64}; + /// @brief Defines the syscall index for bf_vps_op_read_reg + constexpr auto BF_VPS_OP_READ_REG_IDX_VAL{0x000000000000000B_u64}; + /// @brief Defines the syscall index for bf_vps_op_write_reg + constexpr auto BF_VPS_OP_WRITE_REG_IDX_VAL{0x000000000000000C_u64}; + /// @brief Defines the syscall index for bf_vps_op_run + constexpr auto BF_VPS_OP_RUN_IDX_VAL{0x000000000000000D_u64}; + /// @brief Defines the syscall index for bf_vps_op_run_current + constexpr auto BF_VPS_OP_RUN_CURRENT_IDX_VAL{0x000000000000000E_u64}; + /// @brief Defines the syscall index for bf_vps_op_advance_ip + constexpr auto BF_VPS_OP_ADVANCE_IP_IDX_VAL{0x000000000000000F_u64}; + /// @brief Defines the syscall index for bf_vps_op_advance_ip_and_run_current + constexpr auto BF_VPS_OP_ADVANCE_IP_AND_RUN_CURRENT_IDX_VAL{0x0000000000000010_u64}; + /// @brief Defines the syscall index for bf_vps_op_promote + constexpr auto BF_VPS_OP_PROMOTE_IDX_VAL{0x0000000000000011_u64}; + /// @brief Defines the syscall index for bf_vps_op_clear_vps + constexpr auto BF_VPS_OP_CLEAR_VPS_IDX_VAL{0x0000000000000012_u64}; + + /// @brief Defines the syscall index for bf_intrinsic_op_rdmsr + constexpr auto BF_INTRINSIC_OP_RDMSR_IDX_VAL{0x0000000000000000_u64}; + /// @brief Defines the syscall index for bf_intrinsic_op_wrmsr + constexpr auto BF_INTRINSIC_OP_WRMSR_IDX_VAL{0x0000000000000001_u64}; + /// @brief Defines the syscall index for bf_intrinsic_op_invlpga + constexpr auto BF_INTRINSIC_OP_INVLPGA_IDX_VAL{0x0000000000000002_u64}; + /// @brief Defines the syscall index for bf_intrinsic_op_invept + constexpr auto BF_INTRINSIC_OP_INVEPT_IDX_VAL{0x0000000000000003_u64}; + /// @brief Defines the syscall index for bf_intrinsic_op_invvpid + constexpr auto BF_INTRINSIC_OP_INVVPID_IDX_VAL{0x0000000000000004_u64}; + + /// @brief Defines the syscall index for bf_mem_op_alloc_page + constexpr auto BF_MEM_OP_ALLOC_PAGE_IDX_VAL{0x0000000000000000_u64}; + /// @brief Defines the syscall index for bf_mem_op_free_page + constexpr auto BF_MEM_OP_FREE_PAGE_IDX_VAL{0x0000000000000001_u64}; + /// @brief Defines the syscall index for bf_mem_op_alloc_huge + constexpr auto BF_MEM_OP_ALLOC_HUGE_IDX_VAL{0x0000000000000002_u64}; + /// @brief Defines the syscall index for bf_mem_op_free_huge + constexpr auto BF_MEM_OP_FREE_HUGE_IDX_VAL{0x0000000000000003_u64}; + /// @brief Defines the syscall index for bf_mem_op_alloc_heap + constexpr auto BF_MEM_OP_ALLOC_HEAP_IDX_VAL{0x0000000000000004_u64}; +} + +#endif diff --git a/syscall/include/cpp/bf_reg_t.hpp b/syscall/include/cpp/bf_reg_t.hpp new file mode 100644 index 00000000..7fe3d748 --- /dev/null +++ b/syscall/include/cpp/bf_reg_t.hpp @@ -0,0 +1,191 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef BF_REG_T_HPP +#define BF_REG_T_HPP + +#include +#include + +namespace syscall +{ + /// + /// @brief Defines which register is being requested by certain syscalls + /// + enum class bf_reg_t : bsl::uint64 + { + /// @brief defines the rax register + bf_reg_t_rax = (0_u64).get(), + /// @brief defines the rbx register + bf_reg_t_rbx = (1_u64).get(), + /// @brief defines the rcx register + bf_reg_t_rcx = (2_u64).get(), + /// @brief defines the rdx register + bf_reg_t_rdx = (3_u64).get(), + /// @brief defines the rbp register + bf_reg_t_rbp = (4_u64).get(), + /// @brief defines the rsi register + bf_reg_t_rsi = (5_u64).get(), + /// @brief defines the rdi register + bf_reg_t_rdi = (6_u64).get(), + /// @brief defines the r8 register + bf_reg_t_r8 = (7_u64).get(), + /// @brief defines the r9 register + bf_reg_t_r9 = (8_u64).get(), + /// @brief defines the r10 register + bf_reg_t_r10 = (9_u64).get(), + /// @brief defines the r11 register + bf_reg_t_r11 = (10_u64).get(), + /// @brief defines the r12 register + bf_reg_t_r12 = (11_u64).get(), + /// @brief defines the r13 register + bf_reg_t_r13 = (12_u64).get(), + /// @brief defines the r14 register + bf_reg_t_r14 = (13_u64).get(), + /// @brief defines the r15 register + bf_reg_t_r15 = (14_u64).get(), + /// @brief defines the rip register + bf_reg_t_rip = (15_u64).get(), + /// @brief defines the rsp register + bf_reg_t_rsp = (16_u64).get(), + /// @brief defines the rflags register + bf_reg_t_rflags = (17_u64).get(), + /// @brief defines the gdtr_base_addr register + bf_reg_t_gdtr_base_addr = (18_u64).get(), + /// @brief defines the gdtr_limit register + bf_reg_t_gdtr_limit = (19_u64).get(), + /// @brief defines the idtr_base_addr register + bf_reg_t_idtr_base_addr = (20_u64).get(), + /// @brief defines the idtr_limit register + bf_reg_t_idtr_limit = (21_u64).get(), + /// @brief defines the es register + bf_reg_t_es = (22_u64).get(), + /// @brief defines the es_base_addr register + bf_reg_t_es_base_addr = (23_u64).get(), + /// @brief defines the es_limit register + bf_reg_t_es_limit = (24_u64).get(), + /// @brief defines the es_attributes register + bf_reg_t_es_attributes = (25_u64).get(), + /// @brief defines the cs register + bf_reg_t_cs = (26_u64).get(), + /// @brief defines the cs_base_addr register + bf_reg_t_cs_base_addr = (27_u64).get(), + /// @brief defines the cs_limit register + bf_reg_t_cs_limit = (28_u64).get(), + /// @brief defines the cs_attributes register + bf_reg_t_cs_attributes = (29_u64).get(), + /// @brief defines the ss register + bf_reg_t_ss = (30_u64).get(), + /// @brief defines the ss_base_addr register + bf_reg_t_ss_base_addr = (31_u64).get(), + /// @brief defines the ss_limit register + bf_reg_t_ss_limit = (32_u64).get(), + /// @brief defines the ss_attributes register + bf_reg_t_ss_attributes = (33_u64).get(), + /// @brief defines the ds register + bf_reg_t_ds = (34_u64).get(), + /// @brief defines the ds_base_addr register + bf_reg_t_ds_base_addr = (35_u64).get(), + /// @brief defines the ds_limit register + bf_reg_t_ds_limit = (36_u64).get(), + /// @brief defines the ds_attributes register + bf_reg_t_ds_attributes = (37_u64).get(), + /// @brief defines the fs register + bf_reg_t_fs = (38_u64).get(), + /// @brief defines the fs_base_addr register + bf_reg_t_fs_base_addr = (39_u64).get(), + /// @brief defines the fs_limit register + bf_reg_t_fs_limit = (40_u64).get(), + /// @brief defines the fs_attributes register + bf_reg_t_fs_attributes = (41_u64).get(), + /// @brief defines the gs register + bf_reg_t_gs = (42_u64).get(), + /// @brief defines the gs_base_addr register + bf_reg_t_gs_base_addr = (43_u64).get(), + /// @brief defines the gs_limit register + bf_reg_t_gs_limit = (44_u64).get(), + /// @brief defines the gs_attributes register + bf_reg_t_gs_attributes = (45_u64).get(), + /// @brief defines the ldtr register + bf_reg_t_ldtr = (46_u64).get(), + /// @brief defines the ldtr_base_addr register + // We don't have a choice in the naming here + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) + bf_reg_t_ldtr_base_addr = (47_u64).get(), + /// @brief defines the ldtr_limit register + // We don't have a choice in the naming here + // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) + bf_reg_t_ldtr_limit = (48_u64).get(), + /// @brief defines the ldtr_attributes register + bf_reg_t_ldtr_attributes = (49_u64).get(), + /// @brief defines the tr register + bf_reg_t_tr = (50_u64).get(), + /// @brief defines the tr_base_addr register + bf_reg_t_tr_base_addr = (51_u64).get(), + /// @brief defines the tr_limit register + bf_reg_t_tr_limit = (52_u64).get(), + /// @brief defines the tr_attributes register + bf_reg_t_tr_attributes = (53_u64).get(), + /// @brief defines the cr0 register + bf_reg_t_cr0 = (54_u64).get(), + /// @brief defines the cr2 register + bf_reg_t_cr2 = (55_u64).get(), + /// @brief defines the cr3 register + bf_reg_t_cr3 = (56_u64).get(), + /// @brief defines the cr4 register + bf_reg_t_cr4 = (57_u64).get(), + /// @brief defines the dr6 register + bf_reg_t_dr6 = (58_u64).get(), + /// @brief defines the dr7 register + bf_reg_t_dr7 = (59_u64).get(), + /// @brief defines the ia32_efer register + bf_reg_t_ia32_efer = (60_u64).get(), + /// @brief defines the ia32_star register + bf_reg_t_ia32_star = (61_u64).get(), + /// @brief defines the ia32_lstar register + bf_reg_t_ia32_lstar = (62_u64).get(), + /// @brief defines the ia32_cstar register + bf_reg_t_ia32_cstar = (63_u64).get(), + /// @brief defines the ia32_fmask register + bf_reg_t_ia32_fmask = (64_u64).get(), + /// @brief defines the ia32_fs_base register + bf_reg_t_ia32_fs_base = (65_u64).get(), + /// @brief defines the ia32_gs_base register + bf_reg_t_ia32_gs_base = (66_u64).get(), + /// @brief defines the ia32_kernel_gs_base register + bf_reg_t_ia32_kernel_gs_base = (67_u64).get(), + /// @brief defines the ia32_sysenter_cs register + bf_reg_t_ia32_sysenter_cs = (68_u64).get(), + /// @brief defines the ia32_sysenter_esp register + bf_reg_t_ia32_sysenter_esp = (69_u64).get(), + /// @brief defines the ia32_sysenter_eip register + bf_reg_t_ia32_sysenter_eip = (70_u64).get(), + /// @brief defines the ia32_pat register + bf_reg_t_ia32_pat = (71_u64).get(), + /// @brief defines the ia32_debugctl register + bf_reg_t_ia32_debugctl = (72_u64).get(), + }; +} + +#endif diff --git a/syscall/include/cpp/bf_types.hpp b/syscall/include/cpp/bf_types.hpp new file mode 100644 index 00000000..533065ce --- /dev/null +++ b/syscall/include/cpp/bf_types.hpp @@ -0,0 +1,75 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef BF_TYPES_HPP +#define BF_TYPES_HPP + +#include + +namespace syscall +{ + // ------------------------------------------------------------------------- + // Scalar Types + // ------------------------------------------------------------------------- + + /// @brief Defines the type used for returning status from a function + using bf_status_t = bsl::safe_uint64; + /// @brief Defines an unsigned 8bit integer + using bf_uint8_t = bsl::safe_uint8; + /// @brief Defines an unsigned 16bit integer + using bf_uint16_t = bsl::safe_uint16; + /// @brief Defines an unsigned 32bit integer + using bf_uint32_t = bsl::safe_uint32; + /// @brief Defines an unsigned 64bit integer + using bf_uint64_t = bsl::safe_uint64; + + // ------------------------------------------------------------------------- + // Bootstrap Callback Handler Type + // ------------------------------------------------------------------------- + + /// @brief Defines the signature of the bootstrap callback handler + // Entry points cannot use safe integral types + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + using bf_callback_handler_bootstrap_t = void (*)(bf_uint16_t::value_type); + + // ------------------------------------------------------------------------- + // VMExit Callback Handler Type + // ------------------------------------------------------------------------- + + /// @brief Defines the signature of the VM exit callback handler + // Entry points cannot use safe integral types + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + using bf_callback_handler_vmexit_t = void (*)(bf_uint16_t::value_type, bf_uint64_t::value_type); + + // ------------------------------------------------------------------------- + // Fast Fail Callback Handler Type + // ------------------------------------------------------------------------- + + /// @brief Defines the signature of the fast fail callback handler + // Entry points cannot use safe integral types + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + using bf_callback_handler_fail_t = void (*)(bf_uint16_t::value_type, bf_status_t::value_type); +} + +#endif diff --git a/syscall/include/cpp/mk_interface.hpp b/syscall/include/cpp/mk_interface.hpp deleted file mode 100644 index 9ea85103..00000000 --- a/syscall/include/cpp/mk_interface.hpp +++ /dev/null @@ -1,2845 +0,0 @@ -/// @copyright -/// Copyright (C) 2020 Assured Information Security, Inc. -/// -/// @copyright -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// @copyright -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// @copyright -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -/// SOFTWARE. - -#ifndef MK_INTERFACE_H -#define MK_INTERFACE_H - -#include -#include -#include -#include -#include -#include - -namespace syscall -{ - // ------------------------------------------------------------------------- - // Scalar Types - // ------------------------------------------------------------------------- - - /// @brief Defines the type used for returning status from a function - using bf_status_t = bsl::safe_uint64; - /// @brief Defines an unsigned 8bit integer - using bf_uint8_t = bsl::uint8; - /// @brief Defines an unsigned 16bit integer - using bf_uint16_t = bsl::uint16; - /// @brief Defines an unsigned 32bit integer - using bf_uint32_t = bsl::uint32; - /// @brief Defines an unsigned 64bit integer - using bf_uint64_t = bsl::uint64; - /// @brief Defines a raw pointer type - using bf_ptr_t = void const *; - - // ------------------------------------------------------------------------- - // Handle Type - // ------------------------------------------------------------------------- - - /// @class syscall::bf_handle_t - /// - /// - /// @brief The bf_handle_t structure is an opaque structure containing - /// the handle that is used by most of the syscalls in this - /// specification. The opaque structure is used internally by the C - /// wrapper interface for storing state as needed and should not be - /// accessed directly. The C wrapper is allowed to redefine the - /// internal layout of this structure at any time (e.g., the C wrapper - /// might provide an alternative layout for unit testing). - /// - // IWYU is more important here, and this rule would make this interface - // needlessly overcomplicated. - // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) - struct bf_handle_t final - { - /// @brief The handle returned by bf_handle_op_open_handle - bf_uint64_t hndl; - }; - - // ------------------------------------------------------------------------- - // Register Type - // ------------------------------------------------------------------------- - - /// @brief Defines which register is being requested by certain syscalls - // IWYU is more important here, and this rule would make this interface - // needlessly overcomplicated. - // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) - enum class bf_reg_t : bsl::uint64 - { - /// @brief defines the rax register - bf_reg_t_rax = static_cast(0), - /// @brief defines the rbx register - bf_reg_t_rbx = static_cast(1), - /// @brief defines the rcx register - bf_reg_t_rcx = static_cast(2), - /// @brief defines the rdx register - bf_reg_t_rdx = static_cast(3), - /// @brief defines the rbp register - bf_reg_t_rbp = static_cast(4), - /// @brief defines the rsi register - bf_reg_t_rsi = static_cast(5), - /// @brief defines the rdi register - bf_reg_t_rdi = static_cast(6), - /// @brief defines the r8 register - bf_reg_t_r8 = static_cast(7), - /// @brief defines the r9 register - bf_reg_t_r9 = static_cast(8), - /// @brief defines the r10 register - bf_reg_t_r10 = static_cast(9), - /// @brief defines the r11 register - bf_reg_t_r11 = static_cast(10), - /// @brief defines the r12 register - bf_reg_t_r12 = static_cast(11), - /// @brief defines the r13 register - bf_reg_t_r13 = static_cast(12), - /// @brief defines the r14 register - bf_reg_t_r14 = static_cast(13), - /// @brief defines the r15 register - bf_reg_t_r15 = static_cast(14), - /// @brief defines the rip register - bf_reg_t_rip = static_cast(15), - /// @brief defines the rsp register - bf_reg_t_rsp = static_cast(16), - /// @brief defines the rflags register - bf_reg_t_rflags = static_cast(17), - /// @brief defines the gdtr_base_addr register - bf_reg_t_gdtr_base_addr = static_cast(18), - /// @brief defines the gdtr_limit register - bf_reg_t_gdtr_limit = static_cast(19), - /// @brief defines the idtr_base_addr register - bf_reg_t_idtr_base_addr = static_cast(20), - /// @brief defines the idtr_limit register - bf_reg_t_idtr_limit = static_cast(21), - /// @brief defines the es register - bf_reg_t_es = static_cast(22), - /// @brief defines the es_base_addr register - bf_reg_t_es_base_addr = static_cast(23), - /// @brief defines the es_limit register - bf_reg_t_es_limit = static_cast(24), - /// @brief defines the es_attributes register - bf_reg_t_es_attributes = static_cast(25), - /// @brief defines the cs register - bf_reg_t_cs = static_cast(26), - /// @brief defines the cs_base_addr register - bf_reg_t_cs_base_addr = static_cast(27), - /// @brief defines the cs_limit register - bf_reg_t_cs_limit = static_cast(28), - /// @brief defines the cs_attributes register - bf_reg_t_cs_attributes = static_cast(29), - /// @brief defines the ss register - bf_reg_t_ss = static_cast(30), - /// @brief defines the ss_base_addr register - bf_reg_t_ss_base_addr = static_cast(31), - /// @brief defines the ss_limit register - bf_reg_t_ss_limit = static_cast(32), - /// @brief defines the ss_attributes register - bf_reg_t_ss_attributes = static_cast(33), - /// @brief defines the ds register - bf_reg_t_ds = static_cast(34), - /// @brief defines the ds_base_addr register - bf_reg_t_ds_base_addr = static_cast(35), - /// @brief defines the ds_limit register - bf_reg_t_ds_limit = static_cast(36), - /// @brief defines the ds_attributes register - bf_reg_t_ds_attributes = static_cast(37), - /// @brief defines the fs register - bf_reg_t_fs = static_cast(38), - /// @brief defines the fs_base_addr register - bf_reg_t_fs_base_addr = static_cast(39), - /// @brief defines the fs_limit register - bf_reg_t_fs_limit = static_cast(40), - /// @brief defines the fs_attributes register - bf_reg_t_fs_attributes = static_cast(41), - /// @brief defines the gs register - bf_reg_t_gs = static_cast(42), - /// @brief defines the gs_base_addr register - bf_reg_t_gs_base_addr = static_cast(43), - /// @brief defines the gs_limit register - bf_reg_t_gs_limit = static_cast(44), - /// @brief defines the gs_attributes register - bf_reg_t_gs_attributes = static_cast(45), - /// @brief defines the ldtr register - bf_reg_t_ldtr = static_cast(46), - /// @brief defines the ldtr_base_addr register - // We don't have a choice in the naming here - // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) - bf_reg_t_ldtr_base_addr = static_cast(47), - /// @brief defines the ldtr_limit register - // We don't have a choice in the naming here - // NOLINTNEXTLINE(bsl-identifier-typographically-unambiguous) - bf_reg_t_ldtr_limit = static_cast(48), - /// @brief defines the ldtr_attributes register - bf_reg_t_ldtr_attributes = static_cast(49), - /// @brief defines the tr register - bf_reg_t_tr = static_cast(50), - /// @brief defines the tr_base_addr register - bf_reg_t_tr_base_addr = static_cast(51), - /// @brief defines the tr_limit register - bf_reg_t_tr_limit = static_cast(52), - /// @brief defines the tr_attributes register - bf_reg_t_tr_attributes = static_cast(53), - /// @brief defines the cr0 register - bf_reg_t_cr0 = static_cast(54), - /// @brief defines the cr2 register - bf_reg_t_cr2 = static_cast(55), - /// @brief defines the cr3 register - bf_reg_t_cr3 = static_cast(56), - /// @brief defines the cr4 register - bf_reg_t_cr4 = static_cast(57), - /// @brief defines the dr6 register - bf_reg_t_dr6 = static_cast(58), - /// @brief defines the dr7 register - bf_reg_t_dr7 = static_cast(59), - /// @brief defines the ia32_efer register - bf_reg_t_ia32_efer = static_cast(60), - /// @brief defines the ia32_star register - bf_reg_t_ia32_star = static_cast(61), - /// @brief defines the ia32_lstar register - bf_reg_t_ia32_lstar = static_cast(62), - /// @brief defines the ia32_cstar register - bf_reg_t_ia32_cstar = static_cast(63), - /// @brief defines the ia32_fmask register - bf_reg_t_ia32_fmask = static_cast(64), - /// @brief defines the ia32_fs_base register - bf_reg_t_ia32_fs_base = static_cast(65), - /// @brief defines the ia32_gs_base register - bf_reg_t_ia32_gs_base = static_cast(66), - /// @brief defines the ia32_kernel_gs_base register - bf_reg_t_ia32_kernel_gs_base = static_cast(67), - /// @brief defines the ia32_sysenter_cs register - bf_reg_t_ia32_sysenter_cs = static_cast(68), - /// @brief defines the ia32_sysenter_esp register - bf_reg_t_ia32_sysenter_esp = static_cast(69), - /// @brief defines the ia32_sysenter_eip register - bf_reg_t_ia32_sysenter_eip = static_cast(70), - /// @brief defines the ia32_pat register - bf_reg_t_ia32_pat = static_cast(71), - /// @brief defines the ia32_debugctl register - bf_reg_t_ia32_debugctl = static_cast(72), - }; - - // ------------------------------------------------------------------------- - // TLS Page Offsets - // ------------------------------------------------------------------------- - - /// @brief stores the offset in the TLS block for rax - constexpr bsl::safe_uintmax TLS_OFFSET_RAX{bsl::to_umax(0x800U)}; - /// @brief stores the offset in the TLS block for rbx - constexpr bsl::safe_uintmax TLS_OFFSET_RBX{bsl::to_umax(0x808U)}; - /// @brief stores the offset in the TLS block for rcx - constexpr bsl::safe_uintmax TLS_OFFSET_RCX{bsl::to_umax(0x810U)}; - /// @brief stores the offset in the TLS block for rdx - constexpr bsl::safe_uintmax TLS_OFFSET_RDX{bsl::to_umax(0x818U)}; - /// @brief stores the offset in the TLS block for rbp - constexpr bsl::safe_uintmax TLS_OFFSET_RBP{bsl::to_umax(0x820U)}; - /// @brief stores the offset in the TLS block for rsi - constexpr bsl::safe_uintmax TLS_OFFSET_RSI{bsl::to_umax(0x828U)}; - /// @brief stores the offset in the TLS block for rdi - constexpr bsl::safe_uintmax TLS_OFFSET_RDI{bsl::to_umax(0x830U)}; - /// @brief stores the offset in the TLS block for r8 - constexpr bsl::safe_uintmax TLS_OFFSET_R8{bsl::to_umax(0x838U)}; - /// @brief stores the offset in the TLS block for r9 - constexpr bsl::safe_uintmax TLS_OFFSET_R9{bsl::to_umax(0x840U)}; - /// @brief stores the offset in the TLS block for r10 - constexpr bsl::safe_uintmax TLS_OFFSET_R10{bsl::to_umax(0x848U)}; - /// @brief stores the offset in the TLS block for r11 - constexpr bsl::safe_uintmax TLS_OFFSET_R11{bsl::to_umax(0x850U)}; - /// @brief stores the offset in the TLS block for r12 - constexpr bsl::safe_uintmax TLS_OFFSET_R12{bsl::to_umax(0x858U)}; - /// @brief stores the offset in the TLS block for r13 - constexpr bsl::safe_uintmax TLS_OFFSET_R13{bsl::to_umax(0x860U)}; - /// @brief stores the offset in the TLS block for r14 - constexpr bsl::safe_uintmax TLS_OFFSET_R14{bsl::to_umax(0x868U)}; - /// @brief stores the offset in the TLS block for r15 - constexpr bsl::safe_uintmax TLS_OFFSET_R15{bsl::to_umax(0x870U)}; - /// @brief stores the offset in the TLS block for the thread id - constexpr bsl::safe_uintmax TLS_OFFSET_THREAD_ID{bsl::to_umax(0xFF8U)}; - - // ------------------------------------------------------------------------- - // Exit Type - // ------------------------------------------------------------------------- - - /// @brief Defines the exit type used by bf_control_op_exit - // IWYU is more important here, and this rule would make this interface - // needlessly overcomplicated. - // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) - enum class bf_exit_status_t : bsl::uint64 - { - /// @brief Exit with a success code - success = static_cast(0), - /// @brief Exit with a failure code - failure = static_cast(1) - }; - - // ------------------------------------------------------------------------- - // Bootstrap Callback Handler Type - // ------------------------------------------------------------------------- - - /// @brief Defines the signature of the bootstrap callback handler - // Entry points cannot use safe integral types - // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) - using bf_callback_handler_bootstrap_t = void (*)(bsl::uint16); - - // ------------------------------------------------------------------------- - // VMExit Callback Handler Type - // ------------------------------------------------------------------------- - - /// @brief Defines the signature of the VM exit callback handler - // Entry points cannot use safe integral types - // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) - using bf_callback_handler_vmexit_t = void (*)(bsl::uint16, bsl::uint64); - - // ------------------------------------------------------------------------- - // Fast Fail Callback Handler Type - // ------------------------------------------------------------------------- - - /// @brief Defines the signature of the fast fail callback handler - // Entry points cannot use safe integral types - // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) - using bf_callback_handler_fail_t = void (*)(bf_status_t::value_type); - - // ------------------------------------------------------------------------- - // Prototypes - // ------------------------------------------------------------------------- - - /// - /// @brief Implements the ABI for bf_control_op_exit. - /// - extern "C" void bf_control_op_exit_impl() noexcept; - - /// - /// @brief Implements the ABI for bf_handle_op_open_handle. - /// - /// - /// @param reg0_in n/a - /// @param reg0_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_handle_op_open_handle_impl( // -- - bf_uint32_t const reg0_in, // -- - bf_uint64_t *const reg0_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_handle_op_close_handle. - /// - /// - /// @param reg0_in n/a - /// - extern "C" void bf_handle_op_close_handle_impl( // -- - bf_uint64_t const reg0_in) noexcept; - - /// - /// @brief Implements the ABI for bf_debug_op_out. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// - extern "C" void bf_debug_op_out_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint64_t const reg1_in) noexcept; - - /// - /// @brief Implements the ABI for bf_debug_op_dump_vm. - /// - /// - /// @param reg0_in n/a - /// - extern "C" void bf_debug_op_dump_vm_impl( // -- - bf_uint16_t const reg0_in) noexcept; - - /// - /// @brief Implements the ABI for bf_debug_op_dump_vp. - /// - /// - /// @param reg0_in n/a - /// - extern "C" void bf_debug_op_dump_vp_impl( // -- - bf_uint16_t const reg0_in) noexcept; - - /// - /// @brief Implements the ABI for bf_debug_op_dump_vps. - /// - /// - /// @param reg0_in n/a - /// - extern "C" void bf_debug_op_dump_vps_impl( // -- - bf_uint16_t const reg0_in) noexcept; - - /// - /// @brief Implements the ABI for bf_debug_op_dump_vmexit_log. - /// - /// - /// @param reg0_in n/a - /// - extern "C" void bf_debug_op_dump_vmexit_log_impl( // -- - bf_uint16_t const reg0_in) noexcept; - - /// - /// @brief Implements the ABI for bf_debug_op_write_c. - /// - /// - /// @param reg0_in n/a - /// - extern "C" void bf_debug_op_write_c_impl( // -- - bsl::char_type const reg0_in) noexcept; - - /// - /// @brief Implements the ABI for bf_debug_op_write_str. - /// - /// - /// @param reg0_in n/a - /// - extern "C" void bf_debug_op_write_str_impl( // -- - bsl::char_type const *const reg0_in) noexcept; - - /// - /// @brief Implements the ABI for bf_callback_op_wait. - /// - extern "C" void bf_callback_op_wait_impl() noexcept; - - /// - /// @brief Implements the ABI for bf_callback_op_register_bootstrap. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_callback_op_register_bootstrap_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_callback_handler_bootstrap_t const reg1_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_callback_op_register_vmexit. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_callback_op_register_vmexit_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_callback_handler_vmexit_t const reg1_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_callback_op_register_fail. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_callback_op_register_fail_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_callback_handler_fail_t const reg1_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vm_op_create_vm. - /// - /// - /// @param reg0_in n/a - /// @param reg0_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vm_op_create_vm_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t *const reg0_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vm_op_destroy_vm. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// - extern "C" void bf_vm_op_destroy_vm_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in) noexcept; - - /// - /// @brief Implements the ABI for bf_vp_op_create_vp. - /// - /// - /// @param reg0_in n/a - /// @param reg0_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vp_op_create_vp_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t *const reg0_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vp_op_destroy_vp. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// - extern "C" void bf_vp_op_destroy_vp_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in) noexcept; - - /// - /// @brief Implements the ABI for bf_vps_op_create_vps. - /// - /// - /// @param reg0_in n/a - /// @param reg0_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_create_vps_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t *const reg0_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_destroy_vps. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// - extern "C" void bf_vps_op_destroy_vps_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in) noexcept; - - /// - /// @brief Implements the ABI for bf_vps_op_init_as_root. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_init_as_root_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_read8. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @param reg0_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_read8_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in, // -- - bf_uint64_t const reg2_in, // -- - bf_uint8_t *const reg0_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_read16. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @param reg0_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_read16_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in, // -- - bf_uint64_t const reg2_in, // -- - bf_uint16_t *const reg0_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_read32. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @param reg0_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_read32_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in, // -- - bf_uint64_t const reg2_in, // -- - bf_uint32_t *const reg0_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_read64. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @param reg0_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_read64_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in, // -- - bf_uint64_t const reg2_in, // -- - bf_uint64_t *const reg0_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_write8. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @param reg3_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_write8_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in, // -- - bf_uint64_t const reg2_in, // -- - bf_uint8_t const reg3_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_write16. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @param reg3_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_write16_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in, // -- - bf_uint64_t const reg2_in, // -- - bf_uint16_t const reg3_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_write32. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @param reg3_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_write32_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in, // -- - bf_uint64_t const reg2_in, // -- - bf_uint32_t const reg3_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_write64. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @param reg3_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_write64_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in, // -- - bf_uint64_t const reg2_in, // -- - bf_uint64_t const reg3_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_read_reg_impl. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @param reg0_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_read_reg_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in, // -- - bf_reg_t const reg2_in, // -- - bf_uint64_t *const reg0_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_write_reg. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @param reg3_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_write_reg_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in, // -- - bf_reg_t const reg2_in, // -- - bf_uint64_t const reg3_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_run. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @param reg3_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_run_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in, // -- - bf_uint16_t const reg2_in, // -- - bf_uint16_t const reg3_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_run_current. - /// - /// - /// @param reg0_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_run_current_impl( // -- - bf_uint64_t const reg0_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_advance_ip. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_advance_ip_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_advance_ip_and_run_current. - /// - /// - /// @param reg0_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_vps_op_advance_ip_and_run_current_impl( // -- - bf_uint64_t const reg0_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_vps_op_promote. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// - extern "C" void bf_vps_op_promote_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint16_t const reg1_in) noexcept; - - /// - /// @brief Implements the ABI for bf_intrinsic_op_read_msr. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg0_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_intrinsic_op_read_msr_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint32_t const reg1_in, // -- - bf_uint64_t *const reg0_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_intrinsic_op_write_msr. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg2_in n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_intrinsic_op_write_msr_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_uint32_t const reg1_in, // -- - bf_uint64_t const reg2_in) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_mem_op_alloc_page. - /// - /// - /// @param reg0_in n/a - /// @param reg0_out n/a - /// @param reg1_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_mem_op_alloc_page_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_ptr_t *const reg0_out, - bf_uint64_t *const reg1_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_mem_op_virt_to_phys. - /// - /// - /// @param reg0_in n/a - /// @param reg1_in n/a - /// @param reg0_out n/a - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_mem_op_virt_to_phys_impl( // -- - bf_uint64_t const reg0_in, // -- - bf_ptr_t const reg1_in, // -- - bf_uint64_t *const reg0_out) noexcept -> bf_status_t::value_type; - - /// - /// @brief Implements the ABI for bf_tls_rax. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_rax_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_rax. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_rax_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_rbx. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_rbx_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_rbx. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_rbx_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_rcx. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_rcx_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_rcx. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_rcx_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_rdx. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_rdx_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_rdx. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_rdx_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_rbp. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_rbp_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_rbp. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_rbp_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_rsi. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_rsi_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_rsi. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_rsi_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_rdi. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_rdi_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_rdi. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_rdi_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_r8. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_r8_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_r8. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_r8_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_r9. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_r9_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_r9. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_r9_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_r10. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_r10_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_r10. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_r10_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_r11. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_r11_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_r11. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_r11_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_r12. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_r12_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_r12. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_r12_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_r13. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_r13_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_r13. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_r13_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_r14. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_r14_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_r14. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_r14_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_r15. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_r15_impl() noexcept -> bf_uint64_t; - - /// - /// @brief Implements the ABI for bf_tls_set_r15. - /// - /// - /// @param val n/a - /// - extern "C" void bf_tls_set_r15_impl(bf_uint64_t const val) noexcept; - - /// - /// @brief Implements the ABI for bf_tls_thread_id. - /// - /// - /// @return n/a - /// - extern "C" [[nodiscard]] auto bf_tls_thread_id_impl() noexcept -> bf_uint64_t; - - // ------------------------------------------------------------------------- - // TLS - // ------------------------------------------------------------------------- - - /// - /// @brief Returns the value of tls.rax - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.rax - /// - [[nodiscard]] inline auto - bf_tls_rax(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_rax_impl()}; - } - - /// - /// @brief Sets the value of tls.rax - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.rax to - /// - inline void - bf_tls_set_rax(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_rax_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.rbx - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.rbx - /// - [[nodiscard]] inline auto - bf_tls_rbx(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_rbx_impl()}; - } - - /// - /// @brief Sets the value of tls.rbx - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.rbx to - /// - inline void - bf_tls_set_rbx(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_rbx_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.rcx - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.rcx - /// - [[nodiscard]] inline auto - bf_tls_rcx(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_rcx_impl()}; - } - - /// - /// @brief Sets the value of tls.rcx - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.rcx to - /// - inline void - bf_tls_set_rcx(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_rcx_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.rdx - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.rdx - /// - [[nodiscard]] inline auto - bf_tls_rdx(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_rdx_impl()}; - } - - /// - /// @brief Sets the value of tls.rdx - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.rdx to - /// - inline void - bf_tls_set_rdx(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_rdx_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.rbp - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.rbp - /// - [[nodiscard]] inline auto - bf_tls_rbp(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_rbp_impl()}; - } - - /// - /// @brief Sets the value of tls.rbp - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.rbp to - /// - inline void - bf_tls_set_rbp(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_rbp_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.rsi - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.rsi - /// - [[nodiscard]] inline auto - bf_tls_rsi(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_rsi_impl()}; - } - - /// - /// @brief Sets the value of tls.rsi - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.rsi to - /// - inline void - bf_tls_set_rsi(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_rsi_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.rdi - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.rdi - /// - [[nodiscard]] inline auto - bf_tls_rdi(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_rdi_impl()}; - } - - /// - /// @brief Sets the value of tls.rdi - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.rdi to - /// - inline void - bf_tls_set_rdi(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_rdi_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.r8 - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.r8 - /// - [[nodiscard]] inline auto - bf_tls_r8(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_r8_impl()}; - } - - /// - /// @brief Sets the value of tls.r8 - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.r8 to - /// - inline void - bf_tls_set_r8(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_r8_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.r9 - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.r9 - /// - [[nodiscard]] inline auto - bf_tls_r9(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_r9_impl()}; - } - - /// - /// @brief Sets the value of tls.r9 - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.r9 to - /// - inline void - bf_tls_set_r9(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_r9_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.r10 - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.r10 - /// - [[nodiscard]] inline auto - bf_tls_r10(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_r10_impl()}; - } - - /// - /// @brief Sets the value of tls.r10 - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.r10 to - /// - inline void - bf_tls_set_r10(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_r10_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.r11 - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.r11 - /// - [[nodiscard]] inline auto - bf_tls_r11(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_r11_impl()}; - } - - /// - /// @brief Sets the value of tls.r11 - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.r11 to - /// - inline void - bf_tls_set_r11(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_r11_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.r12 - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.r12 - /// - [[nodiscard]] inline auto - bf_tls_r12(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_r12_impl()}; - } - - /// - /// @brief Sets the value of tls.r12 - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.r12 to - /// - inline void - bf_tls_set_r12(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_r12_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.r13 - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.r13 - /// - [[nodiscard]] inline auto - bf_tls_r13(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_r13_impl()}; - } - - /// - /// @brief Sets the value of tls.r13 - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.r13 to - /// - inline void - bf_tls_set_r13(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_r13_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.r14 - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.r14 - /// - [[nodiscard]] inline auto - bf_tls_r14(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_r14_impl()}; - } - - /// - /// @brief Sets the value of tls.r14 - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.r14 to - /// - inline void - bf_tls_set_r14(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_r14_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.r15 - /// - /// - /// @param handle reserved for uint testing - /// @return Returns the value of tls.r15 - /// - [[nodiscard]] inline auto - bf_tls_r15(bf_handle_t const &handle) noexcept -> bsl::safe_uintmax - { - bsl::discard(handle); - return {bf_tls_r15_impl()}; - } - - /// - /// @brief Sets the value of tls.r15 - /// - /// - /// @param handle reserved for uint testing - /// @param val The value to set tls.r15 to - /// - inline void - bf_tls_set_r15(bf_handle_t const &handle, bsl::safe_uintmax const &val) noexcept - { - bsl::discard(handle); - bf_tls_set_r15_impl(val.get()); - } - - /// - /// @brief Returns the value of tls.thread_id - /// - /// - /// @return Returns the value of tls.thread_id - /// - [[nodiscard]] inline auto - bf_tls_thread_id() noexcept -> bsl::safe_uintmax - { - return {bf_tls_thread_id_impl()}; - } - - // ------------------------------------------------------------------------- - // Syscall Status Codes - // ------------------------------------------------------------------------- - - /// @brief Defines a mask for BF_STATUS_SIG - constexpr bf_status_t BF_STATUS_SIG_MASK{bsl::to_u64(0xFFFF000000000000U)}; - /// @brief Defines a mask for BF_STATUS_FLAGS - constexpr bf_status_t BF_STATUS_FLAGS_MASK{bsl::to_u64(0x0000FFFFFFFF0000U)}; - /// @brief Defines a mask for BF_STATUS_VALUE - constexpr bf_status_t BF_STATUS_VALUE_MASK{bsl::to_u64(0x000000000000FFFFU)}; - - /// - /// @brief n/a - /// - /// - /// @param status n/a - /// @return n/a - /// - [[nodiscard]] inline auto - bf_status_sig(bf_status_t const &status) noexcept -> bf_status_t - { - return status & BF_STATUS_SIG_MASK; - } - - /// - /// @brief n/a - /// - /// - /// @param status n/a - /// @return n/a - /// - [[nodiscard]] inline auto - bf_status_flags(bf_status_t const &status) noexcept -> bf_status_t - { - return status & BF_STATUS_FLAGS_MASK; - } - - /// - /// @brief n/a - /// - /// - /// @param status n/a - /// @return n/a - /// - [[nodiscard]] inline auto - bf_status_value(bf_status_t const &status) noexcept -> bf_status_t - { - return status & BF_STATUS_VALUE_MASK; - } - - /// @brief Used to indicated that the syscall returned successfully - constexpr bf_status_t BF_STATUS_SUCCESS{bsl::to_u64(0x0000000000000000U)}; - /// @brief Indicates an unknown error occurred - constexpr bf_status_t BF_STATUS_FAILURE_UNKNOWN{bsl::to_u64(0xDEAD000000010001U)}; - /// @brief Indicates the syscall is unsupported - constexpr bf_status_t BF_STATUS_FAILURE_INVALID_HANDLE{bsl::to_u64(0xDEAD000000020001U)}; - /// @brief Indicates the provided handle is invalid - constexpr bf_status_t BF_STATUS_FAILURE_UNSUPPORTED{bsl::to_u64(0xDEAD000000040001U)}; - /// @brief Indicates the extension is not allowed to execute this syscall - constexpr bf_status_t BF_STATUS_INVALID_PERM_EXT{bsl::to_u64(0xDEAD000000010002U)}; - /// @brief Indicates the policy engine denied the syscall - constexpr bf_status_t BF_STATUS_INVALID_PERM_DENIED{bsl::to_u64(0xDEAD000000020002U)}; - /// @brief Indicates param 0 is invalid - constexpr bf_status_t BF_STATUS_INVALID_PARAMS0{bsl::to_u64(0xDEAD000000010003U)}; - /// @brief Indicates param 1 is invalid - constexpr bf_status_t BF_STATUS_INVALID_PARAMS1{bsl::to_u64(0xDEAD000000020003U)}; - /// @brief Indicates param 2 is invalid - constexpr bf_status_t BF_STATUS_INVALID_PARAMS2{bsl::to_u64(0xDEAD000000040003U)}; - /// @brief Indicates param 3 is invalid - constexpr bf_status_t BF_STATUS_INVALID_PARAMS3{bsl::to_u64(0xDEAD000000080003U)}; - /// @brief Indicates param 4 is invalid - constexpr bf_status_t BF_STATUS_INVALID_PARAMS4{bsl::to_u64(0xDEAD000000100003U)}; - /// @brief Indicates param 5 is invalid - constexpr bf_status_t BF_STATUS_INVALID_PARAMS5{bsl::to_u64(0xDEAD000000200003U)}; - - // ------------------------------------------------------------------------- - // Syscall Inputs - // ------------------------------------------------------------------------- - - /// @brief Defines the BF_SYSCALL_SIG field for RAX - constexpr bsl::safe_uint64 BF_HYPERCALL_SIG_VAL{bsl::to_u64(0x6642000000000000U)}; - /// @brief Defines a mask for BF_SYSCALL_SIG - constexpr bsl::safe_uint64 BF_HYPERCALL_SIG_MASK{bsl::to_u64(0xFFFF000000000000U)}; - /// @brief Defines a mask for BF_SYSCALL_FLAGS - constexpr bsl::safe_uint64 BF_HYPERCALL_FLAGS_MASK{bsl::to_u64(0x0000FFFF00000000U)}; - /// @brief Defines a mask for BF_SYSCALL_OP - constexpr bsl::safe_uint64 BF_HYPERCALL_OPCODE_MASK{bsl::to_u64(0xFFFF0000FFFF0000U)}; - /// @brief Defines a mask for BF_SYSCALL_OP (with no signature added) - constexpr bsl::safe_uint64 BF_HYPERCALL_OPCODE_NOSIG_MASK{bsl::to_u64(0x00000000FFFF0000U)}; - /// @brief Defines a mask for BF_SYSCALL_IDX - constexpr bsl::safe_uint64 BF_HYPERCALL_INDEX_MASK{bsl::to_u64(0x000000000000FFFFU)}; - - /// - /// @brief n/a - /// - /// - /// @param rax n/a - /// @return n/a - /// - [[nodiscard]] constexpr auto - bf_syscall_sig(bsl::safe_uint64 const &rax) noexcept -> bsl::safe_uint64 - { - return rax & BF_HYPERCALL_SIG_MASK; - } - - /// - /// @brief n/a - /// - /// - /// @param rax n/a - /// @return n/a - /// - [[nodiscard]] constexpr auto - bf_syscall_flags(bsl::safe_uint64 const &rax) noexcept -> bsl::safe_uint64 - { - return rax & BF_HYPERCALL_FLAGS_MASK; - } - - /// - /// @brief n/a - /// - /// - /// @param rax n/a - /// @return n/a - /// - [[nodiscard]] constexpr auto - bf_syscall_opcode(bsl::safe_uint64 const &rax) noexcept -> bsl::safe_uint64 - { - return rax & BF_HYPERCALL_OPCODE_MASK; - } - - /// - /// @brief n/a - /// - /// - /// @param rax n/a - /// @return n/a - /// - [[nodiscard]] constexpr auto - bf_syscall_opcode_nosig(bsl::safe_uint64 const &rax) noexcept -> bsl::safe_uint64 - { - return rax & BF_HYPERCALL_OPCODE_NOSIG_MASK; - } - - /// - /// @brief n/a - /// - /// - /// @param rax n/a - /// @return n/a - /// - [[nodiscard]] constexpr auto - bf_syscall_index(bsl::safe_uint64 const &rax) noexcept -> bsl::safe_uint64 - { - return rax & BF_HYPERCALL_INDEX_MASK; - } - - // ------------------------------------------------------------------------- - // Specification IDs - // ------------------------------------------------------------------------- - - /// @brief Defines the ID for version #1 of this spec - constexpr bsl::safe_uint32 BF_SPEC_ID1_VAL{bsl::to_u32(0x31236642)}; - - /// @brief Defines the mask for checking support for version #1 of this spec - constexpr bsl::safe_uint32 BF_SPEC_ID1_MASK{bsl::to_u32(0x2)}; - - /// @brief Defines the value likely returned by bf_handle_op_version - constexpr bsl::safe_uint32 BF_ALL_SPECS_SUPPORTED_VAL{bsl::to_u32(0x2)}; - - // ------------------------------------------------------------------------- - // Syscall Opcodes - Control Support - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall opcode for bf_control_op - constexpr bsl::safe_uint64 BF_CONTROL_OP_VAL{bsl::to_u64(0x6642000000000000U)}; - /// @brief Defines the syscall opcode for bf_control_op (nosig) - constexpr bsl::safe_uint64 BF_CONTROL_OP_NOSIG_VAL{bsl::to_u64(0x0000000000000000U)}; - - // ------------------------------------------------------------------------- - // Syscall Opcodes - Handle Support - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall opcode for bf_handle_op - constexpr bsl::safe_uint64 BF_HANDLE_OP_VAL{bsl::to_u64(0x6642000000010000U)}; - /// @brief Defines the syscall opcode for bf_handle_op (nosig) - constexpr bsl::safe_uint64 BF_HANDLE_OP_NOSIG_VAL{bsl::to_u64(0x0000000000010000U)}; - - // ------------------------------------------------------------------------- - // Syscall Opcodes - Debug Support - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall opcode for bf_debug_op - constexpr bsl::safe_uint64 BF_DEBUG_OP_VAL{bsl::to_u64(0x6642000000020000U)}; - /// @brief Defines the syscall opcode for bf_debug_op (nosig) - constexpr bsl::safe_uint64 BF_DEBUG_OP_NOSIG_VAL{bsl::to_u64(0x00000000000020000U)}; - - // ------------------------------------------------------------------------- - // Syscall Opcodes - Callback Support - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall opcode for bf_callback_op - constexpr bsl::safe_uint64 BF_CALLBACK_OP_VAL{bsl::to_u64(0x6642000000030000U)}; - /// @brief Defines the syscall opcode for bf_callback_op (nosig) - constexpr bsl::safe_uint64 BF_CALLBACK_OP_NOSIG_VAL{bsl::to_u64(0x0000000000030000U)}; - - // ------------------------------------------------------------------------- - // Syscall Opcodes - VM Support - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall opcode for bf_vm_op - constexpr bsl::safe_uint64 BF_VM_OP_VAL{bsl::to_u64(0x6642000000040000U)}; - /// @brief Defines the syscall opcode for bf_vm_op (nosig) - constexpr bsl::safe_uint64 BF_VM_OP_NOSIG_VAL{bsl::to_u64(0x0000000000040000U)}; - - // ------------------------------------------------------------------------- - // Syscall Opcodes - VP Support - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall opcode for bf_vp_op - constexpr bsl::safe_uint64 BF_VP_OP_VAL{bsl::to_u64(0x6642000000050000U)}; - /// @brief Defines the syscall opcode for bf_vp_op (nosig) - constexpr bsl::safe_uint64 BF_VP_OP_NOSIG_VAL{bsl::to_u64(0x0000000000050000U)}; - - // ------------------------------------------------------------------------- - // Syscall Opcodes - VPS Support - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall opcode for bf_vps_op - constexpr bsl::safe_uint64 BF_VPS_OP_VAL{bsl::to_u64(0x6642000000060000U)}; - /// @brief Defines the syscall opcode for bf_vps_op (nosig) - constexpr bsl::safe_uint64 BF_VPS_OP_NOSIG_VAL{bsl::to_u64(0x0000000000060000U)}; - - // ------------------------------------------------------------------------- - // Syscall Opcodes - Intrinsic Support - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall opcode for bf_intrinsic_op - constexpr bsl::safe_uint64 BF_INTRINSIC_OP_VAL{bsl::to_u64(0x6642000000070000U)}; - /// @brief Defines the syscall opcode for bf_intrinsic_op (nosig) - constexpr bsl::safe_uint64 BF_INTRINSIC_OP_NOSIG_VAL{bsl::to_u64(0x0000000000070000U)}; - - // ------------------------------------------------------------------------- - // Syscall Opcodes - Mem Support - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall opcode for bf_mem_op - constexpr bsl::safe_uint64 BF_MEM_OP_VAL{bsl::to_u64(0x6642000000080000U)}; - /// @brief Defines the syscall opcode for bf_mem_op (nosig) - constexpr bsl::safe_uint64 BF_MEM_OP_NOSIG_VAL{bsl::to_u64(0x0000000000080000U)}; - - // ------------------------------------------------------------------------- - // bf_control_op_exit - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_control_op_exit - constexpr bsl::safe_uint64 BF_CONTROL_OP_EXIT_IDX_VAL{bsl::to_u64(0x0000000000000000U)}; - - /// - /// @brief This syscall tells the microkernel to exit the execution - /// of an extension, providing a means to fast fail. - /// - inline void - bf_control_op_exit() noexcept - { - bf_control_op_exit_impl(); - } - - // ------------------------------------------------------------------------- - // bf_handle_op_open_handle - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_handle_op_open_handle - constexpr bsl::safe_uint64 BF_HANDLE_OP_OPEN_HANDLE_IDX_VAL{bsl::to_u64(0x0000000000000000U)}; - - /// - /// @brief This syscall returns a handle which is required to execute - /// the remaining syscalls. Some versions of Bareflank might provide - /// a certain degree of backwards compatibility which can be queried - /// using bf_handle_op_version. The version argument of this syscall - /// provides software with means to tell the microkernel which version - /// of this spec it is trying to use. If software provides a version - /// that Bareflank doesn't support (i.e., a version that is not listed - /// by bf_handle_op_version), this syscall will fail. - /// - /// - /// @param version The version of this spec that software supports - /// @param handle The value to set REG0 to for most other syscalls - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_handle_op_open_handle( // -- - bsl::safe_uint32 const &version, // -- - bf_handle_t &handle) noexcept -> bf_status_t - { - return {bf_handle_op_open_handle_impl(version.get(), &handle.hndl)}; - } - - // ------------------------------------------------------------------------- - // bf_handle_op_close_handle - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_handle_op_close_handle - constexpr bsl::safe_uint64 BF_HANDLE_OP_CLOSE_HANDLE_IDX_VAL{bsl::to_u64(0x0000000000000001U)}; - - /// - /// @brief This syscall closes a previously opened handle. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// - inline void - bf_handle_op_close_handle( // -- - bf_handle_t &handle) noexcept - { - bf_handle_op_close_handle_impl(handle.hndl); - handle = {}; - } - - // ------------------------------------------------------------------------- - // bf_is_spec1_supported - // ------------------------------------------------------------------------- - - /// - /// @brief n/a - /// - /// - /// @param version n/a - /// @return n/a - /// - [[nodiscard]] constexpr auto - bf_is_spec1_supported(bsl::safe_uint32 const &version) noexcept -> bool - { - return ((version & BF_SPEC_ID1_MASK) != bsl::ZERO_U32); - } - - // ------------------------------------------------------------------------- - // bf_debug_op_out - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_debug_op_out - constexpr bsl::safe_uint64 BF_DEBUG_OP_OUT_IDX_VAL{bsl::to_u64(0x0000000000000000U)}; - - /// - /// @brief This syscall tells the microkernel to output RDI and RSI to - /// the console device the microkernel is currently using for - /// debugging. The purpose of this syscall is to provide a simple - /// means for debugging issues with the extension and can be used - /// even when the extension is not fully bootstrapped or is in a - /// failure state. Also note that this syscall is designed to execute - /// as quickly as possible (although it is still constrained by the - /// speed at which it can dump debug text to the console). - /// - /// - /// @param val1 The first value to output to the microkernel's console - /// @param val2 The second value to output to the microkernel's console - /// - inline void - bf_debug_op_out( // -- - bsl::safe_uint64 const &val1, // -- - bsl::safe_uint64 const &val2) noexcept - { - bf_debug_op_out_impl(val1.get(), val2.get()); - } - - // ------------------------------------------------------------------------- - // bf_debug_op_dump_vm - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_debug_op_dump_vm - constexpr bsl::safe_uint64 BF_DEBUG_OP_DUMP_VM_IDX_VAL{bsl::to_u64(0x0000000000000001U)}; - - /// - /// @brief This syscall tells the microkernel to output the state of a - /// VM to the console device the microkernel is currently using for - /// debugging. The report that is generated is implementation defined, - /// and in some cases could take a while to complete. In other words, - /// this syscall should only be used when debugging, and only in - /// scenarios where you can afford the time needed to output a lot of - /// VM state to the microkernel's console. - /// - /// - /// @param vmid The VMID of the VM whose state is to be outputted - /// - inline void - bf_debug_op_dump_vm( // -- - bsl::safe_uint16 const &vmid) noexcept - { - bf_debug_op_dump_vm_impl(vmid.get()); - } - - // ------------------------------------------------------------------------- - // bf_debug_op_dump_vp - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_debug_op_dump_vp - constexpr bsl::safe_uint64 BF_DEBUG_OP_DUMP_VP_IDX_VAL{bsl::to_u64(0x0000000000000002U)}; - - /// - /// @brief This syscall tells the microkernel to output the state of a - /// VP to the console device the microkernel is currently using for - /// debugging. The report that is generated is implementation defined, - /// and in some cases could take a while to complete. In other words, - /// this syscall should only be used when debugging, and only in - /// scenarios where you can afford the time needed to output a lot of - /// VP state to the microkernel's console. - /// - /// - /// @param vpid The VPID of the VP whose state is to be outputted - /// - inline void - bf_debug_op_dump_vp( // -- - bsl::safe_uint16 const &vpid) noexcept - { - bf_debug_op_dump_vp_impl(vpid.get()); - } - - // ------------------------------------------------------------------------- - // bf_debug_op_dump_vps - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_debug_op_dump_vps - constexpr bsl::safe_uint64 BF_DEBUG_OP_DUMP_VPS_IDX_VAL{bsl::to_u64(0x0000000000000003U)}; - - /// - /// @brief This syscall tells the microkernel to output the state of a - /// VPS to the console device the microkernel is currently using for - /// debugging. The report that is generated is implementation defined, - /// and in some cases could take a while to complete. In other words, - /// this syscall should only be used when debugging, and only in - /// scenarios where you can afford the time needed to output a lot of - /// VPS state to the microkernel's console. - /// - /// - /// @param vpsid The VPSID of the VPS whose state is to be outputted - /// - inline void - bf_debug_op_dump_vps( // -- - bsl::safe_uint16 const &vpsid) noexcept - { - bf_debug_op_dump_vps_impl(vpsid.get()); - } - - // ------------------------------------------------------------------------- - // bf_debug_op_dump_vmexit_log - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_debug_op_dump_vmexit_log - constexpr bsl::safe_uint64 BF_DEBUG_OP_DUMP_VMEXIT_LOG_IDX_VAL{ - bsl::to_u64(0x0000000000000004U)}; - - /// - /// @brief This syscall tells the microkernel to output the vmexit log. - /// The vmexit log is a chronological log of the "X" number of exits - /// that have occurred from the time the call to - /// bf_debug_op_dump_vmexit_log is made. The total number of "X" logs - /// is implementation defined and not under the control of software - /// (i.e., this value is usually compiled into Bareflank cannot be - /// changed at runtime). In addition, the format of this log is also - /// implementation defined. If the microkernel has to kill a VP for - /// VM for any reason it will output this log by default for debugging - /// purposes, but sometimes, software is aware of odd condition, or is - /// even aware that something bad has happened, and this syscall - /// provides software with an opportunity to dump this log on demand. - /// - /// - /// @param vpid The VPID of the VP to dump the log from - /// - inline void - bf_debug_op_dump_vmexit_log( // -- - bsl::safe_uint16 const &vpid) noexcept - { - bf_debug_op_dump_vmexit_log_impl(vpid.get()); - } - - // ------------------------------------------------------------------------- - // bf_debug_op_write_c - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_debug_op_write_c - constexpr bsl::safe_uint64 BF_DEBUG_OP_WRITE_C_IDX_VAL{bsl::to_u64(0x0000000000000005U)}; - - /// - /// @brief This syscall tells the microkernel to output a provided - /// character to the microkernel's console. - /// - /// - /// @param c The character to output - /// - inline void - bf_debug_op_write_c( // -- - bsl::char_type const c) noexcept - { - bf_debug_op_write_c_impl(c); - } - - // ------------------------------------------------------------------------- - // bf_debug_op_write_str - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_debug_op_write_str - constexpr bsl::safe_uint64 BF_DEBUG_OP_WRITE_STR_IDX_VAL{bsl::to_u64(0x0000000000000006U)}; - - /// - /// @brief This syscall tells the microkernel to output a provided - /// string to the microkernel's console. - /// - /// - /// @param str The virtual address of a null terminated string to output - /// - inline void - bf_debug_op_write_str( // -- - bsl::cstr_type const str) noexcept - { - bf_debug_op_write_str_impl(str); - } - - // ------------------------------------------------------------------------- - // bf_callback_op_wait - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_callback_op_wait - constexpr bsl::safe_uint64 BF_CALLBACK_OP_WAIT_IDX_VAL{bsl::to_u64(0x0000000000000000U)}; - - /// - /// @brief This syscall tells the microkernel that the extension would - /// like to wait for a callback. This is a blocking syscall that never - /// returns and should be used to return from the successful execution - /// of the _start function. - /// - inline void - bf_callback_op_wait() noexcept - { - bf_callback_op_wait_impl(); - } - - // ------------------------------------------------------------------------- - // bf_callback_op_register_bootstrap - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_callback_op_register_bootstrap - constexpr bsl::safe_uint64 BF_CALLBACK_OP_REGISTER_BOOTSTRAP_IDX_VAL{ - bsl::to_u64(0x0000000000000002U)}; - - /// - /// @brief This syscall tells the microkernel that the extension would - /// like to receive callbacks for bootstrap events - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param handler Set to the virtual address of the callback - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_callback_op_register_bootstrap( // -- - bf_handle_t const &handle, // -- - bf_callback_handler_bootstrap_t const handler) noexcept -> bf_status_t - { - return {bf_callback_op_register_bootstrap_impl(handle.hndl, handler)}; - } - - // ------------------------------------------------------------------------- - // bf_callback_op_register_vmexit - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_callback_op_register_vmexit - constexpr bsl::safe_uint64 BF_CALLBACK_OP_REGISTER_VMEXIT_IDX_VAL{ - bsl::to_u64(0x0000000000000003U)}; - - /// - /// @brief This syscall tells the microkernel that the extension would - /// like to receive callbacks for VM exits - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param handler Set to the virtual address of the callback - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_callback_op_register_vmexit( // -- - bf_handle_t const &handle, // -- - bf_callback_handler_vmexit_t const handler) noexcept -> bf_status_t - { - return {bf_callback_op_register_vmexit_impl(handle.hndl, handler)}; - } - - // ------------------------------------------------------------------------- - // bf_callback_op_register_fail - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_callback_op_register_fail - constexpr bsl::safe_uint64 BF_CALLBACK_OP_REGISTER_FAIL_IDX_VAL{ - bsl::to_u64(0x0000000000000004U)}; - - /// - /// @brief This syscall tells the microkernel that the extension would - /// like to receive callbacks for fast fail events. If a fast fail - /// event occurs, something really bad has happened, and action must - /// be taken, or the physical processor will halt. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param handler Set to the virtual address of the callback - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_callback_op_register_fail( // -- - bf_handle_t const &handle, // -- - bf_callback_handler_fail_t const handler) noexcept -> bf_status_t - { - return {bf_callback_op_register_fail_impl(handle.hndl, handler)}; - } - - // ------------------------------------------------------------------------- - // bf_vm_op_create_vm - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vm_op_create_vm - constexpr bsl::safe_uint64 BF_VM_OP_CREATE_VM_IDX_VAL{bsl::to_u64(0x0000000000000000U)}; - - /// - /// @brief This syscall tells the microkernel to create a VM - /// and return it's ID. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vmid The resulting VMID of the newly created VM - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vm_op_create_vm( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 &vmid) noexcept -> bf_status_t - { - return {bf_vm_op_create_vm_impl(handle.hndl, vmid.data())}; - } - - // ------------------------------------------------------------------------- - // bf_vm_op_destroy_vm - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vm_op_destroy_vm - constexpr bsl::safe_uint64 BF_VM_OP_DESTROY_VM_IDX_VAL{bsl::to_u64(0x0000000000000001U)}; - - /// - /// @brief This syscall tells the microkernel to destroy a VM - /// given an ID. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vmid The VMID of the VM to destroy - /// - inline void - bf_vm_op_destroy_vm( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vmid) noexcept - { - bf_vm_op_destroy_vm_impl(handle.hndl, vmid.get()); - } - - // ------------------------------------------------------------------------- - // bf_vp_op_create_vp - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vp_op_create_vp - constexpr bsl::safe_uint64 BF_VP_OP_CREATE_VP_IDX_VAL{bsl::to_u64(0x0000000000000000U)}; - - /// - /// @brief This syscall tells the microkernel to create a VP - /// and return it's ID. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpid The resulting VPID of the newly created VP - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vp_op_create_vp( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 &vpid) noexcept -> bf_status_t - { - return {bf_vp_op_create_vp_impl(handle.hndl, vpid.data())}; - } - - // ------------------------------------------------------------------------- - // bf_vp_op_destroy_vp - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vp_op_destroy_vp - constexpr bsl::safe_uint64 BF_VP_OP_DESTROY_VP_IDX_VAL{bsl::to_u64(0x0000000000000001U)}; - - /// - /// @brief This syscall tells the microkernel to destroy a VP - /// given an ID. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpid The VPID of the VP to destroy - /// - inline void - bf_vp_op_destroy_vp( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpid) noexcept - { - bf_vp_op_destroy_vp_impl(handle.hndl, vpid.get()); - } - - // ------------------------------------------------------------------------- - // bf_vps_op_create_vps - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_create_vps - constexpr bsl::safe_uint64 BF_VPS_OP_CREATE_VPS_IDX_VAL{bsl::to_u64(0x0000000000000000U)}; - - /// - /// @brief This syscall tells the microkernel to create a VPS - /// and return it's ID. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The resulting VPSID of the newly created VPS - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_create_vps( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 &vpsid) noexcept -> bf_status_t - { - return {bf_vps_op_create_vps_impl(handle.hndl, vpsid.data())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_destroy_vps - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_destroy_vps - constexpr bsl::safe_uint64 BF_VPS_OP_DESTROY_VPS_IDX_VAL{bsl::to_u64(0x0000000000000001U)}; - - /// - /// @brief This syscall tells the microkernel to destroy a VPS - /// given an ID. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to destroy - /// - inline void - bf_vps_op_destroy_vps( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid) noexcept - { - bf_vps_op_destroy_vps_impl(handle.hndl, vpsid.get()); - } - - // ------------------------------------------------------------------------- - // bf_vps_op_init_as_root - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_init_as_root - constexpr bsl::safe_uint64 BF_VPS_OP_INIT_AS_ROOT_IDX_VAL{bsl::to_u64(0x0000000000000002U)}; - - /// - /// @brief This syscall tells the microkernel to initialize a VPS using - /// the root VP state that was provided by the loader given the VPSID - /// to initialize as well as the PPID of the physical processor to - /// get the root VP state from. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to initialize - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_init_as_root( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid) noexcept -> bf_status_t - { - return {bf_vps_op_init_as_root_impl(handle.hndl, vpsid.get())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_read8 - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_read8 - constexpr bsl::safe_uint64 BF_VPS_OP_READ8_IDX_VAL{bsl::to_u64(0x0000000000000003U)}; - - /// - /// @brief Reads an 8bit field from the VPS. The "index" is architecture - /// specific. For Intel, the index (or encoding) is the defined in - /// Appendix B "Field Encoding in VMCS". For AMD, the index (or offset) - /// is defined in Appendix B "Layout of VMCB". - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to read from - /// @param index The HVE specific index defining which field to read - /// @param value The resulting value - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_read8( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid, // -- - bsl::safe_uint64 const &index, // -- - bsl::safe_uint8 &value) noexcept -> bf_status_t - { - return {bf_vps_op_read8_impl(handle.hndl, vpsid.get(), index.get(), value.data())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_read16 - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_read16 - constexpr bsl::safe_uint64 BF_VPS_OP_READ16_IDX_VAL{bsl::to_u64(0x0000000000000004U)}; - - /// - /// @brief Reads a 16bit field from the VPS. The "index" is architecture - /// specific. For Intel, the index (or encoding) is the defined in - /// Appendix B "Field Encoding in VMCS". For AMD, the index (or offset) - /// is defined in Appendix B "Layout of VMCB". - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to read from - /// @param index The HVE specific index defining which field to read - /// @param value The resulting value - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_read16( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid, // -- - bsl::safe_uint64 const &index, // -- - bsl::safe_uint16 &value) noexcept -> bf_status_t - { - return {bf_vps_op_read16_impl(handle.hndl, vpsid.get(), index.get(), value.data())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_read32 - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_read32 - constexpr bsl::safe_uint64 BF_VPS_OP_READ32_IDX_VAL{bsl::to_u64(0x0000000000000005U)}; - - /// - /// @brief Reads a 32bit field from the VPS. The "index" is architecture - /// specific. For Intel, the index (or encoding) is the defined in - /// Appendix B "Field Encoding in VMCS". For AMD, the index (or offset) - /// is defined in Appendix B "Layout of VMCB". - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to read from - /// @param index The HVE specific index defining which field to read - /// @param value The resulting value - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_read32( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid, // -- - bsl::safe_uint64 const &index, // -- - bsl::safe_uint32 &value) noexcept -> bf_status_t - { - return {bf_vps_op_read32_impl(handle.hndl, vpsid.get(), index.get(), value.data())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_read64 - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_read64 - constexpr bsl::safe_uint64 BF_VPS_OP_READ64_IDX_VAL{bsl::to_u64(0x0000000000000006U)}; - - /// - /// @brief Reads an 64bit field from the VPS. The "index" is architecture - /// specific. For Intel, the index (or encoding) is the defined in - /// Appendix B "Field Encoding in VMCS". For AMD, the index (or offset) - /// is defined in Appendix B "Layout of VMCB". - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to read from - /// @param index The HVE specific index defining which field to read - /// @param value The resulting value - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_read64( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid, // -- - bsl::safe_uint64 const &index, // -- - bsl::safe_uint64 &value) noexcept -> bf_status_t - { - return {bf_vps_op_read64_impl(handle.hndl, vpsid.get(), index.get(), value.data())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_write8 - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_write - constexpr bsl::safe_uint64 BF_VPS_OP_WRITE8_IDX_VAL{bsl::to_u64(0x0000000000000007U)}; - - /// - /// @brief Writes to an 8bit field in the VPS. The "index" is architecture - /// specific. For Intel, the index (or encoding) is the defined in - /// Appendix B "Field Encoding in VMCS". For AMD, the index (or offset) - /// is defined in Appendix B "Layout of VMCB". - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to write to - /// @param index The HVE specific index defining which field to write to - /// @param value The value to write to the requested field - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_write8( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid, // -- - bsl::safe_uint64 const &index, // -- - bsl::safe_uint8 const &value) noexcept -> bf_status_t - { - return {bf_vps_op_write8_impl(handle.hndl, vpsid.get(), index.get(), value.get())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_write16 - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_write - constexpr bsl::safe_uint64 BF_VPS_OP_WRITE16_IDX_VAL{bsl::to_u64(0x0000000000000008U)}; - - /// - /// @brief Writes to a 16bit field in the VPS. The "index" is architecture - /// specific. For Intel, the index (or encoding) is the defined in - /// Appendix B "Field Encoding in VMCS". For AMD, the index (or offset) - /// is defined in Appendix B "Layout of VMCB". - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to write to - /// @param index The HVE specific index defining which field to write to - /// @param value The value to write to the requested field - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_write16( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid, // -- - bsl::safe_uint64 const &index, // -- - bsl::safe_uint16 const &value) noexcept -> bf_status_t - { - return {bf_vps_op_write16_impl(handle.hndl, vpsid.get(), index.get(), value.get())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_write32 - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_write - constexpr bsl::safe_uint64 BF_VPS_OP_WRITE32_IDX_VAL{bsl::to_u64(0x0000000000000009U)}; - - /// - /// @brief Writes to a 32bit field in the VPS. The "index" is architecture - /// specific. For Intel, the index (or encoding) is the defined in - /// Appendix B "Field Encoding in VMCS". For AMD, the index (or offset) - /// is defined in Appendix B "Layout of VMCB". - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to write to - /// @param index The HVE specific index defining which field to write to - /// @param value The value to write to the requested field - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_write32( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid, // -- - bsl::safe_uint64 const &index, // -- - bsl::safe_uint32 const &value) noexcept -> bf_status_t - { - return {bf_vps_op_write32_impl(handle.hndl, vpsid.get(), index.get(), value.get())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_write64 - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_write - constexpr bsl::safe_uint64 BF_VPS_OP_WRITE64_IDX_VAL{bsl::to_u64(0x000000000000000AU)}; - - /// - /// @brief Writes to a 64bit field in the VPS. The "index" is architecture - /// specific. For Intel, the index (or encoding) is the defined in - /// Appendix B "Field Encoding in VMCS". For AMD, the index (or offset) - /// is defined in Appendix B "Layout of VMCB". - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to write to - /// @param index The HVE specific index defining which field to write to - /// @param value The value to write to the requested field - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_write64( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid, // -- - bsl::safe_uint64 const &index, // -- - bsl::safe_uint64 const &value) noexcept -> bf_status_t - { - return {bf_vps_op_write64_impl(handle.hndl, vpsid.get(), index.get(), value.get())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_read_reg - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_read_reg - constexpr bsl::safe_uint64 BF_VPS_OP_READ_REG_IDX_VAL{bsl::to_u64(0x000000000000000BU)}; - - /// - /// @brief Reads a CPU register from the VPS given a bf_reg_t. Note - /// that the bf_reg_t is architecture specific. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to read from - /// @param reg A bf_reg_t defining which register to read - /// @param value The resulting value - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_read_reg( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid, // -- - bf_reg_t const reg, // -- - bsl::safe_uint64 &value) noexcept -> bf_status_t - { - return {bf_vps_op_read_reg_impl(handle.hndl, vpsid.get(), reg, value.data())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_write_reg - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_write_reg - constexpr bsl::safe_uint64 BF_VPS_OP_WRITE_REG_IDX_VAL{bsl::to_u64(0x000000000000000CU)}; - - /// - /// @brief Writes to a CPU register in the VPS given a bf_reg_t and the - /// value to write. Note that the bf_reg_t is architecture specific. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to write to - /// @param reg A bf_reg_t defining which register to write to - /// @param value The value to write to the requested register - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_write_reg( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid, // -- - bf_reg_t const reg, // -- - bsl::safe_uint64 const &value) noexcept -> bf_status_t - { - return {bf_vps_op_write_reg_impl(handle.hndl, vpsid.get(), reg, value.get())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_run - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_run - constexpr bsl::safe_uint64 BF_VPS_OP_RUN_IDX_VAL{bsl::to_u64(0x000000000000000DU)}; - - /// - /// @brief This syscall tells the microkernel to run a VP on behalf - /// of a given VM by executing the VP with a given VPS. This system - /// call only returns if an error occurs. On success, this system - /// call will physically execute the requested VP using the requested - /// VPS, and the extension will only execute again on the next VMExit. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to run - /// @param vpid The VPID of the VP to run - /// @param vmid The VMID of the VM to run - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_run( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid, // -- - bsl::safe_uint16 const &vpid, // -- - bsl::safe_uint16 const &vmid) noexcept -> bf_status_t - { - return {bf_vps_op_run_impl(handle.hndl, vpsid.get(), vpid.get(), vmid.get())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_run_current - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_run_current - constexpr bsl::safe_uint64 BF_VPS_OP_RUN_CURRENT_IDX_VAL{bsl::to_u64(0x000000000000000EU)}; - - /// - /// @brief bf_vps_op_run_current tells the microkernel to execute the - /// currently active VPS, VP and VM. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_run_current( // -- - bf_handle_t const &handle) noexcept -> bf_status_t - { - return {bf_vps_op_run_current_impl(handle.hndl)}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_advance_ip - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_advance_ip - constexpr bsl::safe_uint64 BF_VPS_OP_ADVANCE_IP_IDX_VAL{bsl::to_u64(0x000000000000000FU)}; - - /// - /// @brief This syscall tells the microkernel to advance the instruction - /// pointer in the requested VPS. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS advance the IP in - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_advance_ip( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid) noexcept -> bf_status_t - { - return {bf_vps_op_advance_ip_impl(handle.hndl, vpsid.get())}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_advance_ip_and_run_current - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_advance_ip_and_run_current - constexpr bsl::safe_uint64 BF_VPS_OP_ADVANCE_IP_AND_RUN_CURRENT_IDX_VAL{ - bsl::to_u64(0x0000000000000010U)}; - - /// - /// @brief This syscall tells the microkernel to advance the instruction - /// pointer in the requested VPS and run the currently active VPS, VP - /// and VM (i.e., this combines bf_vps_op_advance_ip and - /// bf_vps_op_advance_ip). - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_vps_op_advance_ip_and_run_current( // -- - bf_handle_t const &handle) noexcept -> bf_status_t - { - return {bf_vps_op_advance_ip_and_run_current_impl(handle.hndl)}; - } - - // ------------------------------------------------------------------------- - // bf_vps_op_promote - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_vps_op_promote - constexpr bsl::safe_uint64 BF_VPS_OP_PROMOTE_IDX_VAL{bsl::to_u64(0x0000000000000011U)}; - - /// - /// @brief This syscall tells the microkernel to promote the requested - /// VPS. This will stop the hypervisor complete on the physical - /// processor that this syscall is executed on and replace it's state - /// with the state in the VPS. Note that this syscall only returns - /// on error. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param vpsid The VPSID of the VPS to promote - /// - inline void - bf_vps_op_promote( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint16 const &vpsid) noexcept - { - bf_vps_op_promote_impl(handle.hndl, vpsid.get()); - } - - // ------------------------------------------------------------------------- - // bf_intrinsic_op_read_msr - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_intrinsic_op_read_msr - constexpr bsl::safe_uint64 BF_INTRINSIC_OP_READ_MSR_IDX_VAL{bsl::to_u64(0x0000000000000000U)}; - - /// - /// @brief Reads an MSR directly from the CPU given the address of - /// the MSR to read. Note that this is specific to Intel/AMD only. - /// Also note that not all MSRs can be read, and which MSRs that - /// can be read is up to the microkernel's internal policy as well - /// as which architecture the hypervisor is running on. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param msr The address of the MSR to read - /// @param value The resulting value - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_intrinsic_op_read_msr( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint32 const &msr, // -- - bsl::safe_uint64 &value) noexcept -> bf_status_t - { - return {bf_intrinsic_op_read_msr_impl(handle.hndl, msr.get(), value.data())}; - } - - // ------------------------------------------------------------------------- - // bf_intrinsic_op_write_msr - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_intrinsic_op_write_msr - constexpr bsl::safe_uint64 BF_INTRINSIC_OP_WRITE_MSR_IDX_VAL{bsl::to_u64(0x0000000000000001U)}; - - /// - /// @brief Writes to an MSR directly from the CPU given the address of - /// the MSR to write as well as the value to write. Note that this is - /// specific to Intel/AMD only. Also note that not all MSRs can be - /// written to, and which MSRs that can be written to is up to the - /// microkernel's internal policy as well as which architecture the - /// hypervisor is running on. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param msr The address of the MSR to write to - /// @param value The value to write to the requested MSR - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_intrinsic_op_write_msr( // -- - bf_handle_t const &handle, // -- - bsl::safe_uint32 const &msr, // -- - bsl::safe_uint64 const &value) noexcept -> bf_status_t - { - return {bf_intrinsic_op_write_msr_impl(handle.hndl, msr.get(), value.get())}; - } - - // ------------------------------------------------------------------------- - // bf_mem_op_alloc_page - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_mem_op_alloc_page - constexpr bsl::safe_uint64 BF_MEM_OP_ALLOC_PAGE_IDX_VAL{bsl::to_u64(0x0000000000000000U)}; - - /// - /// @brief Allocates a page. When a page is allocated, it is removed - /// from the micorkernel's direct map, and placed into the extension's - /// direct map. This ensures the extension is free to use an allocated - /// page to store secrets, and extensions can also convert the virtual - /// address of the page to a physical page and back without issue. - /// Note that not all memory allocations (e.g., the heap) work this - /// way. Extensions should use caution when storing secrets. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param virt The virtual address of the resulting page - /// @param phys The physical address of the resulting page - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_mem_op_alloc_page( // -- - bf_handle_t const &handle, // -- - bf_ptr_t &virt, // -- - bsl::safe_uint64 &phys) noexcept -> bf_status_t - { - return {bf_mem_op_alloc_page_impl(handle.hndl, &virt, phys.data())}; - } - - // ------------------------------------------------------------------------- - // bf_mem_op_virt_to_phys - // ------------------------------------------------------------------------- - - /// @brief Defines the syscall index for bf_mem_op_virt_to_phys - constexpr bsl::safe_uint64 BF_MEM_OP_VIRT_TO_PHYS_IDX_VAL{bsl::to_u64(0x0000000000000006U)}; - - /// - /// @brief bf_mem_op_virt_to_phys converts a provided virtual address - /// to a physical address for any virtual address allocated using - /// bf_mem_op_alloc_page, bf_mem_op_alloc_huge, bf_mem_op_alloc_heap - /// or mapped using the direct map. - /// - /// - /// @param handle Set to the result of bf_handle_op_open_handle - /// @param virt The virtual address of the page to convert - /// @param phys The physical address of the provided virtual address - /// @return Returns the bf_status_t result of the syscall. See the - /// specification for more information about error codes. - /// - [[nodiscard]] inline auto - bf_mem_op_virt_to_phys( // -- - bf_handle_t const &handle, // -- - bf_ptr_t const virt, // -- - bsl::safe_uint64 &phys) noexcept -> bf_status_t - { - return {bf_mem_op_virt_to_phys_impl(handle.hndl, virt, phys.data())}; - } -} - -#endif diff --git a/syscall/mk_lib.cmake b/syscall/mk_lib.cmake new file mode 100644 index 00000000..6fdfb28e --- /dev/null +++ b/syscall/mk_lib.cmake @@ -0,0 +1,45 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +add_library(syscall INTERFACE) + +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + +target_include_directories(syscall INTERFACE + include/cpp +) + +# ------------------------------------------------------------------------------ +# Libraries +# ------------------------------------------------------------------------------ + +target_link_libraries(syscall INTERFACE + bsl + hypervisor +) + +# ------------------------------------------------------------------------------ +# Install +# ------------------------------------------------------------------------------ + +install(TARGETS syscall DESTINATION lib) diff --git a/syscall/mocks/cpp/bf_control_ops.hpp b/syscall/mocks/cpp/bf_control_ops.hpp new file mode 100644 index 00000000..a0b2cbd5 --- /dev/null +++ b/syscall/mocks/cpp/bf_control_ops.hpp @@ -0,0 +1,65 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef BF_CONTROL_OPS_HPP +#define BF_CONTROL_OPS_HPP + +#include + +#include + +namespace syscall +{ + /// + /// @brief This syscall tells the microkernel to exit the execution + /// of an extension, providing a means to fast fail. + /// + constexpr void + bf_control_op_exit() noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_control_op_exit_impl(); + } + + /// + /// @brief This syscall tells the microkernel that the extension would + /// like to wait for a callback. This is a blocking syscall that never + /// returns and should be used to return from the successful execution + /// of the _start function. + /// + constexpr void + bf_control_op_wait() noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_control_op_wait_impl(); + } +} + +#endif diff --git a/syscall/mocks/cpp/bf_debug_ops.hpp b/syscall/mocks/cpp/bf_debug_ops.hpp new file mode 100644 index 00000000..a8eeac14 --- /dev/null +++ b/syscall/mocks/cpp/bf_debug_ops.hpp @@ -0,0 +1,211 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef BF_DEBUG_OPS_HPP +#define BF_DEBUG_OPS_HPP + +#include +#include + +#include +#include +#include + +namespace syscall +{ + /// + /// @brief This syscall tells the microkernel to output RDI and RSI to + /// the console device the microkernel is currently using for + /// debugging. + /// + /// + /// @param val1 The first value to output to the microkernel's console + /// @param val2 The second value to output to the microkernel's console + /// + constexpr void + bf_debug_op_out(bf_uint64_t const &val1, bf_uint64_t const &val2) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_out_impl(val1.get(), val2.get()); + } + + /// + /// @brief This syscall tells the microkernel to output the state of a + /// VM to the console device the microkernel is currently using for + /// debugging. + /// + /// + /// @param vmid The VMID of the VM whose state is to be outputted + /// + constexpr void + bf_debug_op_dump_vm(bf_uint16_t const &vmid) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_vm_impl(vmid.get()); + } + + /// + /// @brief This syscall tells the microkernel to output the state of a + /// VP to the console device the microkernel is currently using for + /// debugging. + /// + /// + /// @param vpid The VPID of the VP whose state is to be outputted + /// + constexpr void + bf_debug_op_dump_vp(bf_uint16_t const &vpid) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_vp_impl(vpid.get()); + } + + /// + /// @brief This syscall tells the microkernel to output the state of a + /// VPS to the console device the microkernel is currently using for + /// debugging. + /// + /// + /// @param vpsid The VPSID of the VPS whose state is to be outputted + /// + constexpr void + bf_debug_op_dump_vps(bf_uint16_t const &vpsid) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_vps_impl(vpsid.get()); + } + + /// + /// @brief This syscall tells the microkernel to output the VMExit log. + /// The VMExit log is a chronological log of the "X" number of exits + /// that have occurred on a specific physical processor. + /// + /// + /// @param ppid The PPID of the PP to dump the log from + /// + constexpr void + bf_debug_op_dump_vmexit_log(bf_uint16_t const &ppid) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_vmexit_log_impl(ppid.get()); + } + + /// + /// @brief This syscall tells the microkernel to output a provided + /// character to the microkernel's console. + /// + /// + /// @param c The character to output + /// + constexpr void + bf_debug_op_write_c(bsl::char_type const c) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_write_c_impl(c); + } + + /// + /// @brief This syscall tells the microkernel to output a provided + /// string to the microkernel's console. + /// + /// + /// @param str The virtual address of a null terminated string to output + /// + constexpr void + bf_debug_op_write_str(bsl::cstr_type const str) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_write_str_impl(str); + } + + /// + /// @brief This syscall tells the microkernel to output an extension's + /// state to the console device the microkernel is currently using + /// for debugging. + /// + /// + /// @param extid The EXTID of the extensions's state to output + /// + constexpr void + bf_debug_op_dump_ext(bf_uint16_t const &extid) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_ext_impl(extid.get()); + } + + /// + /// @brief This syscall tells the microkernel to output the page pool's + /// stats to the console device the microkernel is currently using + /// for debugging. + /// + constexpr void + bf_debug_op_dump_page_pool() noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_page_pool_impl(); + } + + /// + /// @brief This syscall tells the microkernel to output the huge pool's + /// stats to the console device the microkernel is currently using + /// for debugging. + /// + constexpr void + bf_debug_op_dump_huge_pool() noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_huge_pool_impl(); + } +} + +#endif diff --git a/syscall/mocks/cpp/bf_syscall_impl.hpp b/syscall/mocks/cpp/bf_syscall_impl.hpp new file mode 100644 index 00000000..e7eb67f6 --- /dev/null +++ b/syscall/mocks/cpp/bf_syscall_impl.hpp @@ -0,0 +1,1788 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_BF_SYSCALL_IMPL_HPP +#define MOCKS_BF_SYSCALL_IMPL_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#pragma clang diagnostic ignored "-Wglobal-constructors" +#pragma clang diagnostic ignored "-Wexit-time-destructors" + +namespace syscall +{ + /// NOTE: + /// - In general, this set of mocked "impl" APIs should not be used + /// directly. Most of these APIs should be used through the bf_syscall_t + /// wrapper, and the mocked version of that wrapper should be used + /// instead as it was far more capable. + /// - There are some APIs in this library that provide some facilities. + /// These specifically include the control ops and the debug ops. + /// The syscall library provides these ops outside of the bf_syscall_t + /// so that they can be used by an extension on their own. + /// - The control ops APIs should only be used in a single unit test + /// designed to ensure the main.cpp (or whatever file the entry points + /// are located in) are tested as this is the only file that should + /// contain these control ops. + /// - The debug ops should only be used by whatever runtime library is + /// used. This runtime library will provide the logic for how to + /// handle the platform BSL functions. All other extension logic can + /// simply use the BSL as it is, as the BSL already provides platform + /// support for Windows and Linux which is what the unit tests will + /// run on, meaning these libraries are only needed to support unit + /// testing of the code that implements the syscall version of the + /// BSL platform logic. + /// + + // ------------------------------------------------------------------------- + // global variables used by the impl mocks + // ------------------------------------------------------------------------- + + /// @brief stores the data to return for an API + constinit inline bsl::unordered_map g_data{}; // GRCOV_EXCLUDE_BR + /// @brief stores the error code to return for an API + constinit inline bsl::unordered_map g_errc{}; // GRCOV_EXCLUDE_BR + + /// @brief stores whether or not bf_control_op_exit_impl was executed + constinit inline bool g_bf_control_op_exit_impl_executed{}; + /// @brief stores whether or not bf_control_op_wait_impl was executed + constinit inline bool g_bf_control_op_wait_impl_executed{}; + + /// @brief stores whether or not bf_debug_op_out_impl was executed + constinit inline bool g_bf_debug_op_out_impl_executed{}; + /// @brief stores whether or not bf_debug_op_dump_vm_impl was executed + constinit inline bool g_bf_debug_op_dump_vm_impl_executed{}; + /// @brief stores whether or not bf_debug_op_dump_vp_impl was executed + constinit inline bool g_bf_debug_op_dump_vp_impl_executed{}; + /// @brief stores whether or not bf_debug_op_dump_vps_impl was executed + constinit inline bool g_bf_debug_op_dump_vps_impl_executed{}; + /// @brief stores whether or not bf_debug_op_dump_vmexit_log_impl was executed + constinit inline bool g_bf_debug_op_dump_vmexit_log_impl_executed{}; + /// @brief stores whether or not bf_debug_op_write_c_impl was executed + constinit inline bool g_bf_debug_op_write_c_impl_executed{}; + /// @brief stores whether or not bf_debug_op_write_str_impl was executed + constinit inline bool g_bf_debug_op_write_str_impl_executed{}; + /// @brief stores whether or not bf_debug_op_dump_ext_impl was executed + constinit inline bool g_bf_debug_op_dump_ext_impl_executed{}; + /// @brief stores whether or not bf_debug_op_dump_page_pool_impl was executed + constinit inline bool g_bf_debug_op_dump_page_pool_impl_executed{}; + /// @brief stores whether or not bf_debug_op_dump_huge_pool_impl was executed + constinit inline bool g_bf_debug_op_dump_huge_pool_impl_executed{}; + + // ------------------------------------------------------------------------- + // dummy callbacks + // ------------------------------------------------------------------------- + + /// + /// @brief Implements a dummy bootstrap entry function. + /// + /// + /// @param ppid the physical process to bootstrap + /// + extern "C" inline void + dummy_bootstrap_entry(syscall::bf_uint16_t::value_type const ppid) noexcept + { + bsl::discard(ppid); + } + + /// + /// @brief Implements a dummy VMExit entry function. + /// + /// + /// @param vpsid the ID of the VPS that generated the VMExit + /// @param exit_reason the exit reason associated with the VMExit + /// + extern "C" inline void + dummy_vmexit_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_uint64_t::value_type const exit_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(exit_reason); + } + + /// + /// @brief Implements a dummy fast fail entry function. + /// + /// + /// @param vpsid the ID of the VPS that generated the fail + /// @param fail_reason the exit reason associated with the fail + /// + extern "C" inline void + dummy_fail_entry( + syscall::bf_uint16_t::value_type const vpsid, + syscall::bf_status_t::value_type const fail_reason) noexcept + { + bsl::discard(vpsid); + bsl::discard(fail_reason); + } + + // ------------------------------------------------------------------------- + // TLS ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_tls_rax. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_rax_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_rax").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_rax. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_rax_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_rax") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_rbx. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_rbx_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_rbx").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_rbx. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_rbx_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_rbx") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_rcx. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_rcx_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_rcx").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_rcx. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_rcx_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_rcx") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_rdx. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_rdx_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_rdx").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_rdx. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_rdx_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_rdx") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_rbp. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_rbp_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_rbp").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_rbp. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_rbp_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_rbp") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_rsi. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_rsi_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_rsi").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_rsi. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_rsi_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_rsi") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_rdi. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_rdi_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_rdi").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_rdi. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_rdi_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_rdi") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_r8. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_r8_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_r8").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_r8. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_r8_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_r8") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_r9. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_r9_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_r9").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_r9. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_r9_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_r9") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_r10. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_r10_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_r10").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_r10. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_r10_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_r10") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_r11. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_r11_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_r11").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_r11. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_r11_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_r11") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_r12. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_r12_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_r12").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_r12. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_r12_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_r12") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_r13. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_r13_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_r13").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_r13. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_r13_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_r13") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_r14. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_r14_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_r14").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_r14. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_r14_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_r14") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_r15. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_r15_impl() noexcept -> bf_uint64_t::value_type + { + return g_data.at("bf_tls_r15").get(); + } + + /// + /// @brief Implements the ABI for bf_tls_set_r15. + /// + /// + /// @param val n/a + /// + extern "C" inline void + bf_tls_set_r15_impl(bf_uint64_t::value_type const val) noexcept + { + g_data.at("bf_tls_r15") = val; + } + + /// + /// @brief Implements the ABI for bf_tls_extid. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_extid_impl() noexcept -> bf_uint16_t::value_type + { + return bsl::to_u16(g_data.at("bf_tls_extid")).get(); + } + + /// + /// @brief Implements the ABI for bf_tls_vmid. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_vmid_impl() noexcept -> bf_uint16_t::value_type + { + return bsl::to_u16(g_data.at("bf_tls_vmid")).get(); + } + + /// + /// @brief Implements the ABI for bf_tls_vpid. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_vpid_impl() noexcept -> bf_uint16_t::value_type + { + return bsl::to_u16(g_data.at("bf_tls_vpid")).get(); + } + + /// + /// @brief Implements the ABI for bf_tls_vpsid. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_vpsid_impl() noexcept -> bf_uint16_t::value_type + { + return bsl::to_u16(g_data.at("bf_tls_vpsid")).get(); + } + + /// + /// @brief Implements the ABI for bf_tls_ppid. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_ppid_impl() noexcept -> bf_uint16_t::value_type + { + return bsl::to_u16(g_data.at("bf_tls_ppid")).get(); + } + + /// + /// @brief Implements the ABI for bf_tls_online_pps. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_tls_online_pps_impl() noexcept -> bf_uint16_t::value_type + { + return bsl::to_u16(g_data.at("bf_tls_online_pps")).get(); + } + + // ------------------------------------------------------------------------- + // bf_control_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_control_op_exit. + /// + extern "C" inline void + bf_control_op_exit_impl() noexcept + { + g_bf_control_op_exit_impl_executed = true; + } + + /// + /// @brief Implements the ABI for bf_control_op_wait. + /// + extern "C" inline void + bf_control_op_wait_impl() noexcept + { + g_bf_control_op_wait_impl_executed = true; + } + + // ------------------------------------------------------------------------- + // bf_handle_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_handle_op_open_handle. + /// + /// + /// @param reg0_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_handle_op_open_handle_impl( + bf_uint32_t::value_type const reg0_in, bf_uint64_t::value_type *const reg0_out) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_handle_op_open_handle_impl") == BF_STATUS_SUCCESS) { + *reg0_out = g_data.at("bf_handle_op_open_handle_impl_reg0_out").get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_handle_op_open_handle_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_handle_op_close_handle. + /// + /// + /// @param reg0_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_handle_op_close_handle_impl(bf_uint64_t::value_type const reg0_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + return g_errc.at("bf_handle_op_close_handle_impl").get(); + } + + // ------------------------------------------------------------------------- + // bf_debug_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_debug_op_out. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// + extern "C" inline void + bf_debug_op_out_impl( + bf_uint64_t::value_type const reg0_in, bf_uint64_t::value_type const reg1_in) noexcept + { + g_bf_debug_op_out_impl_executed = true; + // NOLINTNEXTLINE(bsl-function-name-use) + std::cout << std::hex << "0x" << reg0_in << " 0x" << reg1_in << '\n'; + } + + /// + /// @brief Implements the ABI for bf_debug_op_dump_vm. + /// + /// + /// @param reg0_in n/a + /// + extern "C" inline void + bf_debug_op_dump_vm_impl(bf_uint16_t::value_type const reg0_in) noexcept + { + g_bf_debug_op_dump_vm_impl_executed = true; + // NOLINTNEXTLINE(bsl-function-name-use) + std::cout << std::hex << "vm [0x" << reg0_in << "] dump: mock empty\n"; + } + + /// + /// @brief Implements the ABI for bf_debug_op_dump_vp. + /// + /// + /// @param reg0_in n/a + /// + extern "C" inline void + bf_debug_op_dump_vp_impl(bf_uint16_t::value_type const reg0_in) noexcept + { + g_bf_debug_op_dump_vp_impl_executed = true; + // NOLINTNEXTLINE(bsl-function-name-use) + std::cout << std::hex << "vp [0x" << reg0_in << "] dump: mock empty\n"; + } + + /// + /// @brief Implements the ABI for bf_debug_op_dump_vps. + /// + /// + /// @param reg0_in n/a + /// + extern "C" inline void + bf_debug_op_dump_vps_impl(bf_uint16_t::value_type const reg0_in) noexcept + { + g_bf_debug_op_dump_vps_impl_executed = true; + // NOLINTNEXTLINE(bsl-function-name-use) + std::cout << std::hex << "vps [0x" << reg0_in << "] dump: mock empty\n"; + } + + /// + /// @brief Implements the ABI for bf_debug_op_dump_vmexit_log. + /// + /// + /// @param reg0_in n/a + /// + extern "C" inline void + bf_debug_op_dump_vmexit_log_impl(bf_uint16_t::value_type const reg0_in) noexcept + { + g_bf_debug_op_dump_vmexit_log_impl_executed = true; + // NOLINTNEXTLINE(bsl-function-name-use) + std::cout << std::hex << "vmexit log for pp [0x" << reg0_in << "]: mock empty\n"; + } + + /// + /// @brief Implements the ABI for bf_debug_op_write_c. + /// + /// + /// @param reg0_in n/a + /// + extern "C" inline void + bf_debug_op_write_c_impl(bsl::char_type const reg0_in) noexcept + { + g_bf_debug_op_write_c_impl_executed = true; + std::cout << reg0_in; + } + + /// + /// @brief Implements the ABI for bf_debug_op_write_str. + /// + /// + /// @param reg0_in n/a + /// + extern "C" inline void + bf_debug_op_write_str_impl(bsl::char_type const *const reg0_in) noexcept + { + g_bf_debug_op_write_str_impl_executed = true; + std::cout << reg0_in; + } + + /// + /// @brief Implements the ABI for bf_debug_op_dump_ext. + /// + /// + /// @param reg0_in n/a + /// + extern "C" inline void + bf_debug_op_dump_ext_impl(bf_uint16_t::value_type const reg0_in) noexcept + { + g_bf_debug_op_dump_ext_impl_executed = true; + // NOLINTNEXTLINE(bsl-function-name-use) + std::cout << std::hex << "ext [0x" << reg0_in << "] dump: mock empty\n"; + } + + /// + /// @brief Implements the ABI for bf_debug_op_dump_page_pool. + /// + extern "C" inline void + bf_debug_op_dump_page_pool_impl() noexcept + { + g_bf_debug_op_dump_page_pool_impl_executed = true; + std::cout << "page pool dump: mock empty\n"; + } + + /// + /// @brief Implements the ABI for bf_debug_op_dump_huge_pool. + /// + extern "C" inline void + bf_debug_op_dump_huge_pool_impl() noexcept + { + g_bf_debug_op_dump_huge_pool_impl_executed = true; + std::cout << "huge pool dump: mock empty\n"; + } + + // ------------------------------------------------------------------------- + // bf_callback_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_callback_op_register_bootstrap. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_callback_op_register_bootstrap_impl( + bf_uint64_t::value_type const reg0_in, + bf_callback_handler_bootstrap_t const reg1_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_callback_op_register_bootstrap_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_callback_op_register_vmexit. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_callback_op_register_vmexit_impl( + bf_uint64_t::value_type const reg0_in, bf_callback_handler_vmexit_t const reg1_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_callback_op_register_vmexit_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_callback_op_register_fail. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_callback_op_register_fail_impl( + bf_uint64_t::value_type const reg0_in, bf_callback_handler_fail_t const reg1_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_callback_op_register_fail_impl").get(); + } + + // ------------------------------------------------------------------------- + // bf_vm_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_vm_op_create_vm. + /// + /// + /// @param reg0_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vm_op_create_vm_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type *const reg0_out) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_vm_op_create_vm_impl") == BF_STATUS_SUCCESS) { + *reg0_out = bsl::to_u16(g_data.at("bf_vm_op_create_vm_impl_reg0_out")).get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vm_op_create_vm_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vm_op_destroy_vm. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vm_op_destroy_vm_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_vm_op_destroy_vm_impl").get(); + } + + // ------------------------------------------------------------------------- + // bf_vp_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_vp_op_create_vp. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vp_op_create_vp_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint16_t::value_type const reg2_in, + bf_uint16_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_vp_op_create_vp_impl") == BF_STATUS_SUCCESS) { + *reg0_out = bsl::to_u16(g_data.at("bf_vp_op_create_vp_impl_reg0_out")).get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vp_op_create_vp_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vp_op_destroy_vp. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vp_op_destroy_vp_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_vp_op_destroy_vp_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vp_op_migrate. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vp_op_migrate_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint16_t::value_type const reg2_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + return g_errc.at("bf_vp_op_migrate_impl").get(); + } + + // ------------------------------------------------------------------------- + // bf_vps_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_vps_op_create_vps. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_create_vps_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint16_t::value_type const reg2_in, + bf_uint16_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_vps_op_create_vps_impl") == BF_STATUS_SUCCESS) { + *reg0_out = bsl::to_u16(g_data.at("bf_vps_op_create_vps_impl_reg0_out")).get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vps_op_create_vps_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_destroy_vps. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_destroy_vps_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_vps_op_destroy_vps_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_init_as_root. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_init_as_root_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_vps_op_init_as_root_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_read8. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_read8_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint8_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_vps_op_read8_impl") == BF_STATUS_SUCCESS) { + *reg0_out = bsl::to_u8(g_data.at("bf_vps_op_read8_impl_reg0_out")).get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vps_op_read8_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_read16. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_read16_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint16_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_vps_op_read16_impl") == BF_STATUS_SUCCESS) { + *reg0_out = bsl::to_u16(g_data.at("bf_vps_op_read16_impl_reg0_out")).get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vps_op_read16_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_read32. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_read32_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint32_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_vps_op_read32_impl") == BF_STATUS_SUCCESS) { + *reg0_out = bsl::to_u32(g_data.at("bf_vps_op_read32_impl_reg0_out")).get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vps_op_read32_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_read64. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_read64_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint64_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_vps_op_read64_impl") == BF_STATUS_SUCCESS) { + *reg0_out = bsl::to_u64(g_data.at("bf_vps_op_read64_impl_reg0_out")).get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vps_op_read64_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_write8. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_write8_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint8_t::value_type const reg3_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (g_errc.at("bf_vps_op_write8_impl") == BF_STATUS_SUCCESS) { + g_data.at("bf_vps_op_write8_impl") = bsl::to_u64(reg3_in); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vps_op_write8_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_write16. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_write16_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint16_t::value_type const reg3_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (g_errc.at("bf_vps_op_write16_impl") == BF_STATUS_SUCCESS) { + g_data.at("bf_vps_op_write16_impl") = bsl::to_u64(reg3_in); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vps_op_write16_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_write32. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_write32_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint32_t::value_type const reg3_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (g_errc.at("bf_vps_op_write32_impl") == BF_STATUS_SUCCESS) { + g_data.at("bf_vps_op_write32_impl") = bsl::to_u64(reg3_in); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vps_op_write32_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_write64. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_write64_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint64_t::value_type const reg3_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (g_errc.at("bf_vps_op_write64_impl") == BF_STATUS_SUCCESS) { + g_data.at("bf_vps_op_write64_impl") = bsl::to_u64(reg3_in); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vps_op_write64_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_read_reg_impl. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_read_reg_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_reg_t const reg2_in, + bf_uint64_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_vps_op_read_reg_impl") == BF_STATUS_SUCCESS) { + *reg0_out = g_data.at("bf_vps_op_read_reg_impl_reg0_out").get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vps_op_read_reg_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_write_reg. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_write_reg_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_reg_t const reg2_in, + bf_uint64_t::value_type const reg3_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + if (g_errc.at("bf_vps_op_write_reg_impl") == BF_STATUS_SUCCESS) { + g_data.at("bf_vps_op_write_reg_impl") = bsl::to_u64(reg3_in); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_vps_op_write_reg_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_run. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_run_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint16_t::value_type const reg2_in, + bf_uint16_t::value_type const reg3_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + bsl::discard(reg3_in); + + return g_errc.at("bf_vps_op_run_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_run_current. + /// + /// + /// @param reg0_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_run_current_impl(bf_uint64_t::value_type const reg0_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + return g_errc.at("bf_vps_op_run_current_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_advance_ip. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_advance_ip_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_vps_op_advance_ip_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_advance_ip_and_run_current. + /// + /// + /// @param reg0_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_advance_ip_and_run_current_impl(bf_uint64_t::value_type const reg0_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + return g_errc.at("bf_vps_op_advance_ip_and_run_current_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_promote. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_promote_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_vps_op_promote_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_vps_op_clear_vps. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_vps_op_clear_vps_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_vps_op_clear_vps_impl").get(); + } + + // ------------------------------------------------------------------------- + // bf_intrinsic_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_intrinsic_op_rdmsr. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_intrinsic_op_rdmsr_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint32_t::value_type const reg1_in, + bf_uint64_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_intrinsic_op_rdmsr_impl") == BF_STATUS_SUCCESS) { + *reg0_out = g_data.at("bf_intrinsic_op_rdmsr_impl_reg0_out").get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_intrinsic_op_rdmsr_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_intrinsic_op_wrmsr. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_intrinsic_op_wrmsr_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint32_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + if (g_errc.at("bf_intrinsic_op_wrmsr_impl") == BF_STATUS_SUCCESS) { + g_data.at("bf_intrinsic_op_wrmsr_impl") = bsl::to_u64(reg2_in); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_intrinsic_op_wrmsr_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_intrinsic_op_invlpga. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_intrinsic_op_invlpga_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint64_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + return g_errc.at("bf_intrinsic_op_invlpga_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_intrinsic_op_invept. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_intrinsic_op_invept_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint64_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + + return g_errc.at("bf_intrinsic_op_invept_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_intrinsic_op_invvpid. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_intrinsic_op_invvpid_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint64_t::value_type const reg1_in, + bf_uint16_t::value_type const reg2_in, + bf_uint64_t::value_type const reg3_in) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + bsl::discard(reg2_in); + bsl::discard(reg3_in); + + return g_errc.at("bf_intrinsic_op_invvpid_impl").get(); + } + + // ------------------------------------------------------------------------- + // bf_mem_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_mem_op_alloc_page. + /// + /// + /// @param reg0_in n/a + /// @param reg0_out n/a + /// @param reg1_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_mem_op_alloc_page_impl( + bf_uint64_t::value_type const reg0_in, + void **const reg0_out, + bf_uint64_t::value_type *const reg1_out) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (bsl::unlikely(nullptr == reg1_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_mem_op_alloc_page_impl") == BF_STATUS_SUCCESS) { + *reg0_out = bsl::to_ptr(g_data.at("bf_mem_op_alloc_page_impl_reg0_out")); + *reg1_out = g_data.at("bf_mem_op_alloc_page_impl_reg1_out").get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_mem_op_alloc_page_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_mem_op_free_page. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_mem_op_free_page_impl(bf_uint64_t::value_type const reg0_in, void *const reg1_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_mem_op_free_page_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_mem_op_alloc_huge. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg0_out n/a + /// @param reg1_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_mem_op_alloc_huge_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint64_t::value_type const reg1_in, + void **const reg0_out, + bf_uint64_t::value_type *const reg1_out) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (bsl::unlikely(nullptr == reg1_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_mem_op_alloc_huge_impl") == BF_STATUS_SUCCESS) { + *reg0_out = bsl::to_ptr(g_data.at("bf_mem_op_alloc_huge_impl_reg0_out")); + *reg1_out = g_data.at("bf_mem_op_alloc_huge_impl_reg1_out").get(); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_mem_op_alloc_huge_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_mem_op_free_huge. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_mem_op_free_huge_impl(bf_uint64_t::value_type const reg0_in, void *const reg1_in) noexcept + -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + return g_errc.at("bf_mem_op_free_huge_impl").get(); + } + + /// + /// @brief Implements the ABI for bf_mem_op_alloc_heap. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] inline auto + bf_mem_op_alloc_heap_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint64_t::value_type const reg1_in, + void **const reg0_out) noexcept -> bf_status_t::value_type + { + bsl::discard(reg0_in); + bsl::discard(reg1_in); + + if (bsl::unlikely(nullptr == reg0_out)) { + return BF_STATUS_FAILURE_UNKNOWN.get(); + } + + if (g_errc.at("bf_mem_op_alloc_heap_impl") == BF_STATUS_SUCCESS) { + *reg0_out = bsl::to_ptr(g_data.at("bf_mem_op_alloc_heap_impl_reg0_out")); + } + else { + bsl::touch(); + } + + return g_errc.at("bf_mem_op_alloc_heap_impl").get(); + } +} + +#endif diff --git a/syscall/mocks/cpp/bf_syscall_t.hpp b/syscall/mocks/cpp/bf_syscall_t.hpp new file mode 100644 index 00000000..545b6d8f --- /dev/null +++ b/syscall/mocks/cpp/bf_syscall_t.hpp @@ -0,0 +1,2686 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef MOCKS_BF_SYSCALL_T_HPP +#define MOCKS_BF_SYSCALL_T_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace syscall +{ + /// @class syscall::bf_syscall_t + /// + /// + /// @brief Provides an API wrapper around all of the microkernel ABIs. + /// For more information about these APIs, please see the Microkernel + /// ABI Specification. + /// + /// + class bf_syscall_t final + { + // clang-format off + + /// @brief stores the results for initialize + bsl::errc_type m_initialize; + + /// @brief stores TLS data + bsl::unordered_map m_tls; + + /// @brief stores the results for bf_vm_op_create_vm + bf_uint16_t m_bf_vm_op_create_vm; + /// @brief stores the results for bf_vm_op_destroy_vm + bsl::unordered_map m_bf_vm_op_destroy_vm; + /// @brief stores the results for bf_vp_op_create_vp + bsl::unordered_map, bf_uint16_t> m_bf_vp_op_create_vp; + /// @brief stores the results for bf_vp_op_destroy_vp + bsl::unordered_map m_bf_vp_op_destroy_vp; + /// @brief stores the results for bf_vp_op_migrate + bsl::unordered_map, bsl::errc_type> m_bf_vp_op_migrate; + /// @brief stores the results for bf_vps_op_create_vps + bsl::unordered_map, bf_uint16_t> m_bf_vps_op_create_vps; + /// @brief stores the results for bf_vps_op_destroy_vps + bsl::unordered_map m_bf_vps_op_destroy_vps; + /// @brief stores the results for bf_vps_op_init_as_root + bsl::unordered_map m_bf_vps_op_init_as_root; + /// @brief stores the results for bf_vps_op_read8 + bsl::unordered_map, bf_uint8_t> m_bf_vps_op_read8; + /// @brief stores the results for bf_vps_op_read16 + bsl::unordered_map, bf_uint16_t> m_bf_vps_op_read16; + /// @brief stores the results for bf_vps_op_read32 + bsl::unordered_map, bf_uint32_t> m_bf_vps_op_read32; + /// @brief stores the results for bf_vps_op_read64 + bsl::unordered_map, bf_uint64_t> m_bf_vps_op_read64; + /// @brief stores the results for bf_vps_op_write8 + bsl::unordered_map, bsl::errc_type> m_bf_vps_op_write8; + /// @brief stores the results for bf_vps_op_write16 + bsl::unordered_map, bsl::errc_type> m_bf_vps_op_write16; + /// @brief stores the results for bf_vps_op_write32 + bsl::unordered_map, bsl::errc_type> m_bf_vps_op_write32; + /// @brief stores the results for bf_vps_op_write64 + bsl::unordered_map, bsl::errc_type> m_bf_vps_op_write64; + /// @brief stores the results for bf_vps_op_read_reg + bsl::unordered_map, bf_uint64_t> m_bf_vps_op_read_reg; + /// @brief stores the results for bf_vps_op_write_reg + bsl::unordered_map, bsl::errc_type> m_bf_vps_op_write_reg; + /// @brief stores the results for bf_vps_op_run + bsl::unordered_map, bsl::errc_type> m_bf_vps_op_run; + /// @brief stores the results for bf_vps_op_run_current + bsl::errc_type m_bf_vps_op_run_current; + /// @brief stores the results for bf_vps_op_advance_ip + bsl::unordered_map m_bf_vps_op_advance_ip; + /// @brief stores the results for bf_vps_op_advance_ip_and_run_current + bsl::errc_type m_bf_vps_op_advance_ip_and_run_current; + /// @brief stores the results for bf_vps_op_promote + bsl::unordered_map m_bf_vps_op_promote; + /// @brief stores the results for bf_vps_op_clear_vps + bsl::unordered_map m_bf_vps_op_clear_vps; + /// @brief stores the results for bf_intrinsic_op_rdmsr + bsl::unordered_map m_bf_intrinsic_op_rdmsr; + /// @brief stores the results for bf_intrinsic_op_wrmsr + bsl::unordered_map, bsl::errc_type> m_bf_intrinsic_op_wrmsr; + /// @brief stores the results for bf_intrinsic_op_invlpga + bsl::unordered_map, bsl::errc_type> m_bf_intrinsic_op_invlpga; + /// @brief stores the results for bf_intrinsic_op_invept + bsl::unordered_map, bsl::errc_type> m_bf_intrinsic_op_invept; + /// @brief stores the results for bf_intrinsic_op_invvpid + bsl::unordered_map, bsl::errc_type> m_bf_intrinsic_op_invvpid; + /// @brief stores the results for bf_mem_op_alloc_page + bsl::errc_type m_bf_mem_op_alloc_page; + /// @brief stores the results for bf_mem_op_free_page + bsl::errc_type m_bf_mem_op_free_page; + /// @brief stores the results for bf_mem_op_alloc_huge + bsl::errc_type m_bf_mem_op_alloc_huge; + /// @brief stores the results for bf_mem_op_free_huge + bsl::errc_type m_bf_mem_op_free_huge; + + /// @brief stores a map of allocations and their sizes + bsl::unordered_map m_alloc_free_map; + /// @brief stores the results for bf_read_phys + bsl::unordered_map m_read_write_phys_map; + /// @brief stores a map of virt to phys translations + bsl::unordered_map m_virt_to_phys_map; + /// @brief stores a map of phys to virt translations + bsl::unordered_map m_phys_to_virt_map; + + // clang-format on + + public: + /// + /// @brief Initializes the bf_syscall_t by opening a handle and + /// registering all of the required handlers. If this function + /// fails, the handle is closed automatically. + /// + /// + /// @param version the version provided to the extension by the + /// microkernel. If this API does not support the ABI versions + /// that the microkernel supports, this function will fail. + /// @param bootstrap_handler the bootstrap handler to register + /// @param vmexit_handler the vmexit handler to register + /// @param fail_handler the fail handler to register + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + bf_uint32_t const &version, + bf_callback_handler_bootstrap_t const bootstrap_handler, + bf_callback_handler_vmexit_t const vmexit_handler, + bf_callback_handler_fail_t const fail_handler) noexcept -> bsl::errc_type + { + if (bsl::unlikely(!version)) { + bsl::error() << "invalid version\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(version.is_zero())) { + bsl::error() << "version cannot be zero\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(nullptr == bootstrap_handler)) { + bsl::error() << "invalid bootstrap_handler\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(nullptr == vmexit_handler)) { + bsl::error() << "invalid vmexit_handler\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(nullptr == fail_handler)) { + bsl::error() << "invalid fail_handler\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_initialize; + } + + /// + /// @brief Sets the return value of initialize. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// initialize + /// + constexpr void + set_initialize(bsl::errc_type const &errc) noexcept + { + m_initialize = errc; + } + + /// + /// @brief Releases the bf_syscall_t by closing the handle. + /// + constexpr void + release() noexcept + {} + + // --------------------------------------------------------------------- + // TLS ops + // --------------------------------------------------------------------- + + /// + /// @brief Returns the value of tls.rax + /// + /// + /// @return Returns the value of tls.rax + /// + [[nodiscard]] constexpr auto + bf_tls_rax() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_RAX); + } + + /// + /// @brief Sets the value of tls.rax + /// + /// + /// @param val The value to set tls.rax to + /// + constexpr void + bf_tls_set_rax(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_RAX) = val; + } + + /// + /// @brief Returns the value of tls.rbx + /// + /// + /// @return Returns the value of tls.rbx + /// + [[nodiscard]] constexpr auto + bf_tls_rbx() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_RBX); + } + + /// + /// @brief Sets the value of tls.rbx + /// + /// + /// @param val The value to set tls.rbx to + /// + constexpr void + bf_tls_set_rbx(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_RBX) = val; + } + + /// + /// @brief Returns the value of tls.rcx + /// + /// + /// @return Returns the value of tls.rcx + /// + [[nodiscard]] constexpr auto + bf_tls_rcx() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_RCX); + } + + /// + /// @brief Sets the value of tls.rcx + /// + /// + /// @param val The value to set tls.rcx to + /// + constexpr void + bf_tls_set_rcx(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_RCX) = val; + } + + /// + /// @brief Returns the value of tls.rdx + /// + /// + /// @return Returns the value of tls.rdx + /// + [[nodiscard]] constexpr auto + bf_tls_rdx() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_RDX); + } + + /// + /// @brief Sets the value of tls.rdx + /// + /// + /// @param val The value to set tls.rdx to + /// + constexpr void + bf_tls_set_rdx(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_RDX) = val; + } + + /// + /// @brief Returns the value of tls.rbp + /// + /// + /// @return Returns the value of tls.rbp + /// + [[nodiscard]] constexpr auto + bf_tls_rbp() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_RBP); + } + + /// + /// @brief Sets the value of tls.rbp + /// + /// + /// @param val The value to set tls.rbp to + /// + constexpr void + bf_tls_set_rbp(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_RBP) = val; + } + + /// + /// @brief Returns the value of tls.rsi + /// + /// + /// @return Returns the value of tls.rsi + /// + [[nodiscard]] constexpr auto + bf_tls_rsi() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_RSI); + } + + /// + /// @brief Sets the value of tls.rsi + /// + /// + /// @param val The value to set tls.rsi to + /// + constexpr void + bf_tls_set_rsi(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_RSI) = val; + } + + /// + /// @brief Returns the value of tls.rdi + /// + /// + /// @return Returns the value of tls.rdi + /// + [[nodiscard]] constexpr auto + bf_tls_rdi() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_RDI); + } + + /// + /// @brief Sets the value of tls.rdi + /// + /// + /// @param val The value to set tls.rdi to + /// + constexpr void + bf_tls_set_rdi(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_RDI) = val; + } + + /// + /// @brief Returns the value of tls.r8 + /// + /// + /// @return Returns the value of tls.r8 + /// + [[nodiscard]] constexpr auto + bf_tls_r8() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_R8); + } + + /// + /// @brief Sets the value of tls.r8 + /// + /// + /// @param val The value to set tls.r8 to + /// + constexpr void + bf_tls_set_r8(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_R8) = val; + } + + /// + /// @brief Returns the value of tls.r9 + /// + /// + /// @return Returns the value of tls.r9 + /// + [[nodiscard]] constexpr auto + bf_tls_r9() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_R9); + } + + /// + /// @brief Sets the value of tls.r9 + /// + /// + /// @param val The value to set tls.r9 to + /// + constexpr void + bf_tls_set_r9(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_R9) = val; + } + + /// + /// @brief Returns the value of tls.r10 + /// + /// + /// @return Returns the value of tls.r10 + /// + [[nodiscard]] constexpr auto + bf_tls_r10() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_R10); + } + + /// + /// @brief Sets the value of tls.r10 + /// + /// + /// @param val The value to set tls.r10 to + /// + constexpr void + bf_tls_set_r10(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_R10) = val; + } + + /// + /// @brief Returns the value of tls.r11 + /// + /// + /// @return Returns the value of tls.r11 + /// + [[nodiscard]] constexpr auto + bf_tls_r11() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_R11); + } + + /// + /// @brief Sets the value of tls.r11 + /// + /// + /// @param val The value to set tls.r11 to + /// + constexpr void + bf_tls_set_r11(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_R11) = val; + } + + /// + /// @brief Returns the value of tls.r12 + /// + /// + /// @return Returns the value of tls.r12 + /// + [[nodiscard]] constexpr auto + bf_tls_r12() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_R12); + } + + /// + /// @brief Sets the value of tls.r12 + /// + /// + /// @param val The value to set tls.r12 to + /// + constexpr void + bf_tls_set_r12(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_R12) = val; + } + + /// + /// @brief Returns the value of tls.r13 + /// + /// + /// @return Returns the value of tls.r13 + /// + [[nodiscard]] constexpr auto + bf_tls_r13() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_R13); + } + + /// + /// @brief Sets the value of tls.r13 + /// + /// + /// @param val The value to set tls.r13 to + /// + constexpr void + bf_tls_set_r13(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_R13) = val; + } + + /// + /// @brief Returns the value of tls.r14 + /// + /// + /// @return Returns the value of tls.r14 + /// + [[nodiscard]] constexpr auto + bf_tls_r14() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_R14); + } + + /// + /// @brief Sets the value of tls.r14 + /// + /// + /// @param val The value to set tls.r14 to + /// + constexpr void + bf_tls_set_r14(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_R14) = val; + } + + /// + /// @brief Returns the value of tls.r15 + /// + /// + /// @return Returns the value of tls.r15 + /// + [[nodiscard]] constexpr auto + bf_tls_r15() const noexcept -> bf_uint64_t + { + return m_tls.at(TLS_OFFSET_R15); + } + + /// + /// @brief Sets the value of tls.r15 + /// + /// + /// @param val The value to set tls.r15 to + /// + constexpr void + bf_tls_set_r15(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + m_tls.at(TLS_OFFSET_R15) = val; + } + + /// + /// @brief Returns the value of tls.extid + /// + /// + /// @return Returns the value of tls.extid + /// + [[nodiscard]] constexpr auto + bf_tls_extid() const noexcept -> bsl::safe_uint16 + { + return bsl::to_u16(m_tls.at(TLS_OFFSET_ACTIVE_EXTID)); + } + + /// + /// @brief Sets the value of tls.extid (unit testing only) + /// + /// + /// @param val The value to set tls.extid to + /// + constexpr void + bf_tls_set_extid(bf_uint16_t const &val) noexcept + { + m_tls.at(TLS_OFFSET_ACTIVE_EXTID) = bsl::to_u64(val); + } + + /// + /// @brief Returns the value of tls.vmid + /// + /// + /// @return Returns the value of tls.vmid + /// + [[nodiscard]] constexpr auto + bf_tls_vmid() const noexcept -> bsl::safe_uint16 + { + return bsl::to_u16(m_tls.at(TLS_OFFSET_ACTIVE_VMID)); + } + + /// + /// @brief Sets the value of tls.vmid (unit testing only) + /// + /// + /// @param val The value to set tls.vmid to + /// + constexpr void + bf_tls_set_vmid(bf_uint16_t const &val) noexcept + { + m_tls.at(TLS_OFFSET_ACTIVE_VMID) = bsl::to_u64(val); + } + + /// + /// @brief Returns the value of tls.vpid + /// + /// + /// @return Returns the value of tls.vpid + /// + [[nodiscard]] constexpr auto + bf_tls_vpid() const noexcept -> bsl::safe_uint16 + { + return bsl::to_u16(m_tls.at(TLS_OFFSET_ACTIVE_VPID)); + } + + /// + /// @brief Sets the value of tls.vpid (unit testing only) + /// + /// + /// @param val The value to set tls.vpid to + /// + constexpr void + bf_tls_set_vpid(bf_uint16_t const &val) noexcept + { + m_tls.at(TLS_OFFSET_ACTIVE_VPID) = bsl::to_u64(val); + } + + /// + /// @brief Returns the value of tls.vpsid + /// + /// + /// @return Returns the value of tls.vpsid + /// + [[nodiscard]] constexpr auto + bf_tls_vpsid() const noexcept -> bsl::safe_uint16 + { + return bsl::to_u16(m_tls.at(TLS_OFFSET_ACTIVE_VPSID)); + } + + /// + /// @brief Sets the value of tls.vpsid (unit testing only) + /// + /// + /// @param val The value to set tls.vpsid to + /// + constexpr void + bf_tls_set_vpsid(bf_uint16_t const &val) noexcept + { + m_tls.at(TLS_OFFSET_ACTIVE_VPSID) = bsl::to_u64(val); + } + + /// + /// @brief Returns the value of tls.ppid + /// + /// + /// @return Returns the value of tls.ppid + /// + [[nodiscard]] constexpr auto + bf_tls_ppid() const noexcept -> bsl::safe_uint16 + { + return bsl::to_u16(m_tls.at(TLS_OFFSET_ACTIVE_PPID)); + } + + /// + /// @brief Sets the value of tls.ppid (unit testing only) + /// + /// + /// @param val The value to set tls.ppid to + /// + constexpr void + bf_tls_set_ppid(bf_uint16_t const &val) noexcept + { + m_tls.at(TLS_OFFSET_ACTIVE_PPID) = bsl::to_u64(val); + } + + /// + /// @brief Returns the value of tls.online_pps + /// + /// + /// @return Returns the value of tls.online_pps + /// + [[nodiscard]] constexpr auto + bf_tls_online_pps() const noexcept -> bsl::safe_uint16 + { + return bsl::to_u16(m_tls.at(TLS_OFFSET_ONLINE_PPS)); + } + + /// + /// @brief Sets the value of tls.online_pps (unit testing only) + /// + /// + /// @param val The value to set tls.online_pps to + /// + constexpr void + bf_tls_set_online_pps(bf_uint16_t const &val) noexcept + { + m_tls.at(TLS_OFFSET_ONLINE_PPS) = bsl::to_u64(val); + } + + // --------------------------------------------------------------------- + // bf_vm_ops + // --------------------------------------------------------------------- + + /// + /// @brief This syscall tells the microkernel to create a VM + /// and return it's ID. + /// + /// + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vm_op_create_vm() noexcept -> bf_uint16_t + { + return m_bf_vm_op_create_vm; + } + + /// + /// @brief Sets the return value of bf_vm_op_create_vm. + /// (unit testing only) + /// + /// + /// @param vmid the ID to return when executing bf_vm_op_create_vm + /// + constexpr void + set_bf_vm_op_create_vm(bf_uint16_t const &vmid) noexcept + { + m_bf_vm_op_create_vm = vmid; + } + + /// + /// @brief This syscall tells the microkernel to destroy a VM + /// given an ID. + /// + /// + /// @param vmid The VMID of the VM to destroy + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vm_op_destroy_vm(bf_uint16_t const &vmid) noexcept -> bsl::errc_type + { + if (bsl::unlikely(!vmid)) { + bsl::error() << "invalid vmid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_vm_op_destroy_vm.at(vmid); + } + + /// + /// @brief Sets the return value of bf_vm_op_destroy_vm. + /// (unit testing only) + /// + /// + /// @param vmid The VMID of the VM to destroy + /// @param errc the bsl::errc_type to return when executing + /// bf_vm_op_destroy_vm + /// + constexpr void + set_bf_vm_op_destroy_vm(bf_uint16_t const &vmid, bsl::errc_type const errc) noexcept + { + m_bf_vm_op_destroy_vm.at(vmid) = errc; + } + + // --------------------------------------------------------------------- + // bf_vp_ops + // --------------------------------------------------------------------- + + /// + /// @brief This syscall tells the microkernel to create a VP given the + /// IDs of the VM and PP the VP will be assigned to. Upon success, + /// this syscall returns the ID of the newly created VP. + /// + /// + /// @param vmid The ID of the VM to assign the newly created VP to + /// @param ppid The ID of the PP to assign the newly created VP to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vp_op_create_vp(bf_uint16_t const &vmid, bf_uint16_t const &ppid) noexcept -> bf_uint16_t + { + if (bsl::unlikely(!vmid)) { + bsl::error() << "invalid vmid\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + if (bsl::unlikely(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + return m_bf_vp_op_create_vp.at({vmid, ppid}); + } + + /// + /// @brief Sets the return value of bf_vp_op_create_vp. + /// (unit testing only) + /// + /// + /// @param vmid The ID of the VM to assign the newly created VP to + /// @param ppid The ID of the PP to assign the newly created VP to + /// @param vpid the ID to return when executing set_bf_vp_op_create_vp + /// + constexpr void + set_bf_vp_op_create_vp( + bf_uint16_t const &vmid, bf_uint16_t const &ppid, bf_uint16_t const &vpid) noexcept + { + m_bf_vp_op_create_vp.at({vmid, ppid}) = vpid; + } + + /// + /// @brief This syscall tells the microkernel to destroy a VP + /// given an ID. + /// + /// + /// @param vpid The VPID of the VP to destroy + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vp_op_destroy_vp(bf_uint16_t const &vpid) noexcept -> bsl::errc_type + { + if (bsl::unlikely(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_vp_op_destroy_vp.at(vpid); + } + + /// + /// @brief Sets the return value of bf_vp_op_destroy_vp. + /// (unit testing only) + /// + /// + /// @param vpid The VPID of the VP to destroy + /// @param errc the bsl::errc_type to return when executing + /// bf_vp_op_destroy_vp + /// + constexpr void + set_bf_vp_op_destroy_vp(bf_uint16_t const &vpid, bsl::errc_type const errc) noexcept + { + m_bf_vp_op_destroy_vp.at(vpid) = errc; + } + + /// + /// @brief This syscall tells the microkernel to migrate a VP from one PP + /// to another PP. This function does not execute the VP (use + /// bf_vps_op_run for that), but instead allows bf_vps_op_run to + /// execute a VP on a PP that it was not originally assigned to. + /// + /// When a VP is migrated, all of the VPSs that are assigned to the + /// requested VP are also migrated to this new PP as well. From an + /// AMD/Intel point of view, this clears the VMCS/VMCB for each VPS + /// assigned to the VP. On Intel, it also loads the newly cleared VPS + /// and sets the launched state to false, ensuring the next + /// bf_vps_op_run will use VMLaunch instead of VMResume. + /// + /// It should be noted that the migration of a VPS from one PP to + /// another does not happen during the execution of this ABI. This + /// ABI simply tells the microkernel that the requested VP may now + /// execute on the requested PP. This will cause a mismatch between + /// the assigned PP for a VP and the assigned PP for a VPS. The + /// microkernel will detect this mismatch when an extension attempts + /// to execute bf_vps_op_run. When this occurs, the microkernel will + /// ensure the VP is being run on the PP it was assigned to during + /// migration, and then it will check to see if the PP of the VPS + /// matches. If it doesn't, it will then perform a migration of that + /// VPS at that time. This ensures that the microkernel is only + /// migrations VPSs when it needs to, and it ensures the VPS is + /// cleared an loaded (in the case of Intel) on the PP it will be + /// executed on, which is a requirement for VMCS migration. An + /// extension can determine which VPSs have been migrated by looking + /// at the assigned PP of a VPS. If it doesn't match the VP it was + /// assigned to, it has not been migrated. Finally, an extension is + /// free to read/write to the VPSs state, even if it has not been + /// migrated. The only requirement for migration is execution (meaning + /// VMRun/VMLaunch/VMResume). + /// + /// Any additional migration responsibilities, like TSC + /// synchronization, must be performed by the extension. + /// + /// + /// @param vpid The VPID of the VP to migrate + /// @param ppid The ID of the PP to assign the provided VP to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vp_op_migrate(bf_uint16_t const &vpid, bf_uint16_t const &ppid) noexcept + -> bsl::errc_type + { + if (bsl::unlikely(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_vp_op_migrate.at({vpid, ppid}); + } + + /// + /// @brief Sets the return value of bf_vp_op_migrate. + /// (unit testing only) + /// + /// + /// @param vpid The VPID of the VP to migrate + /// @param ppid The ID of the PP to assign the provided VP to + /// @param errc the bsl::errc_type to return when executing + /// bf_vp_op_migrate + /// + constexpr void + set_bf_vp_op_migrate( + bf_uint16_t const &vpid, bf_uint16_t const &ppid, bsl::errc_type const errc) noexcept + { + m_bf_vp_op_migrate.at({vpid, ppid}) = errc; + } + + // --------------------------------------------------------------------- + // bf_vps_ops + // --------------------------------------------------------------------- + + /// + /// @brief This syscall tells the microkernel to create a VPS + /// and return it's ID. + /// + /// + /// @param vpid The ID of the VP to assign the newly created VPS to + /// @param ppid The resulting VPSID of the newly created VPS + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_create_vps(bf_uint16_t const &vpid, bf_uint16_t const &ppid) noexcept + -> bf_uint16_t + { + if (bsl::unlikely(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + if (bsl::unlikely(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + return m_bf_vps_op_create_vps.at({vpid, ppid}); + } + + /// + /// @brief Sets the return value of bf_vps_op_create_vps. + /// (unit testing only) + /// + /// + /// @param vpid The ID of the VP to assign the newly created VPS to + /// @param ppid The resulting VPSID of the newly created VPS + /// @param vspid the ID to return when executing + /// set_bf_vps_op_create_vps + /// + constexpr void + set_bf_vps_op_create_vps( + bf_uint16_t const &vpid, bf_uint16_t const &ppid, bf_uint16_t const &vspid) noexcept + { + m_bf_vps_op_create_vps.at({vpid, ppid}) = vspid; + } + + /// + /// @brief This syscall tells the microkernel to destroy a VPS + /// given an ID. + /// + /// + /// @param vpsid The VPSID of the VPS to destroy + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_destroy_vps(bf_uint16_t const &vpsid) noexcept -> bsl::errc_type + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_vps_op_destroy_vps.at(vpsid); + } + + /// + /// @brief Sets the return value of bf_vps_op_destroy_vps. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to destroy + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_destroy_vps + /// + constexpr void + set_bf_vps_op_destroy_vps(bf_uint16_t const &vpsid, bsl::errc_type const errc) noexcept + { + m_bf_vps_op_destroy_vps.at(vpsid) = errc; + } + + /// + /// @brief This syscall tells the microkernel to initialize a VPS using + /// the root VP state provided by the loader using the current PPID. + /// + /// + /// @param vpsid The VPSID of the VPS to initialize + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_init_as_root(bf_uint16_t const &vpsid) noexcept -> bsl::errc_type + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_vps_op_init_as_root.at(vpsid); + } + + /// + /// @brief Sets the return value of bf_vps_op_init_as_root. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to initialize + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_init_as_root + /// + constexpr void + set_bf_vps_op_init_as_root(bf_uint16_t const &vpsid, bsl::errc_type const errc) noexcept + { + m_bf_vps_op_init_as_root.at(vpsid) = errc; + } + + /// + /// @brief Reads an 8bit field from the VPS and returns the value. The + /// "index" is architecture-specific. For Intel, Appendix B, "Field + /// Encoding in VMCS," defines the index (or encoding). For AMD, + /// Appendix B, "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @return Returns the value read, or bf_uint8_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_vps_op_read8(bf_uint16_t const &vpsid, bf_uint64_t const &index) const noexcept + -> bf_uint8_t + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bf_uint8_t::failure(); + } + + if (bsl::unlikely(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bf_uint8_t::failure(); + } + + return m_bf_vps_op_read8.at({vpsid, index}); + } + + /// + /// @brief Sets the return value of bf_vps_op_read8. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @param value the value to return when executing + /// bf_vps_op_read8 + /// + constexpr void + set_bf_vps_op_read8( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint8_t const &value) noexcept + { + m_bf_vps_op_read8.at({vpsid, index}) = value; + } + + /// + /// @brief Reads an 16bit field from the VPS and returns the value. The + /// "index" is architecture-specific. For Intel, Appendix B, "Field + /// Encoding in VMCS," defines the index (or encoding). For AMD, + /// Appendix B, "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @return Returns the value read, or bf_uint16_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_vps_op_read16(bf_uint16_t const &vpsid, bf_uint64_t const &index) const noexcept + -> bf_uint16_t + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + if (bsl::unlikely(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + return m_bf_vps_op_read16.at({vpsid, index}); + } + + /// + /// @brief Sets the return value of bf_vps_op_read16. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @param value the value to return when executing + /// bf_vps_op_read16 + /// + constexpr void + set_bf_vps_op_read16( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint16_t const &value) noexcept + { + m_bf_vps_op_read16.at({vpsid, index}) = value; + } + + /// + /// @brief Reads an 32bit field from the VPS and returns the value. The + /// "index" is architecture-specific. For Intel, Appendix B, "Field + /// Encoding in VMCS," defines the index (or encoding). For AMD, + /// Appendix B, "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @return Returns the value read, or bf_uint32_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_vps_op_read32(bf_uint16_t const &vpsid, bf_uint64_t const &index) const noexcept + -> bf_uint32_t + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bf_uint32_t::failure(); + } + + if (bsl::unlikely(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bf_uint32_t::failure(); + } + + return m_bf_vps_op_read32.at({vpsid, index}); + } + + /// + /// @brief Sets the return value of bf_vps_op_read32. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @param value the value to return when executing + /// bf_vps_op_read32 + /// + constexpr void + set_bf_vps_op_read32( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint32_t const &value) noexcept + { + m_bf_vps_op_read32.at({vpsid, index}) = value; + } + + /// + /// @brief Reads an 64bit field from the VPS and returns the value. The + /// "index" is architecture-specific. For Intel, Appendix B, "Field + /// Encoding in VMCS," defines the index (or encoding). For AMD, + /// Appendix B, "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @return Returns the value read, or bf_uint64_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_vps_op_read64(bf_uint16_t const &vpsid, bf_uint64_t const &index) const noexcept + -> bf_uint64_t + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bf_uint64_t::failure(); + } + + if (bsl::unlikely(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bf_uint64_t::failure(); + } + + return m_bf_vps_op_read64.at({vpsid, index}); + } + + /// + /// @brief Sets the return value of bf_vps_op_read64. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @param value the value to return when executing + /// bf_vps_op_read64 + /// + constexpr void + set_bf_vps_op_read64( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint64_t const &value) noexcept + { + m_bf_vps_op_read64.at({vpsid, index}) = value; + } + + /// + /// @brief Writes to an 8bit field in the VPS. The "index" is + /// architecture-specific. For Intel, Appendix B, "Field Encoding in + /// VMCS," defines the index (or encoding). For AMD, Appendix B, + /// "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_write8( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint8_t const &value) noexcept + -> bsl::errc_type + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (m_bf_vps_op_write8.at({vpsid, index, value})) { + m_bf_vps_op_read8.at({vpsid, index}) = value; + } + else { + bsl::touch(); + } + + return m_bf_vps_op_write8.at({vpsid, index, value}); + } + + /// + /// @brief Sets the return value of bf_vps_op_write8. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_write8 + /// + constexpr void + set_bf_vps_op_write8( + bf_uint16_t const &vpsid, + bf_uint64_t const &index, + bf_uint8_t const &value, + bsl::errc_type const errc) noexcept + { + m_bf_vps_op_write8.at({vpsid, index, value}) = errc; + } + + /// + /// @brief Writes to an 16bit field in the VPS. The "index" is + /// architecture-specific. For Intel, Appendix B, "Field Encoding in + /// VMCS," defines the index (or encoding). For AMD, Appendix B, + /// "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_write16( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint16_t const &value) noexcept + -> bsl::errc_type + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (m_bf_vps_op_write16.at({vpsid, index, value})) { + m_bf_vps_op_read16.at({vpsid, index}) = value; + } + else { + bsl::touch(); + } + + return m_bf_vps_op_write16.at({vpsid, index, value}); + } + + /// + /// @brief Sets the return value of bf_vps_op_write16. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_write16 + /// + constexpr void + set_bf_vps_op_write16( + bf_uint16_t const &vpsid, + bf_uint64_t const &index, + bf_uint16_t const &value, + bsl::errc_type const errc) noexcept + { + m_bf_vps_op_write16.at({vpsid, index, value}) = errc; + } + + /// + /// @brief Writes to an 32bit field in the VPS. The "index" is + /// architecture-specific. For Intel, Appendix B, "Field Encoding in + /// VMCS," defines the index (or encoding). For AMD, Appendix B, + /// "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_write32( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint32_t const &value) noexcept + -> bsl::errc_type + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (m_bf_vps_op_write32.at({vpsid, index, value})) { + m_bf_vps_op_read32.at({vpsid, index}) = value; + } + else { + bsl::touch(); + } + + return m_bf_vps_op_write32.at({vpsid, index, value}); + } + + /// + /// @brief Sets the return value of bf_vps_op_write32. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_write32 + /// + constexpr void + set_bf_vps_op_write32( + bf_uint16_t const &vpsid, + bf_uint64_t const &index, + bf_uint32_t const &value, + bsl::errc_type const errc) noexcept + { + m_bf_vps_op_write32.at({vpsid, index, value}) = errc; + } + + /// + /// @brief Writes to an 64bit field in the VPS. The "index" is + /// architecture-specific. For Intel, Appendix B, "Field Encoding in + /// VMCS," defines the index (or encoding). For AMD, Appendix B, + /// "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_write64( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint64_t const &value) noexcept + -> bsl::errc_type + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (m_bf_vps_op_write64.at({vpsid, index, value})) { + m_bf_vps_op_read64.at({vpsid, index}) = value; + } + else { + bsl::touch(); + } + + return m_bf_vps_op_write64.at({vpsid, index, value}); + } + + /// + /// @brief Sets the return value of bf_vps_op_write64. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_write64 + /// + constexpr void + set_bf_vps_op_write64( + bf_uint16_t const &vpsid, + bf_uint64_t const &index, + bf_uint64_t const &value, + bsl::errc_type const errc) noexcept + { + m_bf_vps_op_write64.at({vpsid, index, value}) = errc; + } + + /// + /// @brief Reads a CPU register from the VPS given a bf_reg_t. Note + /// that the bf_reg_t is architecture specific. + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param reg A bf_reg_t defining which register to read + /// @return Returns the value read, or bf_uint64_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_vps_op_read_reg(bf_uint16_t const &vpsid, bf_reg_t const reg) const noexcept + -> bf_uint64_t + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bf_uint64_t::failure(); + } + + return m_bf_vps_op_read_reg.at({vpsid, reg}); + } + + /// + /// @brief Sets the return value of bf_vps_op_read_reg. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param reg A bf_reg_t defining which register to read + /// @param value the value to return when executing + /// bf_vps_op_read_reg + /// + constexpr void + set_bf_vps_op_read_reg( + bf_uint16_t const &vpsid, bf_reg_t const reg, bf_uint64_t const &value) noexcept + { + m_bf_vps_op_read_reg.at({vpsid, reg}) = value; + } + + /// + /// @brief Writes to a CPU register in the VPS given a bf_reg_t and the + /// value to write. Note that the bf_reg_t is architecture specific. + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param reg A bf_reg_t defining which register to write to + /// @param value The value to write to the requested register + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_write_reg( + bf_uint16_t const &vpsid, bf_reg_t const reg, bf_uint64_t const &value) noexcept + -> bsl::errc_type + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (m_bf_vps_op_write_reg.at({vpsid, reg, value})) { + m_bf_vps_op_read_reg.at({vpsid, reg}) = value; + } + else { + bsl::touch(); + } + + return m_bf_vps_op_write_reg.at({vpsid, reg, value}); + } + + /// + /// @brief Sets the return value of bf_vps_op_write_reg. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param reg A bf_reg_t defining which register to write to + /// @param value The value to write to the requested field + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_write_reg + /// + constexpr void + set_bf_vps_op_write_reg( + bf_uint16_t const &vpsid, + bf_reg_t const reg, + bf_uint64_t const &value, + bsl::errc_type const errc) noexcept + { + m_bf_vps_op_write_reg.at({vpsid, reg, value}) = errc; + } + + /// + /// @brief bf_vps_op_run tells the microkernel to execute a given VPS on + /// behalf of a given VP and VM. This system call only returns if an + /// error occurs. On success, this system call will physically execute + /// the requested VM and VP using the requested VPS, and the extension + /// will only execute again on the next VMExit. + /// + /// Unless an extension needs to change the active VM, VP or VPS, the + /// extension should use bf_vps_op_run_current instead of + /// bf_vps_op_run. bf_vps_op_run is slow as it must perform a series of + /// checks to determine if it has any work to perform before execution + /// of a VM can occur. + /// + /// Unlike bf_vps_op_run_current which is really just a return to + /// microkernel execution, bf_vps_op_run must perform the following + /// operations: + /// - It first verifies that the provided VM, VP and VPS are all + /// created. Meaning, and extension must first use the create ABI + /// to properly create a VM, VP and VPS before it may be used. + /// - Next, it must ensure VM, VP and VPS assignment is correct. A + /// newly created VP and VPS are unassigned. Once bf_vps_op_run is + /// executed, the VP is assigned to the provided VM and the VPS is + /// assigned to the provided VP. The VP and VPS are also both + /// assigned to the PP bf_vps_op_run is executed on. Once these + /// assignments take place, an extension cannot change them, and any + /// attempt to run a VP or VPS on a VM, VP or PP they are not + /// assigned to will fail. It is impossible to change the assigned of + /// a VM or VP, but an extension can change the assignment of a VP + /// and VPSs PP by using the bf_vp_op_migrate function. + /// - Next, bf_vps_op_run must determine if it needs to migrate a VPS + /// to the PP the VPS is being executed on by bf_vps_op_run. For more + /// information about how this works, please see bf_vp_op_migrate. + /// - Finally, bf_vps_op_run must ensure the active VM, VP and VPS are + /// set to the VM, VP and VPS provided to this ABI. Any changes in + /// the active state could cause additional operations to take place. + /// For example, the VPS must transfer the TLS state of the general + /// purpose registers to its internal cache so that the VPS that is + /// about to become active can use the TLS block instead. + /// + /// + /// @param vmid The VMID of the VM to run + /// @param vpid The VPID of the VP to run + /// @param vpsid The VPSID of the VPS to run + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_run( + bf_uint16_t const &vmid, bf_uint16_t const &vpid, bf_uint16_t const &vpsid) noexcept + -> bsl::errc_type + { + if (bsl::unlikely(!vmid)) { + bsl::error() << "invalid vmid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_vps_op_run.at({vmid, vpid, vpsid}); + } + + /// + /// @brief Sets the return value of bf_vps_op_run. + /// (unit testing only) + /// + /// + /// @param vmid The VMID of the VM to run + /// @param vpid The VPID of the VP to run + /// @param vpsid The VPSID of the VPS to run + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_run + /// + constexpr void + set_bf_vps_op_run( + bf_uint16_t const &vmid, + bf_uint16_t const &vpid, + bf_uint16_t const &vpsid, + bsl::errc_type const errc) noexcept + { + m_bf_vps_op_run.at({vmid, vpid, vpsid}) = errc; + } + + /// + /// @brief bf_vps_op_run_current tells the microkernel to execute the + /// currently active VPS, VP and VM. + /// + /// + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_run_current() noexcept -> bsl::errc_type + { + return m_bf_vps_op_run_current; + } + + /// + /// @brief Sets the return value of bf_vps_op_run_current. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_run_current + /// + constexpr void + set_bf_vps_op_run_current(bsl::errc_type const errc) noexcept + { + m_bf_vps_op_run_current = errc; + } + + /// + /// @brief This syscall tells the microkernel to advance the instruction + /// pointer in the requested VPS. + /// + /// + /// @param vpsid The VPSID of the VPS advance the IP in + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_advance_ip(bf_uint16_t const &vpsid) noexcept -> bsl::errc_type + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_vps_op_advance_ip.at(vpsid); + } + + /// + /// @brief Sets the return value of bf_vps_op_advance_ip. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS advance the IP in + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_advance_ip + /// + constexpr void + set_bf_vps_op_advance_ip(bf_uint16_t const &vpsid, bsl::errc_type const errc) noexcept + { + m_bf_vps_op_advance_ip.at(vpsid) = errc; + } + + /// + /// @brief This syscall tells the microkernel to advance the instruction + /// pointer in the currently active VPS and run the currently active + /// VPS, VP and VM (i.e., this combines bf_vps_op_advance_ip and + /// bf_vps_op_advance_ip). + /// + /// + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_advance_ip_and_run_current() noexcept -> bsl::errc_type + { + return m_bf_vps_op_advance_ip_and_run_current; + } + + /// + /// @brief Sets the return value of bf_vps_op_advance_ip_and_run_current. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_advance_ip_and_run_current + /// + constexpr void + set_bf_vps_op_advance_ip_and_run_current(bsl::errc_type const errc) noexcept + { + m_bf_vps_op_advance_ip_and_run_current = errc; + } + + /// + /// @brief This syscall tells the microkernel to promote the requested + /// VPS. This will stop the hypervisor complete on the physical + /// processor that this syscall is executed on and replace it's state + /// with the state in the VPS. Note that this syscall only returns + /// on error. + /// + /// + /// @param vpsid The VPSID of the VPS to promote + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_promote(bf_uint16_t const &vpsid) noexcept -> bsl::errc_type + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_vps_op_promote.at(vpsid); + } + + /// + /// @brief Sets the return value of bf_vps_op_promote. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to promote + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_promote + /// + constexpr void + set_bf_vps_op_promote(bf_uint16_t const &vpsid, bsl::errc_type const errc) noexcept + { + m_bf_vps_op_promote.at(vpsid) = errc; + } + + /// + /// @brief bf_vps_op_clear_vps tells the microkernel to clear the VPS's + /// hardware cache, if one exists. How this is used depends entirely + /// on the hardware and is associated with AMD's VMCB Clean Bits, + /// and Intel's VMClear instruction. See the associated documentation + /// for more details. On AMD, this ABI clears the entire VMCB. For more + /// fine grained control, use the write ABIs to manually modify the + /// VMCB. + /// + /// + /// @param vpsid The VPSID of the VPS to clear + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_clear_vps(bf_uint16_t const &vpsid) noexcept -> bsl::errc_type + { + if (bsl::unlikely(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_vps_op_clear_vps.at(vpsid); + } + + /// + /// @brief Sets the return value of bf_vps_op_clear_vps. + /// (unit testing only) + /// + /// + /// @param vpsid The VPSID of the VPS to clear + /// @param errc the bsl::errc_type to return when executing + /// bf_vps_op_clear_vps + /// + constexpr void + set_bf_vps_op_clear_vps(bf_uint16_t const &vpsid, bsl::errc_type const errc) noexcept + { + m_bf_vps_op_clear_vps.at(vpsid) = errc; + } + + // --------------------------------------------------------------------- + // bf_intrinsic_ops + // --------------------------------------------------------------------- + + /// + /// @brief Reads an MSR directly from the CPU given the address of + /// the MSR to read. Note that this is specific to Intel/AMD only. + /// Also note that not all MSRs can be read, and which MSRs that + /// can be read is up to the microkernel's internal policy as well + /// as which architecture the hypervisor is running on. + /// + /// + /// @param msr The address of the MSR to read + /// @return Returns the value read, or bf_uint64_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_intrinsic_op_rdmsr(bf_uint32_t const &msr) const noexcept -> bf_uint64_t + { + if (bsl::unlikely(!msr)) { + bsl::error() << "invalid msr\n" << bsl::here(); + return bf_uint64_t::failure(); + } + + return m_bf_intrinsic_op_rdmsr.at(msr); + } + + /// + /// @brief Sets the return value of bf_intrinsic_op_rdmsr. + /// (unit testing only) + /// + /// + /// @param msr The address of the MSR to read + /// @param value the value to return when executing + /// bf_intrinsic_op_rdmsr + /// + constexpr void + set_bf_intrinsic_op_rdmsr(bf_uint32_t const &msr, bf_uint64_t const &value) noexcept + { + m_bf_intrinsic_op_rdmsr.at(msr) = value; + } + + /// + /// @brief Writes to an MSR directly from the CPU given the address of + /// the MSR to write as well as the value to write. Note that this is + /// specific to Intel/AMD only. Also note that not all MSRs can be + /// written to, and which MSRs that can be written to is up to the + /// microkernel's internal policy as well as which architecture the + /// hypervisor is running on. + /// + /// + /// @param msr The address of the MSR to write to + /// @param value The value to write to the requested MSR + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_intrinsic_op_wrmsr(bf_uint32_t const &msr, bf_uint64_t const &value) noexcept + -> bsl::errc_type + { + if (bsl::unlikely(!msr)) { + bsl::error() << "invalid msr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (m_bf_intrinsic_op_wrmsr.at({msr, value})) { + m_bf_intrinsic_op_rdmsr.at(msr) = value; + } + else { + bsl::touch(); + } + + return m_bf_intrinsic_op_wrmsr.at({msr, value}); + } + + /// + /// @brief Sets the return value of bf_intrinsic_op_wrmsr. + /// (unit testing only) + /// + /// + /// @param msr The address of the MSR to write to + /// @param value The value to write to the requested MSR + /// @param errc the bsl::errc_type to return when executing + /// bf_intrinsic_op_wrmsr + /// + constexpr void + set_bf_intrinsic_op_wrmsr( + bf_uint32_t const &msr, bf_uint64_t const &value, bsl::errc_type const errc) noexcept + { + m_bf_intrinsic_op_wrmsr.at({msr, value}) = errc; + } + + /// + /// @brief Invalidates the TLB mapping for a given virtual page and a + /// given ASID. Note that this is specific to AMD only. + /// + /// + /// @param addr The address to invalidate + /// @param asid The ASID to invalidate + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_intrinsic_op_invlpga(bf_uint64_t const &addr, bf_uint64_t const &asid) noexcept + -> bsl::errc_type + { + if (bsl::unlikely(!addr)) { + bsl::error() << "invalid addr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!asid)) { + bsl::error() << "invalid asid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_intrinsic_op_invlpga.at({addr, asid}); + } + + /// + /// @brief Sets the return value of bf_intrinsic_op_invlpga. + /// (unit testing only) + /// + /// + /// @param addr The address to invalidate + /// @param asid The ASID to invalidate + /// @param errc the bsl::errc_type to return when executing + /// bf_intrinsic_op_invlpga + /// + constexpr void + set_bf_intrinsic_op_invlpga( + bf_uint64_t const &addr, bf_uint64_t const &asid, bsl::errc_type const errc) noexcept + { + m_bf_intrinsic_op_invlpga.at({addr, asid}) = errc; + } + + /// + /// @brief Invalidates mappings in the translation lookaside buffers + /// (TLBs) and paging-structure caches that were derived from extended + /// page tables (EPT). Note that this is specific to Intel only. + /// + /// + /// @param eptp The EPTP to invalidate + /// @param type The INVEPT type (see the Intel SDM for details) + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_intrinsic_op_invept(bf_uint64_t const &eptp, bf_uint64_t const &type) noexcept + -> bsl::errc_type + { + if (bsl::unlikely(!eptp)) { + bsl::error() << "invalid eptp\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!type)) { + bsl::error() << "invalid type\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_intrinsic_op_invept.at({eptp, type}); + } + + /// + /// @brief Sets the return value of bf_intrinsic_op_invept. + /// (unit testing only) + /// + /// + /// @param eptp The EPTP to invalidate + /// @param type The INVEPT type (see the Intel SDM for details) + /// @param errc the bsl::errc_type to return when executing + /// bf_intrinsic_op_invept + /// + constexpr void + set_bf_intrinsic_op_invept( + bf_uint64_t const &eptp, bf_uint64_t const &type, bsl::errc_type const errc) noexcept + { + m_bf_intrinsic_op_invept.at({eptp, type}) = errc; + } + + /// + /// @brief Invalidates mappings in the translation lookaside buffers + /// (TLBs) and paging-structure caches based on virtual-processor + /// identifier (VPID). Note that this is specific to Intel only. + /// + /// + /// @param addr The address to invalidate + /// @param vpid The VPID to invalidate + /// @param type The INVVPID type (see the Intel SDM for details) + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_intrinsic_op_invvpid( + bf_uint64_t const &addr, bf_uint16_t const &vpid, bf_uint64_t const &type) noexcept + -> bsl::errc_type + { + if (bsl::unlikely(!addr)) { + bsl::error() << "invalid addr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!type)) { + bsl::error() << "invalid type\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + return m_bf_intrinsic_op_invvpid.at({addr, vpid, type}); + } + + /// + /// @brief Sets the return value of bf_intrinsic_op_invvpid. + /// (unit testing only) + /// + /// + /// @param addr The address to invalidate + /// @param vpid The VPID to invalidate + /// @param type The INVVPID type (see the Intel SDM for details) + /// @param errc the bsl::errc_type to return when executing + /// bf_intrinsic_op_invvpid + /// + constexpr void + set_bf_intrinsic_op_invvpid( + bf_uint64_t const &addr, + bf_uint16_t const &vpid, + bf_uint64_t const &type, + bsl::errc_type const errc) noexcept + { + m_bf_intrinsic_op_invvpid.at({addr, vpid, type}) = errc; + } + + // --------------------------------------------------------------------- + // bf_mem_ops + // --------------------------------------------------------------------- + + /// + /// @brief bf_mem_op_alloc_page allocates a page, and maps this page + /// into the direct map of the VM. + /// + /// + /// @param phys The physical address of the resulting page + /// @return Returns a pointer to the newly allocated memory on success, + /// or a nullptr on failure. + /// + [[nodiscard]] constexpr auto + bf_mem_op_alloc_page(bf_uint64_t &phys) noexcept -> void * + { + if (bsl::unlikely(!phys)) { + bsl::error() << "invalid phys\n" << bsl::here(); + return nullptr; + } + + if (!m_bf_mem_op_alloc_page) { + return nullptr; + } + + auto *const virt{new bsl::uint8[HYPERVISOR_PAGE_SIZE.get()]}; + m_alloc_free_map.at(virt) = HYPERVISOR_PAGE_SIZE; + + phys = (m_alloc_free_map.size() * HYPERVISOR_PAGE_SIZE); + m_virt_to_phys_map.at(virt) = phys; + m_phys_to_virt_map.at(phys) = virt; + + return virt; + } + + /// + /// @brief bf_mem_op_alloc_page allocates a page, and maps this page + /// into the direct map of the VM. + /// + /// + /// @return Returns a pointer to the newly allocated memory on success, + /// or a nullptr on failure. + /// + [[nodiscard]] constexpr auto + bf_mem_op_alloc_page() noexcept -> void * + { + bf_uint64_t ignored{}; + return this->bf_mem_op_alloc_page(ignored); + } + + /// + /// @brief Sets the return value of bf_mem_op_alloc_page. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// bf_mem_op_alloc_page + /// + constexpr void + set_bf_mem_op_alloc_page(bsl::errc_type const errc) noexcept + { + m_bf_mem_op_alloc_page = errc; + } + + /// + /// @brief Frees a page previously allocated by bf_mem_op_alloc_page. + /// This operation is optional and not all microkernels may implement + /// it. + /// + /// + /// @param addr The virtual address of the page to free + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_mem_op_free_page(void *const addr) noexcept -> bsl::errc_type + { + bf_uint64_t phys{}; + bsl::uint8 *virt{}; + + if (bsl::unlikely(nullptr == addr)) { + bsl::error() << "addr is a nullptr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (!m_bf_mem_op_free_page) { + return m_bf_mem_op_free_page; + } + + if (m_alloc_free_map.at(addr).is_zero()) { + return bsl::errc_failure; + } + + phys = m_virt_to_phys_map.at(addr); + virt = m_phys_to_virt_map.at(phys); + m_virt_to_phys_map.at(virt) = {}; + m_phys_to_virt_map.at(phys) = {}; + + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + delete[] virt; // GRCOV_EXCLUDE_BR + m_alloc_free_map.at(virt) = {}; + + return bsl::errc_success; + } + + /// + /// @brief Sets the return value of bf_mem_op_free_page. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// bf_mem_op_free_page + /// + constexpr void + set_bf_mem_op_free_page(bsl::errc_type const errc) noexcept + { + m_bf_mem_op_free_page = errc; + } + + /// + /// @brief bf_mem_op_alloc_huge allocates a physically contiguous block + /// of memory. When allocating a page, the extension should keep in + /// mind the following: + /// - The total memory available to allocate from this pool is + /// extremely limited. This should only be used when absolutely + /// needed, and extensions should not expect more than 1 MB (might + /// be less) of total memory available. + /// - Memory allocated from the huge pool might be allocated using + /// different schemes. For example, the microkernel might allocate + /// in increments of a page, or it might use a buddy allocator that + /// would allocate in multiples of 2. If the allocation size + /// doesn't match the algorithm, internal fragmentation could + /// occur, further limiting the total number of allocations this + /// pool can support. + /// + /// + /// @param size The total number of bytes to allocate + /// @param phys The physical address of the resulting memory + /// @return Returns a pointer to the newly allocated memory on success, + /// or a nullptr on failure. + /// + [[nodiscard]] constexpr auto + bf_mem_op_alloc_huge(bf_uint64_t const &size, bf_uint64_t &phys) noexcept -> void * + { + if (bsl::unlikely(!size)) { + bsl::error() << "invalid size\n" << bsl::here(); + return nullptr; + } + + if (bsl::unlikely(size.is_zero())) { + bsl::error() << "size cannot be 0\n" << bsl::here(); + return nullptr; + } + + if (bsl::unlikely(!phys)) { + bsl::error() << "invalid phys\n" << bsl::here(); + return nullptr; + } + + if (!m_bf_mem_op_alloc_huge) { + return nullptr; + } + + auto *const virt{new bsl::uint8[size.get()]}; + m_alloc_free_map.at(virt) = size; + + phys = (m_alloc_free_map.size() * HYPERVISOR_PAGE_SIZE); + m_virt_to_phys_map.at(virt) = phys; + m_phys_to_virt_map.at(phys) = virt; + + return virt; + } + + /// + /// @brief bf_mem_op_alloc_huge allocates a physically contiguous block + /// of memory. When allocating a page, the extension should keep in + /// mind the following: + /// - The total memory available to allocate from this pool is + /// extremely limited. This should only be used when absolutely + /// needed, and extensions should not expect more than 1 MB (might + /// be less) of total memory available. + /// - Memory allocated from the huge pool might be allocated using + /// different schemes. For example, the microkernel might allocate + /// in increments of a page, or it might use a buddy allocator that + /// would allocate in multiples of 2. If the allocation size + /// doesn't match the algorithm, internal fragmentation could + /// occur, further limiting the total number of allocations this + /// pool can support. + /// + /// + /// @param size The total number of bytes to allocate + /// @return Returns a pointer to the newly allocated memory on success, + /// or a nullptr on failure. + /// + [[nodiscard]] constexpr auto + bf_mem_op_alloc_huge(bf_uint64_t const &size) noexcept -> void * + { + bf_uint64_t ignored{}; + return this->bf_mem_op_alloc_huge(size, ignored); + } + + /// + /// @brief Sets the return value of bf_mem_op_alloc_huge. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// bf_mem_op_alloc_huge + /// + constexpr void + set_bf_mem_op_alloc_huge(bsl::errc_type const errc) noexcept + { + m_bf_mem_op_alloc_huge = errc; + } + + /// + /// @brief Frees memory previously allocated by bf_mem_op_alloc_huge. + /// This operation is optional and not all microkernels may implement + /// it. + /// + /// + /// @param addr The virtual address of the memory to free + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_mem_op_free_huge(void *const addr) noexcept -> bsl::errc_type + { + bf_uint64_t phys{}; + bsl::uint8 *virt{}; + + if (bsl::unlikely(nullptr == addr)) { + bsl::error() << "addr is a nullptr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (!m_bf_mem_op_free_huge) { + return m_bf_mem_op_free_huge; + } + + if (m_alloc_free_map.at(addr).is_zero()) { + return bsl::errc_failure; + } + + phys = m_virt_to_phys_map.at(addr); + virt = m_phys_to_virt_map.at(phys); + m_virt_to_phys_map.at(virt) = {}; + m_phys_to_virt_map.at(phys) = {}; + + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + delete[] virt; // GRCOV_EXCLUDE_BR + m_alloc_free_map.at(virt) = {}; + + return bsl::errc_success; + } + + /// + /// @brief Sets the return value of bf_mem_op_free_huge. + /// (unit testing only) + /// + /// + /// @param errc the bsl::errc_type to return when executing + /// bf_mem_op_free_huge + /// + constexpr void + set_bf_mem_op_free_huge(bsl::errc_type const errc) noexcept + { + m_bf_mem_op_free_huge = errc; + } + + /// + /// @brief bf_mem_op_alloc_heap allocates heap memory. When allocating + /// heap memory, the extension should keep in mind the following: + /// - This ABI is designed to work similar to sbrk() to support + /// malloc/free implementations common with existing open source + /// libraries. + /// - Calling this ABI with with a size of 0 will return the current + /// heap location. + /// - Calling this ABI with a size (in bytes) will result in return + /// the previous heap location. The current heap location will be + /// set to the previous location, plus the provide size, rounded to + /// the nearest page size. + /// - The heap is not mapped into the direct map, so virtual to + /// physical (and vice versa) translations are not possible. + /// - There is no ability to free heap memory + /// + /// + /// @param size The number of bytes to increase the heap by + /// @return Returns a pointer to the newly allocated memory on success, + /// or a nullptr on failure. + /// + [[nodiscard]] static constexpr auto + bf_mem_op_alloc_heap(bf_uint64_t const &size) noexcept -> void * + { + bsl::discard(size); + + /// NOTE: + /// - This API is currently not supported by this unit test + /// library. This API is designed to support the implementation + /// of a malloc/free engine, and mimics sbrk(). To implement + /// this, the unit test would have to provide a contiguous + /// memory block that doesn't change, but can grow, at least + /// enough for the unit tests. + /// - In general, any code that is using this API would generally + /// be using whatever malloc/free engine this API is designed + /// to support, so during a unit test, malloc/free can simply + /// be used (or hopefully new/delete so that constexpr unit tests + /// can still be used). As a result, the only actual code that + /// would need this for testing would be the malloc/free engine. + /// - To unit test that code, simply set up the code to use sbrk() + /// and don't include a libc in your example (or at least do not + /// perform any allocations using malloc/free from libc). + /// - Due to the ability to set up unit tests to get 100% without + /// actually needing to use this API directly, we do not provide + /// it and instead encourage the above approach as needed. + /// - Code that doesn't use a heap does not need to worry about + /// any of this, and instead can use the page allocation APIs + /// above for doing a full memory analysis during unit testing. + /// + + bsl::error() << "bf_mem_op_alloc_heap not supported\n" << bsl::here(); + return nullptr; + } + + // --------------------------------------------------------------------- + // direct map helpers + // --------------------------------------------------------------------- + + /// + /// @brief Returns the value at the provided physical address + /// on success, or returns bsl::safe_integral::failure() + /// on failure. + /// + /// + /// @tparam T the type of integral to read + /// @param phys the physical address to read + /// @return Returns the value at the provided physical address + /// on success, or returns bsl::safe_integral::failure() + /// on failure. + /// + template + [[nodiscard]] constexpr auto + bf_read_phys(bf_uint64_t const &phys) const noexcept -> bsl::safe_integral + { + static_assert(bsl::is_unsigned::value); + bsl::safe_uintmax virt{}; + + if (bsl::unlikely(!phys)) { + bsl::error() << "invalid phys\n" << bsl::here(); + return bsl::safe_integral::failure(); + } + + if (bsl::unlikely(phys.is_zero())) { + bsl::error() << "phys is a nullptr\n" << bsl::here(); + return bsl::safe_integral::failure(); + } + + virt = phys + HYPERVISOR_EXT_DIRECT_MAP_ADDR; + if (bsl::unlikely(!virt)) { + bsl::error() << "bf_read_phys failed due to invalid physical address " // -- + << bsl::hex(phys) << bsl::endl // -- + << bsl::here(); + + return bsl::safe_integral::failure(); + } + + return bsl::convert(m_read_write_phys_map.at(phys)); + } + + /// + /// @brief Writes the provided value at the provided physical address + /// + /// + /// @tparam T the type of integral to write + /// @param phys the physical address to write + /// @param val the value to write to the provided physical address + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + template + [[nodiscard]] constexpr auto + bf_write_phys(bf_uint64_t const &phys, bsl::safe_integral const &val) noexcept + -> bsl::errc_type + { + static_assert(bsl::is_unsigned::value); + bsl::safe_uintmax virt{}; + + if (bsl::unlikely(!phys)) { + bsl::error() << "invalid phys\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(phys.is_zero())) { + bsl::error() << "phys is a nullptr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!val)) { + bsl::error() << "invalid val\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + virt = phys + HYPERVISOR_EXT_DIRECT_MAP_ADDR; + if (bsl::unlikely(!virt)) { + bsl::error() << "bf_write_phys failed due to invalid physical address " // -- + << bsl::hex(phys) << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + m_read_write_phys_map.at(phys) = bsl::to_u64(val); + return bsl::errc_success; + } + + /// + /// @brief Performs a virtual address to physical address translation. + /// Note that this function only works on direct map memory, which + /// includes direct map addresses, allocated pages and allocated + /// huge memory. + /// + /// + /// @param virt the virtual address to convert + /// @return Returns the resulting physical address + /// + [[nodiscard]] constexpr auto + bf_virt_to_phys(void *const virt) const noexcept -> bf_uint64_t + { + if (bsl::unlikely(nullptr == virt)) { + bsl::error() << "invalid virt\n" << bsl::here(); + return bf_uint64_t::failure(); + } + + /// NOTE: + /// - If you get this error message, it is because your code + /// does not adhere to the ABI. Virt to phys conversions are + /// only supported for memory that is allocated using + /// bf_mem_op_alloc_page and bf_mem_op_alloc_huge. We added this + /// extra check for sanity to help ensure the ABI is being + /// adhered to as the regular code doesn't keep track of this + /// which could result in UB. + /// + + if (!m_virt_to_phys_map.contains(virt)) { + bsl::error() << "virtual address " // -- + << virt // -- + << " was not obtained from" // -- + << " bf_mem_op_alloc_page" // -- + << " or " // -- + << " bf_mem_op_alloc_huge" // -- + << bsl::endl // -- + << bsl::here(); + + return bf_uint64_t::failure(); + } + + return m_virt_to_phys_map.at(virt); + } + + /// + /// @brief Performs a physical address to virtual address translation. + /// Note that this function only works on direct map memory, which + /// includes direct map addresses, allocated pages and allocated + /// huge memory. + /// + /// + /// @param phys the physical address to convert + /// @return Returns the resulting virtual address + /// + [[nodiscard]] constexpr auto + bf_phys_to_virt(bf_uint64_t const &phys) const noexcept -> void * + { + if (bsl::unlikely(!phys)) { + bsl::error() << "invalid phys\n" << bsl::here(); + return nullptr; + } + + if (bsl::unlikely(phys.is_zero())) { + bsl::error() << "phys is a nullptr\n" << bsl::here(); + return nullptr; + } + + /// NOTE: + /// - If you get this error message, it is because your code + /// does not adhere to the ABI. Virt to phys conversions are + /// only supported for memory that is allocated using + /// bf_mem_op_alloc_page and bf_mem_op_alloc_huge. We added this + /// extra check for sanity to help ensure the ABI is being + /// adhered to as the regular code doesn't keep track of this + /// which could result in UB. + /// + + if (!m_phys_to_virt_map.contains(phys)) { + bsl::error() << "physical address " // -- + << phys // -- + << " was not reserved using" // -- + << " bf_mem_op_alloc_page" // -- + << " or " // -- + << " bf_mem_op_alloc_huge" // -- + << bsl::endl // -- + << bsl::here(); + + return nullptr; + } + + return m_phys_to_virt_map.at(phys); + } + }; +} + +#endif diff --git a/syscall/src/arm/aarch64/bf_callback_op_register_bootstrap_impl.S b/syscall/src/arm/aarch64/bf_callback_op_register_bootstrap_impl.S new file mode 100644 index 00000000..6f89c84e --- /dev/null +++ b/syscall/src/arm/aarch64/bf_callback_op_register_bootstrap_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_callback_op_register_bootstrap_impl + .type bf_callback_op_register_bootstrap_impl, @function +bf_callback_op_register_bootstrap_impl: + +/* + mov rax, 0x6642000000030002 + syscall +*/ + + ret + + .size bf_callback_op_register_bootstrap_impl, .-bf_callback_op_register_bootstrap_impl diff --git a/syscall/src/arm/aarch64/bf_callback_op_register_fail_impl.S b/syscall/src/arm/aarch64/bf_callback_op_register_fail_impl.S new file mode 100644 index 00000000..11733124 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_callback_op_register_fail_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_callback_op_register_fail_impl + .type bf_callback_op_register_fail_impl, @function +bf_callback_op_register_fail_impl: + +/* + mov rax, 0x6642000000030004 + syscall +*/ + + ret + + .size bf_callback_op_register_fail_impl, .-bf_callback_op_register_fail_impl diff --git a/syscall/src/arm/aarch64/bf_callback_op_register_vmexit_impl.S b/syscall/src/arm/aarch64/bf_callback_op_register_vmexit_impl.S new file mode 100644 index 00000000..4f60283a --- /dev/null +++ b/syscall/src/arm/aarch64/bf_callback_op_register_vmexit_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_callback_op_register_vmexit_impl + .type bf_callback_op_register_vmexit_impl, @function +bf_callback_op_register_vmexit_impl: + +/* + mov rax, 0x6642000000030003 + syscall +*/ + + ret + + .size bf_callback_op_register_vmexit_impl, .-bf_callback_op_register_vmexit_impl diff --git a/syscall/src/arm/aarch64/bf_control_op_exit_impl.S b/syscall/src/arm/aarch64/bf_control_op_exit_impl.S new file mode 100644 index 00000000..c1afc3c8 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_control_op_exit_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_control_op_exit_impl + .type bf_control_op_exit_impl, @function +bf_control_op_exit_impl: + +/* + mov rax, 0x6642000000000000 + syscall +*/ + + ret + + .size bf_control_op_exit_impl, .-bf_control_op_exit_impl diff --git a/syscall/src/arm/aarch64/bf_control_op_wait_impl.S b/syscall/src/arm/aarch64/bf_control_op_wait_impl.S new file mode 100644 index 00000000..7bb7a49f --- /dev/null +++ b/syscall/src/arm/aarch64/bf_control_op_wait_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_control_op_wait_impl + .type bf_control_op_wait_impl, @function +bf_control_op_wait_impl: + +/* + mov rax, 0x6642000000000001 + syscall +*/ + + ret + + .size bf_control_op_wait_impl, .-bf_control_op_wait_impl diff --git a/syscall/src/arm/aarch64/bf_debug_op_dump_ext_impl.S b/syscall/src/arm/aarch64/bf_debug_op_dump_ext_impl.S new file mode 100644 index 00000000..b0046517 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_debug_op_dump_ext_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_debug_op_dump_ext_impl + .type bf_debug_op_dump_ext_impl, @function +bf_debug_op_dump_ext_impl: + +/* + mov rax, 0x6642000000020007 + syscall +*/ + + ret + + .size bf_debug_op_dump_ext_impl, .-bf_debug_op_dump_ext_impl diff --git a/syscall/src/arm/aarch64/bf_debug_op_dump_huge_pool_impl.S b/syscall/src/arm/aarch64/bf_debug_op_dump_huge_pool_impl.S new file mode 100644 index 00000000..fbc439d0 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_debug_op_dump_huge_pool_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_debug_op_dump_huge_pool_impl + .type bf_debug_op_dump_huge_pool_impl, @function +bf_debug_op_dump_huge_pool_impl: + +/* + mov rax, 0x6642000000020009 + syscall +*/ + + ret + + .size bf_debug_op_dump_huge_pool_impl, .-bf_debug_op_dump_huge_pool_impl diff --git a/syscall/src/arm/aarch64/bf_debug_op_dump_page_pool_impl.S b/syscall/src/arm/aarch64/bf_debug_op_dump_page_pool_impl.S new file mode 100644 index 00000000..66c193da --- /dev/null +++ b/syscall/src/arm/aarch64/bf_debug_op_dump_page_pool_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_debug_op_dump_page_pool_impl + .type bf_debug_op_dump_page_pool_impl, @function +bf_debug_op_dump_page_pool_impl: + +/* + mov rax, 0x6642000000020008 + syscall +*/ + + ret + + .size bf_debug_op_dump_page_pool_impl, .-bf_debug_op_dump_page_pool_impl diff --git a/syscall/src/arm/aarch64/bf_debug_op_dump_vm_impl.S b/syscall/src/arm/aarch64/bf_debug_op_dump_vm_impl.S new file mode 100644 index 00000000..a3141332 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_debug_op_dump_vm_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_debug_op_dump_vm_impl + .type bf_debug_op_dump_vm_impl, @function +bf_debug_op_dump_vm_impl: + +/* + mov rax, 0x6642000000020001 + syscall +*/ + + ret + + .size bf_debug_op_dump_vm_impl, .-bf_debug_op_dump_vm_impl diff --git a/syscall/src/arm/aarch64/bf_debug_op_dump_vmexit_log_impl.S b/syscall/src/arm/aarch64/bf_debug_op_dump_vmexit_log_impl.S new file mode 100644 index 00000000..6c044c11 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_debug_op_dump_vmexit_log_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_debug_op_dump_vmexit_log_impl + .type bf_debug_op_dump_vmexit_log_impl, @function +bf_debug_op_dump_vmexit_log_impl: + +/* + mov rax, 0x6642000000020004 + syscall +*/ + + ret + + .size bf_debug_op_dump_vmexit_log_impl, .-bf_debug_op_dump_vmexit_log_impl diff --git a/syscall/src/arm/aarch64/bf_debug_op_dump_vp_impl.S b/syscall/src/arm/aarch64/bf_debug_op_dump_vp_impl.S new file mode 100644 index 00000000..96dde37b --- /dev/null +++ b/syscall/src/arm/aarch64/bf_debug_op_dump_vp_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_debug_op_dump_vp_impl + .type bf_debug_op_dump_vp_impl, @function +bf_debug_op_dump_vp_impl: + +/* + mov rax, 0x6642000000020002 + syscall +*/ + + ret + + .size bf_debug_op_dump_vp_impl, .-bf_debug_op_dump_vp_impl diff --git a/syscall/src/arm/aarch64/bf_debug_op_dump_vps_impl.S b/syscall/src/arm/aarch64/bf_debug_op_dump_vps_impl.S new file mode 100644 index 00000000..29063bf6 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_debug_op_dump_vps_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_debug_op_dump_vps_impl + .type bf_debug_op_dump_vps_impl, @function +bf_debug_op_dump_vps_impl: + +/* + mov rax, 0x6642000000020003 + syscall +*/ + + ret + + .size bf_debug_op_dump_vps_impl, .-bf_debug_op_dump_vps_impl diff --git a/syscall/src/arm/aarch64/bf_debug_op_out_impl.S b/syscall/src/arm/aarch64/bf_debug_op_out_impl.S new file mode 100644 index 00000000..67765c65 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_debug_op_out_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_debug_op_out_impl + .type bf_debug_op_out_impl, @function +bf_debug_op_out_impl: + +/* + mov rax, 0x6642000000020000 + syscall +*/ + + ret + + .size bf_debug_op_out_impl, .-bf_debug_op_out_impl diff --git a/syscall/src/arm/aarch64/bf_debug_op_write_c_impl.S b/syscall/src/arm/aarch64/bf_debug_op_write_c_impl.S new file mode 100644 index 00000000..21740361 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_debug_op_write_c_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_debug_op_write_c_impl + .type bf_debug_op_write_c_impl, @function +bf_debug_op_write_c_impl: + +/* + mov rax, 0x6642000000020005 + syscall +*/ + + ret + + .size bf_debug_op_write_c_impl, .-bf_debug_op_write_c_impl diff --git a/syscall/src/arm/aarch64/bf_debug_op_write_str_impl.S b/syscall/src/arm/aarch64/bf_debug_op_write_str_impl.S new file mode 100644 index 00000000..eabf08af --- /dev/null +++ b/syscall/src/arm/aarch64/bf_debug_op_write_str_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_debug_op_write_str_impl + .type bf_debug_op_write_str_impl, @function +bf_debug_op_write_str_impl: + +/* + mov rax, 0x6642000000020006 + syscall +*/ + + ret + + .size bf_debug_op_write_str_impl, .-bf_debug_op_write_str_impl diff --git a/syscall/src/arm/aarch64/bf_handle_op_close_handle_impl.S b/syscall/src/arm/aarch64/bf_handle_op_close_handle_impl.S new file mode 100644 index 00000000..ccb8badc --- /dev/null +++ b/syscall/src/arm/aarch64/bf_handle_op_close_handle_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_handle_op_close_handle_impl + .type bf_handle_op_close_handle_impl, @function +bf_handle_op_close_handle_impl: + +/* + mov rax, 0x6642000000010001 + syscall +*/ + + ret + + .size bf_handle_op_close_handle_impl, .-bf_handle_op_close_handle_impl diff --git a/syscall/src/arm/aarch64/bf_handle_op_open_handle_impl.S b/syscall/src/arm/aarch64/bf_handle_op_open_handle_impl.S new file mode 100644 index 00000000..9a20c9e7 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_handle_op_open_handle_impl.S @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_handle_op_open_handle_impl + .type bf_handle_op_open_handle_impl, @function +bf_handle_op_open_handle_impl: + +/* + mov rax, 0x6642000000010000 + syscall + + mov [rsi], rdi +*/ + + ret + + .size bf_handle_op_open_handle_impl, .-bf_handle_op_open_handle_impl diff --git a/syscall/src/arm/aarch64/bf_intrinsic_op_invept_impl.S b/syscall/src/arm/aarch64/bf_intrinsic_op_invept_impl.S new file mode 100644 index 00000000..b23c3dac --- /dev/null +++ b/syscall/src/arm/aarch64/bf_intrinsic_op_invept_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_intrinsic_op_invept_impl + .type bf_intrinsic_op_invept_impl, @function +bf_intrinsic_op_invept_impl: + +/* + mov rax, 0x6642000000070003 + syscall +*/ + + ret + + .size bf_intrinsic_op_invept_impl, .-bf_intrinsic_op_invept_impl diff --git a/syscall/src/arm/aarch64/bf_intrinsic_op_invlpga_impl.S b/syscall/src/arm/aarch64/bf_intrinsic_op_invlpga_impl.S new file mode 100644 index 00000000..0bd96a68 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_intrinsic_op_invlpga_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_intrinsic_op_invlpga_impl + .type bf_intrinsic_op_invlpga_impl, @function +bf_intrinsic_op_invlpga_impl: + +/* + mov rax, 0x6642000000070002 + syscall +*/ + + ret + + .size bf_intrinsic_op_invlpga_impl, .-bf_intrinsic_op_invlpga_impl diff --git a/syscall/src/arm/aarch64/bf_intrinsic_op_invvpid_impl.S b/syscall/src/arm/aarch64/bf_intrinsic_op_invvpid_impl.S new file mode 100644 index 00000000..c7372d00 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_intrinsic_op_invvpid_impl.S @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_intrinsic_op_invvpid_impl + .type bf_intrinsic_op_invvpid_impl, @function +bf_intrinsic_op_invvpid_impl: + +/* + mov r10, rcx + + mov rax, 0x6642000000070004 + syscall +*/ + + ret + + .size bf_intrinsic_op_invvpid_impl, .-bf_intrinsic_op_invvpid_impl diff --git a/syscall/src/arm/aarch64/bf_intrinsic_op_rdmsr_impl.S b/syscall/src/arm/aarch64/bf_intrinsic_op_rdmsr_impl.S new file mode 100644 index 00000000..f04a6399 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_intrinsic_op_rdmsr_impl.S @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_intrinsic_op_rdmsr_impl + .type bf_intrinsic_op_rdmsr_impl, @function +bf_intrinsic_op_rdmsr_impl: + +/* + mov rax, 0x6642000000070000 + syscall + + mov [rdx], rdi +*/ + + ret + + .size bf_intrinsic_op_rdmsr_impl, .-bf_intrinsic_op_rdmsr_impl diff --git a/syscall/src/arm/aarch64/bf_intrinsic_op_wrmsr_impl.S b/syscall/src/arm/aarch64/bf_intrinsic_op_wrmsr_impl.S new file mode 100644 index 00000000..c8092d37 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_intrinsic_op_wrmsr_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_intrinsic_op_wrmsr_impl + .type bf_intrinsic_op_wrmsr_impl, @function +bf_intrinsic_op_wrmsr_impl: + +/* + mov rax, 0x6642000000070001 + syscall +*/ + + ret + + .size bf_intrinsic_op_wrmsr_impl, .-bf_intrinsic_op_wrmsr_impl diff --git a/syscall/src/arm/aarch64/bf_mem_op_alloc_heap_impl.S b/syscall/src/arm/aarch64/bf_mem_op_alloc_heap_impl.S new file mode 100644 index 00000000..14c62bb8 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_mem_op_alloc_heap_impl.S @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_mem_op_alloc_heap_impl + .type bf_mem_op_alloc_heap_impl, @function +bf_mem_op_alloc_heap_impl: + +/* + mov rax, 0x6642000000080004 + syscall + + mov [rdx], rdi +*/ + + ret + + .size bf_mem_op_alloc_heap_impl, .-bf_mem_op_alloc_heap_impl diff --git a/syscall/src/arm/aarch64/bf_mem_op_alloc_huge_impl.S b/syscall/src/arm/aarch64/bf_mem_op_alloc_huge_impl.S new file mode 100644 index 00000000..a3cd7289 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_mem_op_alloc_huge_impl.S @@ -0,0 +1,45 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_mem_op_alloc_huge_impl + .type bf_mem_op_alloc_huge_impl, @function +bf_mem_op_alloc_huge_impl: + +/* + mov r10, rcx + + mov rax, 0x6642000000080002 + syscall + + mov [rdx], rdi + mov [r10], rsi +*/ + + ret + + .size bf_mem_op_alloc_huge_impl, .-bf_mem_op_alloc_huge_impl diff --git a/syscall/src/arm/aarch64/bf_mem_op_alloc_page_impl.S b/syscall/src/arm/aarch64/bf_mem_op_alloc_page_impl.S new file mode 100644 index 00000000..f0880f90 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_mem_op_alloc_page_impl.S @@ -0,0 +1,45 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_mem_op_alloc_page_impl + .type bf_mem_op_alloc_page_impl, @function +bf_mem_op_alloc_page_impl: + +/* + mov r10, rsi + + mov rax, 0x6642000000080000 + syscall + + mov [r10], rdi + mov [rdx], rsi +*/ + + ret + + .size bf_mem_op_alloc_page_impl, .-bf_mem_op_alloc_page_impl diff --git a/syscall/src/arm/aarch64/bf_mem_op_free_huge_impl.S b/syscall/src/arm/aarch64/bf_mem_op_free_huge_impl.S new file mode 100644 index 00000000..c5fe68e7 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_mem_op_free_huge_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_mem_op_free_huge_impl + .type bf_mem_op_free_huge_impl, @function +bf_mem_op_free_huge_impl: + +/* + mov rax, 0x6642000000080003 + syscall +*/ + + ret + + .size bf_mem_op_free_huge_impl, .-bf_mem_op_free_huge_impl diff --git a/syscall/src/arm/aarch64/bf_mem_op_free_page_impl.S b/syscall/src/arm/aarch64/bf_mem_op_free_page_impl.S new file mode 100644 index 00000000..d0894ee2 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_mem_op_free_page_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_mem_op_free_page_impl + .type bf_mem_op_free_page_impl, @function +bf_mem_op_free_page_impl: + +/* + mov rax, 0x6642000000080001 + syscall +*/ + + ret + + .size bf_mem_op_free_page_impl, .-bf_mem_op_free_page_impl diff --git a/syscall/src/arm/aarch64/bf_tls_extid_impl.S b/syscall/src/arm/aarch64/bf_tls_extid_impl.S new file mode 100644 index 00000000..231865d5 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_extid_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_extid_impl + .type bf_tls_extid_impl, @function +bf_tls_extid_impl: + +/* + xor rax, rax + mov ax, fs:[0xFF0] +*/ + + ret + + .size bf_tls_extid_impl, .-bf_tls_extid_impl diff --git a/syscall/src/arm/aarch64/bf_tls_online_pps_impl.S b/syscall/src/arm/aarch64/bf_tls_online_pps_impl.S new file mode 100644 index 00000000..72e304b6 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_online_pps_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_ppid_impl + .type bf_tls_ppid_impl, @function +bf_tls_ppid_impl: + +/* + xor rax, rax + mov ax, fs:[0xFF8] +*/ + + ret + + .size bf_tls_ppid_impl, .-bf_tls_ppid_impl diff --git a/syscall/src/arm/aarch64/bf_tls_ppid_impl.S b/syscall/src/arm/aarch64/bf_tls_ppid_impl.S new file mode 100644 index 00000000..94e2a3b4 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_ppid_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_online_pps_impl + .type bf_tls_online_pps_impl, @function +bf_tls_online_pps_impl: + +/* + xor rax, rax + mov ax, fs:[0xFFA] +*/ + + ret + + .size bf_tls_online_pps_impl, .-bf_tls_online_pps_impl diff --git a/syscall/src/arm/aarch64/bf_tls_r10_impl.S b/syscall/src/arm/aarch64/bf_tls_r10_impl.S new file mode 100644 index 00000000..cd5a5471 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_r10_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_r10_impl + .type bf_tls_r10_impl, @function +bf_tls_r10_impl: + +/* + mov rax, fs:[0x848] +*/ + ret + + .size bf_tls_r10_impl, .-bf_tls_r10_impl diff --git a/syscall/src/arm/aarch64/bf_tls_r11_impl.S b/syscall/src/arm/aarch64/bf_tls_r11_impl.S new file mode 100644 index 00000000..47b44000 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_r11_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_r11_impl + .type bf_tls_r11_impl, @function +bf_tls_r11_impl: + +/* + mov rax, fs:[0x850] +*/ + ret + + .size bf_tls_r11_impl, .-bf_tls_r11_impl diff --git a/syscall/src/arm/aarch64/bf_tls_r12_impl.S b/syscall/src/arm/aarch64/bf_tls_r12_impl.S new file mode 100644 index 00000000..74db50d3 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_r12_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_r12_impl + .type bf_tls_r12_impl, @function +bf_tls_r12_impl: + +/* + mov rax, fs:[0x858] +*/ + ret + + .size bf_tls_r12_impl, .-bf_tls_r12_impl diff --git a/syscall/src/arm/aarch64/bf_tls_r13_impl.S b/syscall/src/arm/aarch64/bf_tls_r13_impl.S new file mode 100644 index 00000000..9efcd6b9 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_r13_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_r13_impl + .type bf_tls_r13_impl, @function +bf_tls_r13_impl: + +/* + mov rax, fs:[0x860] +*/ + ret + + .size bf_tls_r13_impl, .-bf_tls_r13_impl diff --git a/syscall/src/arm/aarch64/bf_tls_r14_impl.S b/syscall/src/arm/aarch64/bf_tls_r14_impl.S new file mode 100644 index 00000000..fbff5fd2 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_r14_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_r14_impl + .type bf_tls_r14_impl, @function +bf_tls_r14_impl: + +/* + mov rax, fs:[0x868] +*/ + ret + + .size bf_tls_r14_impl, .-bf_tls_r14_impl diff --git a/syscall/src/arm/aarch64/bf_tls_r15_impl.S b/syscall/src/arm/aarch64/bf_tls_r15_impl.S new file mode 100644 index 00000000..6caa5ab3 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_r15_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_r15_impl + .type bf_tls_r15_impl, @function +bf_tls_r15_impl: + +/* + mov rax, fs:[0x870] +*/ + ret + + .size bf_tls_r15_impl, .-bf_tls_r15_impl diff --git a/syscall/src/arm/aarch64/bf_tls_r8_impl.S b/syscall/src/arm/aarch64/bf_tls_r8_impl.S new file mode 100644 index 00000000..56b6fe1e --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_r8_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_r8_impl + .type bf_tls_r8_impl, @function +bf_tls_r8_impl: + +/* + mov rax, fs:[0x838] +*/ + ret + + .size bf_tls_r8_impl, .-bf_tls_r8_impl diff --git a/syscall/src/arm/aarch64/bf_tls_r9_impl.S b/syscall/src/arm/aarch64/bf_tls_r9_impl.S new file mode 100644 index 00000000..1bbbe1f1 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_r9_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_r9_impl + .type bf_tls_r9_impl, @function +bf_tls_r9_impl: + +/* + mov rax, fs:[0x840] +*/ + ret + + .size bf_tls_r9_impl, .-bf_tls_r9_impl diff --git a/syscall/src/arm/aarch64/bf_tls_rax_impl.S b/syscall/src/arm/aarch64/bf_tls_rax_impl.S new file mode 100644 index 00000000..efb1403f --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_rax_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_rax_impl + .type bf_tls_rax_impl, @function +bf_tls_rax_impl: + +/* + mov rax, fs:[0x800] +*/ + ret + + .size bf_tls_rax_impl, .-bf_tls_rax_impl diff --git a/syscall/src/arm/aarch64/bf_tls_rbp_impl.S b/syscall/src/arm/aarch64/bf_tls_rbp_impl.S new file mode 100644 index 00000000..8450d254 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_rbp_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_rbp_impl + .type bf_tls_rbp_impl, @function +bf_tls_rbp_impl: + +/* + mov rax, fs:[0x820] +*/ + ret + + .size bf_tls_rbp_impl, .-bf_tls_rbp_impl diff --git a/syscall/src/arm/aarch64/bf_tls_rbx_impl.S b/syscall/src/arm/aarch64/bf_tls_rbx_impl.S new file mode 100644 index 00000000..464a5570 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_rbx_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_rbx_impl + .type bf_tls_rbx_impl, @function +bf_tls_rbx_impl: + +/* + mov rax, fs:[0x808] +*/ + ret + + .size bf_tls_rbx_impl, .-bf_tls_rbx_impl diff --git a/syscall/src/arm/aarch64/bf_tls_rcx_impl.S b/syscall/src/arm/aarch64/bf_tls_rcx_impl.S new file mode 100644 index 00000000..83cae0dd --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_rcx_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_rcx_impl + .type bf_tls_rcx_impl, @function +bf_tls_rcx_impl: + +/* + mov rax, fs:[0x810] +*/ + ret + + .size bf_tls_rcx_impl, .-bf_tls_rcx_impl diff --git a/syscall/src/arm/aarch64/bf_tls_rdi_impl.S b/syscall/src/arm/aarch64/bf_tls_rdi_impl.S new file mode 100644 index 00000000..8aa8ed36 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_rdi_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_rdi_impl + .type bf_tls_rdi_impl, @function +bf_tls_rdi_impl: + +/* + mov rax, fs:[0x830] +*/ + ret + + .size bf_tls_rdi_impl, .-bf_tls_rdi_impl diff --git a/syscall/src/arm/aarch64/bf_tls_rdx_impl.S b/syscall/src/arm/aarch64/bf_tls_rdx_impl.S new file mode 100644 index 00000000..cb746a27 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_rdx_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_rdx_impl + .type bf_tls_rdx_impl, @function +bf_tls_rdx_impl: + +/* + mov rax, fs:[0x818] +*/ + ret + + .size bf_tls_rdx_impl, .-bf_tls_rdx_impl diff --git a/syscall/src/arm/aarch64/bf_tls_rsi_impl.S b/syscall/src/arm/aarch64/bf_tls_rsi_impl.S new file mode 100644 index 00000000..6f948ebf --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_rsi_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_rsi_impl + .type bf_tls_rsi_impl, @function +bf_tls_rsi_impl: + +/* + mov rax, fs:[0x828] +*/ + ret + + .size bf_tls_rsi_impl, .-bf_tls_rsi_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_r10_impl.S b/syscall/src/arm/aarch64/bf_tls_set_r10_impl.S new file mode 100644 index 00000000..ebc75a88 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_r10_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_r10_impl + .type bf_tls_set_r10_impl, @function +bf_tls_set_r10_impl: + +/* + mov fs:[0x848], rdi +*/ + ret + + .size bf_tls_set_r10_impl, .-bf_tls_set_r10_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_r11_impl.S b/syscall/src/arm/aarch64/bf_tls_set_r11_impl.S new file mode 100644 index 00000000..c6a92a6c --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_r11_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_r11_impl + .type bf_tls_set_r11_impl, @function +bf_tls_set_r11_impl: + +/* + mov fs:[0x850], rdi +*/ + ret + + .size bf_tls_set_r11_impl, .-bf_tls_set_r11_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_r12_impl.S b/syscall/src/arm/aarch64/bf_tls_set_r12_impl.S new file mode 100644 index 00000000..45d272c1 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_r12_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_r12_impl + .type bf_tls_set_r12_impl, @function +bf_tls_set_r12_impl: + +/* + mov fs:[0x858], rdi +*/ + ret + + .size bf_tls_set_r12_impl, .-bf_tls_set_r12_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_r13_impl.S b/syscall/src/arm/aarch64/bf_tls_set_r13_impl.S new file mode 100644 index 00000000..8fb9c492 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_r13_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_r13_impl + .type bf_tls_set_r13_impl, @function +bf_tls_set_r13_impl: + +/* + mov fs:[0x860], rdi +*/ + ret + + .size bf_tls_set_r13_impl, .-bf_tls_set_r13_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_r14_impl.S b/syscall/src/arm/aarch64/bf_tls_set_r14_impl.S new file mode 100644 index 00000000..19373f6e --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_r14_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_r14_impl + .type bf_tls_set_r14_impl, @function +bf_tls_set_r14_impl: + +/* + mov fs:[0x868], rdi +*/ + ret + + .size bf_tls_set_r14_impl, .-bf_tls_set_r14_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_r15_impl.S b/syscall/src/arm/aarch64/bf_tls_set_r15_impl.S new file mode 100644 index 00000000..99c7e94c --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_r15_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_r15_impl + .type bf_tls_set_r15_impl, @function +bf_tls_set_r15_impl: + +/* + mov fs:[0x870], rdi +*/ + ret + + .size bf_tls_set_r15_impl, .-bf_tls_set_r15_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_r8_impl.S b/syscall/src/arm/aarch64/bf_tls_set_r8_impl.S new file mode 100644 index 00000000..28006f30 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_r8_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_r8_impl + .type bf_tls_set_r8_impl, @function +bf_tls_set_r8_impl: + +/* + mov fs:[0x838], rdi +*/ + ret + + .size bf_tls_set_r8_impl, .-bf_tls_set_r8_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_r9_impl.S b/syscall/src/arm/aarch64/bf_tls_set_r9_impl.S new file mode 100644 index 00000000..7cb0f016 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_r9_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_r9_impl + .type bf_tls_set_r9_impl, @function +bf_tls_set_r9_impl: + +/* + mov fs:[0x840], rdi +*/ + ret + + .size bf_tls_set_r9_impl, .-bf_tls_set_r9_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_rax_impl.S b/syscall/src/arm/aarch64/bf_tls_set_rax_impl.S new file mode 100644 index 00000000..ac519375 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_rax_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_rax_impl + .type bf_tls_set_rax_impl, @function +bf_tls_set_rax_impl: + +/* + mov fs:[0x800], rdi +*/ + ret + + .size bf_tls_set_rax_impl, .-bf_tls_set_rax_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_rbp_impl.S b/syscall/src/arm/aarch64/bf_tls_set_rbp_impl.S new file mode 100644 index 00000000..d8f2bea8 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_rbp_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_rbp_impl + .type bf_tls_set_rbp_impl, @function +bf_tls_set_rbp_impl: + +/* + mov fs:[0x820], rdi +*/ + ret + + .size bf_tls_set_rbp_impl, .-bf_tls_set_rbp_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_rbx_impl.S b/syscall/src/arm/aarch64/bf_tls_set_rbx_impl.S new file mode 100644 index 00000000..62c9fbc0 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_rbx_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_rbx_impl + .type bf_tls_set_rbx_impl, @function +bf_tls_set_rbx_impl: + +/* + mov fs:[0x808], rdi +*/ + ret + + .size bf_tls_set_rbx_impl, .-bf_tls_set_rbx_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_rcx_impl.S b/syscall/src/arm/aarch64/bf_tls_set_rcx_impl.S new file mode 100644 index 00000000..692ed7af --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_rcx_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_rcx_impl + .type bf_tls_set_rcx_impl, @function +bf_tls_set_rcx_impl: + +/* + mov fs:[0x810], rdi +*/ + ret + + .size bf_tls_set_rcx_impl, .-bf_tls_set_rcx_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_rdi_impl.S b/syscall/src/arm/aarch64/bf_tls_set_rdi_impl.S new file mode 100644 index 00000000..f3ba875f --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_rdi_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_rdi_impl + .type bf_tls_set_rdi_impl, @function +bf_tls_set_rdi_impl: + +/* + mov fs:[0x830], rdi +*/ + ret + + .size bf_tls_set_rdi_impl, .-bf_tls_set_rdi_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_rdx_impl.S b/syscall/src/arm/aarch64/bf_tls_set_rdx_impl.S new file mode 100644 index 00000000..dbc1046a --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_rdx_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_rdx_impl + .type bf_tls_set_rdx_impl, @function +bf_tls_set_rdx_impl: + +/* + mov fs:[0x818], rdi +*/ + ret + + .size bf_tls_set_rdx_impl, .-bf_tls_set_rdx_impl diff --git a/syscall/src/arm/aarch64/bf_tls_set_rsi_impl.S b/syscall/src/arm/aarch64/bf_tls_set_rsi_impl.S new file mode 100644 index 00000000..6675db61 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_set_rsi_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_set_rsi_impl + .type bf_tls_set_rsi_impl, @function +bf_tls_set_rsi_impl: + +/* + mov fs:[0x828], rdi +*/ + ret + + .size bf_tls_set_rsi_impl, .-bf_tls_set_rsi_impl diff --git a/syscall/src/arm/aarch64/bf_tls_thread_id_impl.S b/syscall/src/arm/aarch64/bf_tls_thread_id_impl.S new file mode 100644 index 00000000..89af6b9c --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_thread_id_impl.S @@ -0,0 +1,38 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_thread_id_impl + .type bf_tls_thread_id_impl, @function +bf_tls_thread_id_impl: + +/* + mov rax, fs:[0xFF8] +*/ + ret + + .size bf_tls_thread_id_impl, .-bf_tls_thread_id_impl diff --git a/syscall/src/arm/aarch64/bf_tls_vmid_impl.S b/syscall/src/arm/aarch64/bf_tls_vmid_impl.S new file mode 100644 index 00000000..bc9df318 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_vmid_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_vmid_impl + .type bf_tls_vmid_impl, @function +bf_tls_vmid_impl: + +/* + xor rax, rax + mov ax, fs:[0xFF2] +*/ + + ret + + .size bf_tls_vmid_impl, .-bf_tls_vmid_impl diff --git a/syscall/src/arm/aarch64/bf_tls_vpid_impl.S b/syscall/src/arm/aarch64/bf_tls_vpid_impl.S new file mode 100644 index 00000000..fa43a6c9 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_vpid_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_vpid_impl + .type bf_tls_vpid_impl, @function +bf_tls_vpid_impl: + +/* + xor rax, rax + mov ax, fs:[0xFF4] +*/ + ret + + .size bf_tls_vpid_impl, .-bf_tls_vpid_impl diff --git a/syscall/src/arm/aarch64/bf_tls_vpsid_impl.S b/syscall/src/arm/aarch64/bf_tls_vpsid_impl.S new file mode 100644 index 00000000..dca781e5 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_tls_vpsid_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_tls_vpsid_impl + .type bf_tls_vpsid_impl, @function +bf_tls_vpsid_impl: + +/* + xor rax, rax + mov ax, fs:[0xFF6] +*/ + ret + + .size bf_tls_vpsid_impl, .-bf_tls_vpsid_impl diff --git a/syscall/src/arm/aarch64/bf_vm_op_create_vm_impl.S b/syscall/src/arm/aarch64/bf_vm_op_create_vm_impl.S new file mode 100644 index 00000000..693f6833 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vm_op_create_vm_impl.S @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vm_op_create_vm_impl + .type bf_vm_op_create_vm_impl, @function +bf_vm_op_create_vm_impl: + +/* + mov rax, 0x6642000000040000 + syscall + + mov [rsi], di +*/ + ret + + .size bf_vm_op_create_vm_impl, .-bf_vm_op_create_vm_impl diff --git a/syscall/src/arm/aarch64/bf_vm_op_destroy_vm_impl.S b/syscall/src/arm/aarch64/bf_vm_op_destroy_vm_impl.S new file mode 100644 index 00000000..9c514caa --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vm_op_destroy_vm_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vm_op_destroy_vm_impl + .type bf_vm_op_destroy_vm_impl, @function +bf_vm_op_destroy_vm_impl: + +/* + mov rax, 0x6642000000040001 + syscall +*/ + ret + + .size bf_vm_op_destroy_vm_impl, .-bf_vm_op_destroy_vm_impl diff --git a/syscall/src/arm/aarch64/bf_vp_op_create_vp_impl.S b/syscall/src/arm/aarch64/bf_vp_op_create_vp_impl.S new file mode 100644 index 00000000..03ef302f --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vp_op_create_vp_impl.S @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vp_op_create_vp_impl + .type bf_vp_op_create_vp_impl, @function +bf_vp_op_create_vp_impl: + +/* + mov r10, rcx + + mov rax, 0x6642000000050000 + syscall + + mov [r10], di +*/ + ret + + .size bf_vp_op_create_vp_impl, .-bf_vp_op_create_vp_impl diff --git a/syscall/src/arm/aarch64/bf_vp_op_destroy_vp_impl.S b/syscall/src/arm/aarch64/bf_vp_op_destroy_vp_impl.S new file mode 100644 index 00000000..7be0dcd2 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vp_op_destroy_vp_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vp_op_destroy_vp_impl + .type bf_vp_op_destroy_vp_impl, @function +bf_vp_op_destroy_vp_impl: + +/* + mov rax, 0x6642000000050001 + syscall +*/ + ret + + .size bf_vp_op_destroy_vp_impl, .-bf_vp_op_destroy_vp_impl diff --git a/syscall/src/arm/aarch64/bf_vp_op_migrate_impl.S b/syscall/src/arm/aarch64/bf_vp_op_migrate_impl.S new file mode 100644 index 00000000..d5b0acb9 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vp_op_migrate_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vp_op_migrate_impl + .type bf_vp_op_migrate_impl, @function +bf_vp_op_migrate_impl: + +/* + mov rax, 0x6642000000050002 + syscall +*/ + ret + + .size bf_vp_op_migrate_impl, .-bf_vp_op_migrate_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_advance_ip_and_run_current_impl.S b/syscall/src/arm/aarch64/bf_vps_op_advance_ip_and_run_current_impl.S new file mode 100644 index 00000000..721ca70b --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_advance_ip_and_run_current_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_advance_ip_and_run_current_impl + .type bf_vps_op_advance_ip_and_run_current_impl, @function +bf_vps_op_advance_ip_and_run_current_impl: + +/* + mov rax, 0x6642000000060010 + syscall +*/ + ret + + .size bf_vps_op_advance_ip_and_run_current_impl, .-bf_vps_op_advance_ip_and_run_current_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_advance_ip_impl.S b/syscall/src/arm/aarch64/bf_vps_op_advance_ip_impl.S new file mode 100644 index 00000000..6e910766 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_advance_ip_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_advance_ip_impl + .type bf_vps_op_advance_ip_impl, @function +bf_vps_op_advance_ip_impl: + +/* + mov rax, 0x664200000006000F + syscall +*/ + ret + + .size bf_vps_op_advance_ip_impl, .-bf_vps_op_advance_ip_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_clear_vps_impl.S b/syscall/src/arm/aarch64/bf_vps_op_clear_vps_impl.S new file mode 100644 index 00000000..201bb4e3 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_clear_vps_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_clear_vps_impl + .type bf_vps_op_clear_vps_impl, @function +bf_vps_op_clear_vps_impl: + +/* + mov rax, 0x6642000000060012 + syscall +*/ + ret + + .size bf_vps_op_clear_vps_impl, .-bf_vps_op_clear_vps_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_create_vps_impl.S b/syscall/src/arm/aarch64/bf_vps_op_create_vps_impl.S new file mode 100644 index 00000000..197726e5 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_create_vps_impl.S @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_create_vps_impl + .type bf_vps_op_create_vps_impl, @function +bf_vps_op_create_vps_impl: + +/* + mov r10, rcx + + mov rax, 0x6642000000060000 + syscall + + mov [r10], di +*/ + ret + + .size bf_vps_op_create_vps_impl, .-bf_vps_op_create_vps_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_destroy_vps_impl.S b/syscall/src/arm/aarch64/bf_vps_op_destroy_vps_impl.S new file mode 100644 index 00000000..b3c144a1 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_destroy_vps_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_destroy_vps_impl + .type bf_vps_op_destroy_vps_impl, @function +bf_vps_op_destroy_vps_impl: + +/* + mov rax, 0x6642000000060001 + syscall +*/ + ret + + .size bf_vps_op_destroy_vps_impl, .-bf_vps_op_destroy_vps_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_init_as_root_impl.S b/syscall/src/arm/aarch64/bf_vps_op_init_as_root_impl.S new file mode 100644 index 00000000..88ec21a0 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_init_as_root_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_init_as_root_impl + .type bf_vps_op_init_as_root_impl, @function +bf_vps_op_init_as_root_impl: + +/* + mov rax, 0x6642000000060002 + syscall +*/ + ret + + .size bf_vps_op_init_as_root_impl, .-bf_vps_op_init_as_root_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_promote_impl.S b/syscall/src/arm/aarch64/bf_vps_op_promote_impl.S new file mode 100644 index 00000000..60626505 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_promote_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_promote_impl + .type bf_vps_op_promote_impl, @function +bf_vps_op_promote_impl: + +/* + mov rax, 0x6642000000060011 + syscall +*/ + ret + + .size bf_vps_op_promote_impl, .-bf_vps_op_promote_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_read16_impl.S b/syscall/src/arm/aarch64/bf_vps_op_read16_impl.S new file mode 100644 index 00000000..982dfacd --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_read16_impl.S @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_read16_impl + .type bf_vps_op_read16_impl, @function +bf_vps_op_read16_impl: + +/* + mov r10, rcx + + mov rax, 0x6642000000060004 + syscall + + mov [r10], di +*/ + ret + + .size bf_vps_op_read16_impl, .-bf_vps_op_read16_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_read32_impl.S b/syscall/src/arm/aarch64/bf_vps_op_read32_impl.S new file mode 100644 index 00000000..10695e18 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_read32_impl.S @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_read32_impl + .type bf_vps_op_read32_impl, @function +bf_vps_op_read32_impl: + +/* + mov r10, rcx + + mov rax, 0x6642000000060005 + syscall + + mov [r10], edi +*/ + ret + + .size bf_vps_op_read32_impl, .-bf_vps_op_read32_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_read64_impl.S b/syscall/src/arm/aarch64/bf_vps_op_read64_impl.S new file mode 100644 index 00000000..52ae9516 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_read64_impl.S @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_read64_impl + .type bf_vps_op_read64_impl, @function +bf_vps_op_read64_impl: + +/* + mov r10, rcx + + mov rax, 0x6642000000060006 + syscall + + mov [r10], rdi +*/ + ret + + .size bf_vps_op_read64_impl, .-bf_vps_op_read64_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_read8_impl.S b/syscall/src/arm/aarch64/bf_vps_op_read8_impl.S new file mode 100644 index 00000000..bcd77cda --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_read8_impl.S @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_read8_impl + .type bf_vps_op_read8_impl, @function +bf_vps_op_read8_impl: + +/* + mov r10, rcx + + mov rax, 0x6642000000060003 + syscall + + mov [r10], dil +*/ + ret + + .size bf_vps_op_read8_impl, .-bf_vps_op_read8_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_read_reg_impl.S b/syscall/src/arm/aarch64/bf_vps_op_read_reg_impl.S new file mode 100644 index 00000000..67678fe2 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_read_reg_impl.S @@ -0,0 +1,43 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_read_reg_impl + .type bf_vps_op_read_reg_impl, @function +bf_vps_op_read_reg_impl: + +/* + mov r10, rcx + + mov rax, 0x664200000006000B + syscall + + mov [r10], rdi +*/ + ret + + .size bf_vps_op_read_reg_impl, .-bf_vps_op_read_reg_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_run_current_impl.S b/syscall/src/arm/aarch64/bf_vps_op_run_current_impl.S new file mode 100644 index 00000000..44ce9b5e --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_run_current_impl.S @@ -0,0 +1,39 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_run_current_impl + .type bf_vps_op_run_current_impl, @function +bf_vps_op_run_current_impl: + +/* + mov rax, 0x664200000006000E + syscall +*/ + ret + + .size bf_vps_op_run_current_impl, .-bf_vps_op_run_current_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_run_impl.S b/syscall/src/arm/aarch64/bf_vps_op_run_impl.S new file mode 100644 index 00000000..3a9da433 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_run_impl.S @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_run_impl + .type bf_vps_op_run_impl, @function +bf_vps_op_run_impl: + +/* + mov r10, rcx + + mov rax, 0x664200000006000D + syscall +*/ + ret + + .size bf_vps_op_run_impl, .-bf_vps_op_run_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_write16_impl.S b/syscall/src/arm/aarch64/bf_vps_op_write16_impl.S new file mode 100644 index 00000000..0b074718 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_write16_impl.S @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_write16_impl + .type bf_vps_op_write16_impl, @function +bf_vps_op_write16_impl: + +/* + mov r10, rcx + + mov rax, 0x6642000000060008 + syscall +*/ + ret + + .size bf_vps_op_write16_impl, .-bf_vps_op_write16_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_write32_impl.S b/syscall/src/arm/aarch64/bf_vps_op_write32_impl.S new file mode 100644 index 00000000..0d0c2312 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_write32_impl.S @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_write32_impl + .type bf_vps_op_write32_impl, @function +bf_vps_op_write32_impl: + +/* + mov r10, rcx + + mov rax, 0x6642000000060009 + syscall +*/ + ret + + .size bf_vps_op_write32_impl, .-bf_vps_op_write32_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_write64_impl.S b/syscall/src/arm/aarch64/bf_vps_op_write64_impl.S new file mode 100644 index 00000000..bc4fc977 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_write64_impl.S @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_write64_impl + .type bf_vps_op_write64_impl, @function +bf_vps_op_write64_impl: + +/* + mov r10, rcx + + mov rax, 0x664200000006000A + syscall +*/ + ret + + .size bf_vps_op_write64_impl, .-bf_vps_op_write64_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_write8_impl.S b/syscall/src/arm/aarch64/bf_vps_op_write8_impl.S new file mode 100644 index 00000000..29668a20 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_write8_impl.S @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_write8_impl + .type bf_vps_op_write8_impl, @function +bf_vps_op_write8_impl: + +/* + mov r10, rcx + + mov rax, 0x6642000000060007 + syscall +*/ + ret + + .size bf_vps_op_write8_impl, .-bf_vps_op_write8_impl diff --git a/syscall/src/arm/aarch64/bf_vps_op_write_reg_impl.S b/syscall/src/arm/aarch64/bf_vps_op_write_reg_impl.S new file mode 100644 index 00000000..3239ae56 --- /dev/null +++ b/syscall/src/arm/aarch64/bf_vps_op_write_reg_impl.S @@ -0,0 +1,41 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .text + + .globl bf_vps_op_write_reg_impl + .type bf_vps_op_write_reg_impl, @function +bf_vps_op_write_reg_impl: + +/* + mov r10, rcx + + mov rax, 0x664200000006000C + syscall +*/ + ret + + .size bf_vps_op_write_reg_impl, .-bf_vps_op_write_reg_impl diff --git a/syscall/src/cpp/bf_control_ops.hpp b/syscall/src/cpp/bf_control_ops.hpp new file mode 100644 index 00000000..a0b2cbd5 --- /dev/null +++ b/syscall/src/cpp/bf_control_ops.hpp @@ -0,0 +1,65 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef BF_CONTROL_OPS_HPP +#define BF_CONTROL_OPS_HPP + +#include + +#include + +namespace syscall +{ + /// + /// @brief This syscall tells the microkernel to exit the execution + /// of an extension, providing a means to fast fail. + /// + constexpr void + bf_control_op_exit() noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_control_op_exit_impl(); + } + + /// + /// @brief This syscall tells the microkernel that the extension would + /// like to wait for a callback. This is a blocking syscall that never + /// returns and should be used to return from the successful execution + /// of the _start function. + /// + constexpr void + bf_control_op_wait() noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_control_op_wait_impl(); + } +} + +#endif diff --git a/syscall/src/cpp/bf_debug_ops.hpp b/syscall/src/cpp/bf_debug_ops.hpp new file mode 100644 index 00000000..a8eeac14 --- /dev/null +++ b/syscall/src/cpp/bf_debug_ops.hpp @@ -0,0 +1,211 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef BF_DEBUG_OPS_HPP +#define BF_DEBUG_OPS_HPP + +#include +#include + +#include +#include +#include + +namespace syscall +{ + /// + /// @brief This syscall tells the microkernel to output RDI and RSI to + /// the console device the microkernel is currently using for + /// debugging. + /// + /// + /// @param val1 The first value to output to the microkernel's console + /// @param val2 The second value to output to the microkernel's console + /// + constexpr void + bf_debug_op_out(bf_uint64_t const &val1, bf_uint64_t const &val2) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_out_impl(val1.get(), val2.get()); + } + + /// + /// @brief This syscall tells the microkernel to output the state of a + /// VM to the console device the microkernel is currently using for + /// debugging. + /// + /// + /// @param vmid The VMID of the VM whose state is to be outputted + /// + constexpr void + bf_debug_op_dump_vm(bf_uint16_t const &vmid) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_vm_impl(vmid.get()); + } + + /// + /// @brief This syscall tells the microkernel to output the state of a + /// VP to the console device the microkernel is currently using for + /// debugging. + /// + /// + /// @param vpid The VPID of the VP whose state is to be outputted + /// + constexpr void + bf_debug_op_dump_vp(bf_uint16_t const &vpid) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_vp_impl(vpid.get()); + } + + /// + /// @brief This syscall tells the microkernel to output the state of a + /// VPS to the console device the microkernel is currently using for + /// debugging. + /// + /// + /// @param vpsid The VPSID of the VPS whose state is to be outputted + /// + constexpr void + bf_debug_op_dump_vps(bf_uint16_t const &vpsid) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_vps_impl(vpsid.get()); + } + + /// + /// @brief This syscall tells the microkernel to output the VMExit log. + /// The VMExit log is a chronological log of the "X" number of exits + /// that have occurred on a specific physical processor. + /// + /// + /// @param ppid The PPID of the PP to dump the log from + /// + constexpr void + bf_debug_op_dump_vmexit_log(bf_uint16_t const &ppid) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_vmexit_log_impl(ppid.get()); + } + + /// + /// @brief This syscall tells the microkernel to output a provided + /// character to the microkernel's console. + /// + /// + /// @param c The character to output + /// + constexpr void + bf_debug_op_write_c(bsl::char_type const c) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_write_c_impl(c); + } + + /// + /// @brief This syscall tells the microkernel to output a provided + /// string to the microkernel's console. + /// + /// + /// @param str The virtual address of a null terminated string to output + /// + constexpr void + bf_debug_op_write_str(bsl::cstr_type const str) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_write_str_impl(str); + } + + /// + /// @brief This syscall tells the microkernel to output an extension's + /// state to the console device the microkernel is currently using + /// for debugging. + /// + /// + /// @param extid The EXTID of the extensions's state to output + /// + constexpr void + bf_debug_op_dump_ext(bf_uint16_t const &extid) noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_ext_impl(extid.get()); + } + + /// + /// @brief This syscall tells the microkernel to output the page pool's + /// stats to the console device the microkernel is currently using + /// for debugging. + /// + constexpr void + bf_debug_op_dump_page_pool() noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_page_pool_impl(); + } + + /// + /// @brief This syscall tells the microkernel to output the huge pool's + /// stats to the console device the microkernel is currently using + /// for debugging. + /// + constexpr void + bf_debug_op_dump_huge_pool() noexcept + { + if (bsl::is_constant_evaluated()) { + return; + } + + bf_debug_op_dump_huge_pool_impl(); + } +} + +#endif diff --git a/syscall/src/cpp/bf_syscall_impl.hpp b/syscall/src/cpp/bf_syscall_impl.hpp new file mode 100644 index 00000000..bb870e9a --- /dev/null +++ b/syscall/src/cpp/bf_syscall_impl.hpp @@ -0,0 +1,991 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef BF_SYSCALL_IMPL_HPP +#define BF_SYSCALL_IMPL_HPP + +#include +#include + +#include +#include + +namespace syscall +{ + // ------------------------------------------------------------------------- + // TLS ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_tls_rax. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_rax_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_rax. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_rax_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_rbx. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_rbx_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_rbx. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_rbx_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_rcx. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_rcx_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_rcx. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_rcx_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_rdx. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_rdx_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_rdx. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_rdx_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_rbp. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_rbp_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_rbp. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_rbp_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_rsi. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_rsi_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_rsi. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_rsi_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_rdi. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_rdi_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_rdi. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_rdi_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_r8. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_r8_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_r8. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_r8_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_r9. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_r9_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_r9. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_r9_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_r10. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_r10_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_r10. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_r10_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_r11. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_r11_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_r11. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_r11_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_r12. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_r12_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_r12. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_r12_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_r13. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_r13_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_r13. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_r13_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_r14. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_r14_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_r14. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_r14_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_r15. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_r15_impl() noexcept -> bf_uint64_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_set_r15. + /// + /// + /// @param val n/a + /// + extern "C" void bf_tls_set_r15_impl(bf_uint64_t::value_type const val) noexcept; + + /// + /// @brief Implements the ABI for bf_tls_extid. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_extid_impl() noexcept -> bf_uint16_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_vmid. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_vmid_impl() noexcept -> bf_uint16_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_vpid. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_vpid_impl() noexcept -> bf_uint16_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_vpsid. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_vpsid_impl() noexcept -> bf_uint16_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_ppid. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_ppid_impl() noexcept -> bf_uint16_t::value_type; + + /// + /// @brief Implements the ABI for bf_tls_online_pps. + /// + /// + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_tls_online_pps_impl() noexcept -> bf_uint16_t::value_type; + + // ------------------------------------------------------------------------- + // bf_control_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_control_op_exit. + /// + extern "C" void bf_control_op_exit_impl() noexcept; + + /// + /// @brief Implements the ABI for bf_control_op_wait. + /// + extern "C" void bf_control_op_wait_impl() noexcept; + + // ------------------------------------------------------------------------- + // bf_handle_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_handle_op_open_handle. + /// + /// + /// @param reg0_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_handle_op_open_handle_impl( + bf_uint32_t::value_type const reg0_in, bf_uint64_t::value_type *const reg0_out) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_handle_op_close_handle. + /// + /// + /// @param reg0_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto + bf_handle_op_close_handle_impl(bf_uint64_t::value_type const reg0_in) noexcept + -> bf_status_t::value_type; + + // ------------------------------------------------------------------------- + // bf_debug_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_debug_op_out. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// + extern "C" void bf_debug_op_out_impl( + bf_uint64_t::value_type const reg0_in, bf_uint64_t::value_type const reg1_in) noexcept; + + /// + /// @brief Implements the ABI for bf_debug_op_dump_vm. + /// + /// + /// @param reg0_in n/a + /// + extern "C" void bf_debug_op_dump_vm_impl(bf_uint16_t::value_type const reg0_in) noexcept; + + /// + /// @brief Implements the ABI for bf_debug_op_dump_vp. + /// + /// + /// @param reg0_in n/a + /// + extern "C" void bf_debug_op_dump_vp_impl(bf_uint16_t::value_type const reg0_in) noexcept; + + /// + /// @brief Implements the ABI for bf_debug_op_dump_vps. + /// + /// + /// @param reg0_in n/a + /// + extern "C" void bf_debug_op_dump_vps_impl(bf_uint16_t::value_type const reg0_in) noexcept; + + /// + /// @brief Implements the ABI for bf_debug_op_dump_vmexit_log. + /// + /// + /// @param reg0_in n/a + /// + extern "C" void + bf_debug_op_dump_vmexit_log_impl(bf_uint16_t::value_type const reg0_in) noexcept; + + /// + /// @brief Implements the ABI for bf_debug_op_write_c. + /// + /// + /// @param reg0_in n/a + /// + extern "C" void bf_debug_op_write_c_impl(bsl::char_type const reg0_in) noexcept; + + /// + /// @brief Implements the ABI for bf_debug_op_write_str. + /// + /// + /// @param reg0_in n/a + /// + extern "C" void bf_debug_op_write_str_impl(bsl::char_type const *const reg0_in) noexcept; + + /// + /// @brief Implements the ABI for bf_debug_op_dump_ext. + /// + /// + /// @param reg0_in n/a + /// + extern "C" void bf_debug_op_dump_ext_impl(bf_uint16_t::value_type const reg0_in) noexcept; + + /// + /// @brief Implements the ABI for bf_debug_op_dump_page_pool. + /// + extern "C" void bf_debug_op_dump_page_pool_impl() noexcept; + + /// + /// @brief Implements the ABI for bf_debug_op_dump_huge_pool. + /// + extern "C" void bf_debug_op_dump_huge_pool_impl() noexcept; + + // ------------------------------------------------------------------------- + // bf_callback_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_callback_op_register_bootstrap. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_callback_op_register_bootstrap_impl( + bf_uint64_t::value_type const reg0_in, + bf_callback_handler_bootstrap_t const reg1_in) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_callback_op_register_vmexit. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_callback_op_register_vmexit_impl( + bf_uint64_t::value_type const reg0_in, bf_callback_handler_vmexit_t const reg1_in) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_callback_op_register_fail. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_callback_op_register_fail_impl( + bf_uint64_t::value_type const reg0_in, bf_callback_handler_fail_t const reg1_in) noexcept + -> bf_status_t::value_type; + + // ------------------------------------------------------------------------- + // bf_vm_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_vm_op_create_vm. + /// + /// + /// @param reg0_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vm_op_create_vm_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type *const reg0_out) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vm_op_destroy_vm. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vm_op_destroy_vm_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type; + + // ------------------------------------------------------------------------- + // bf_vp_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_vp_op_create_vp. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vp_op_create_vp_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint16_t::value_type const reg2_in, + bf_uint16_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vp_op_destroy_vp. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vp_op_destroy_vp_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vp_op_migrate. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vp_op_migrate_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint16_t::value_type const reg2_in) noexcept -> bf_status_t::value_type; + + // ------------------------------------------------------------------------- + // bf_vps_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_vps_op_create_vps. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_create_vps_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint16_t::value_type const reg2_in, + bf_uint16_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_destroy_vps. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_destroy_vps_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_init_as_root. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_init_as_root_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_read8. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_read8_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint8_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_read16. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_read16_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint16_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_read32. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_read32_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint32_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_read64. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_read64_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint64_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_write8. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_write8_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint8_t::value_type const reg3_in) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_write16. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_write16_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint16_t::value_type const reg3_in) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_write32. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_write32_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint32_t::value_type const reg3_in) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_write64. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_write64_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in, + bf_uint64_t::value_type const reg3_in) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_read_reg_impl. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_read_reg_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_reg_t const reg2_in, + bf_uint64_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_write_reg. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_write_reg_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_reg_t const reg2_in, + bf_uint64_t::value_type const reg3_in) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_run. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_run_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint16_t::value_type const reg1_in, + bf_uint16_t::value_type const reg2_in, + bf_uint16_t::value_type const reg3_in) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_run_current. + /// + /// + /// @param reg0_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto + bf_vps_op_run_current_impl(bf_uint64_t::value_type const reg0_in) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_advance_ip. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_advance_ip_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_advance_ip_and_run_current. + /// + /// + /// @param reg0_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto + bf_vps_op_advance_ip_and_run_current_impl(bf_uint64_t::value_type const reg0_in) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_promote. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_promote_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_vps_op_clear_vps. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_vps_op_clear_vps_impl( + bf_uint64_t::value_type const reg0_in, bf_uint16_t::value_type const reg1_in) noexcept + -> bf_status_t::value_type; + + // ------------------------------------------------------------------------- + // bf_intrinsic_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_intrinsic_op_rdmsr. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_intrinsic_op_rdmsr_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint32_t::value_type const reg1_in, + bf_uint64_t::value_type *const reg0_out) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_intrinsic_op_wrmsr. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_intrinsic_op_wrmsr_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint32_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_intrinsic_op_invlpga. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_intrinsic_op_invlpga_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint64_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_intrinsic_op_invept. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_intrinsic_op_invept_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint64_t::value_type const reg1_in, + bf_uint64_t::value_type const reg2_in) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_intrinsic_op_invvpid. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg2_in n/a + /// @param reg3_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_intrinsic_op_invvpid_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint64_t::value_type const reg1_in, + bf_uint16_t::value_type const reg2_in, + bf_uint64_t::value_type const reg3_in) noexcept -> bf_status_t::value_type; + + // ------------------------------------------------------------------------- + // bf_mem_ops + // ------------------------------------------------------------------------- + + /// + /// @brief Implements the ABI for bf_mem_op_alloc_page. + /// + /// + /// @param reg0_in n/a + /// @param reg0_out n/a + /// @param reg1_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_mem_op_alloc_page_impl( + bf_uint64_t::value_type const reg0_in, + void **const reg0_out, + bf_uint64_t::value_type *const reg1_out) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_mem_op_free_page. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto + bf_mem_op_free_page_impl(bf_uint64_t::value_type const reg0_in, void *const reg1_in) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_mem_op_alloc_huge. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg0_out n/a + /// @param reg1_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_mem_op_alloc_huge_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint64_t::value_type const reg1_in, + void **const reg0_out, + bf_uint64_t::value_type *const reg1_out) noexcept -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_mem_op_free_huge. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto + bf_mem_op_free_huge_impl(bf_uint64_t::value_type const reg0_in, void *const reg1_in) noexcept + -> bf_status_t::value_type; + + /// + /// @brief Implements the ABI for bf_mem_op_alloc_heap. + /// + /// + /// @param reg0_in n/a + /// @param reg1_in n/a + /// @param reg0_out n/a + /// @return n/a + /// + extern "C" [[nodiscard]] auto bf_mem_op_alloc_heap_impl( + bf_uint64_t::value_type const reg0_in, + bf_uint64_t::value_type const reg1_in, + void **const reg0_out) noexcept -> bf_status_t::value_type; +} + +#endif diff --git a/syscall/src/cpp/bf_syscall_t.hpp b/syscall/src/cpp/bf_syscall_t.hpp new file mode 100644 index 00000000..f5e0e993 --- /dev/null +++ b/syscall/src/cpp/bf_syscall_t.hpp @@ -0,0 +1,2288 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#ifndef BF_SYSCALL_T_HPP +#define BF_SYSCALL_T_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace syscall +{ + /// @class syscall::bf_syscall_t + /// + /// + /// @brief Provides an API wrapper around all of the microkernel ABIs. + /// For more information about these APIs, please see the Microkernel + /// ABI Specification. + /// + /// + class bf_syscall_t final + { + /// @brief stores the handle used for making syscalls. + bf_uint64_t m_hndl{}; + + public: + /// + /// @brief Initializes the bf_syscall_t by opening a handle and + /// registering all of the required handlers. If this function + /// fails, the handle is closed automatically. + /// + /// + /// @param version the version provided to the extension by the + /// microkernel. If this API does not support the ABI versions + /// that the microkernel supports, this function will fail. + /// @param bootstrap_handler the bootstrap handler to register + /// @param vmexit_handler the vmexit handler to register + /// @param fail_handler the fail handler to register + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// and friends otherwise + /// + [[nodiscard]] constexpr auto + initialize( + bf_uint32_t const &version, + bf_callback_handler_bootstrap_t const bootstrap_handler, + bf_callback_handler_vmexit_t const vmexit_handler, + bf_callback_handler_fail_t const fail_handler) noexcept -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!version)) { + bsl::error() << "invalid version\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(version.is_zero())) { + bsl::error() << "version cannot be zero\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(nullptr == bootstrap_handler)) { + bsl::error() << "invalid bootstrap_handler\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(nullptr == vmexit_handler)) { + bsl::error() << "invalid vmexit_handler\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(nullptr == fail_handler)) { + bsl::error() << "invalid fail_handler\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely(!bf_is_spec1_supported(version))) { + bsl::error() << "unsupported microkernel " // -- + << bsl::hex(version) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_unsupported; + } + + ret = bf_handle_op_open_handle_impl(BF_SPEC_ID1_VAL.get(), m_hndl.data()); + if (bsl::unlikely_assert(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_handle_op_open_handle_impl failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + bsl::finally_assert release_on_error{[this]() noexcept -> void { + this->release(); + }}; + + ret = bf_callback_op_register_bootstrap_impl(m_hndl.get(), bootstrap_handler); + if (bsl::unlikely_assert(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_callback_op_register_bootstrap failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + ret = bf_callback_op_register_vmexit_impl(m_hndl.get(), vmexit_handler); + if (bsl::unlikely_assert(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_callback_op_register_vmexit failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + ret = bf_callback_op_register_fail_impl(m_hndl.get(), fail_handler); + if (bsl::unlikely_assert(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_callback_op_register_fail failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + release_on_error.ignore(); + return bsl::errc_success; + } + + /// + /// @brief Releases the bf_syscall_t by closing the handle. + /// + constexpr void + release() noexcept + { + bsl::discard(bf_handle_op_close_handle_impl(m_hndl.get())); + m_hndl = {}; + } + + // --------------------------------------------------------------------- + // TLS ops + // --------------------------------------------------------------------- + + /// + /// @brief Returns the value of tls.rax + /// + /// + /// @return Returns the value of tls.rax + /// + [[nodiscard]] static constexpr auto + bf_tls_rax() noexcept -> bf_uint64_t + { + return bf_tls_rax_impl(); + } + + /// + /// @brief Sets the value of tls.rax + /// + /// + /// @param val The value to set tls.rax to + /// + static constexpr void + bf_tls_set_rax(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_rax_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.rbx + /// + /// + /// @return Returns the value of tls.rbx + /// + [[nodiscard]] static constexpr auto + bf_tls_rbx() noexcept -> bf_uint64_t + { + return bf_tls_rbx_impl(); + } + + /// + /// @brief Sets the value of tls.rbx + /// + /// + /// @param val The value to set tls.rbx to + /// + static constexpr void + bf_tls_set_rbx(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_rbx_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.rcx + /// + /// + /// @return Returns the value of tls.rcx + /// + [[nodiscard]] static constexpr auto + bf_tls_rcx() noexcept -> bf_uint64_t + { + return bf_tls_rcx_impl(); + } + + /// + /// @brief Sets the value of tls.rcx + /// + /// + /// @param val The value to set tls.rcx to + /// + static constexpr void + bf_tls_set_rcx(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_rcx_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.rdx + /// + /// + /// @return Returns the value of tls.rdx + /// + [[nodiscard]] static constexpr auto + bf_tls_rdx() noexcept -> bf_uint64_t + { + return bf_tls_rdx_impl(); + } + + /// + /// @brief Sets the value of tls.rdx + /// + /// + /// @param val The value to set tls.rdx to + /// + static constexpr void + bf_tls_set_rdx(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_rdx_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.rbp + /// + /// + /// @return Returns the value of tls.rbp + /// + [[nodiscard]] static constexpr auto + bf_tls_rbp() noexcept -> bf_uint64_t + { + return bf_tls_rbp_impl(); + } + + /// + /// @brief Sets the value of tls.rbp + /// + /// + /// @param val The value to set tls.rbp to + /// + static constexpr void + bf_tls_set_rbp(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_rbp_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.rsi + /// + /// + /// @return Returns the value of tls.rsi + /// + [[nodiscard]] static constexpr auto + bf_tls_rsi() noexcept -> bf_uint64_t + { + return bf_tls_rsi_impl(); + } + + /// + /// @brief Sets the value of tls.rsi + /// + /// + /// @param val The value to set tls.rsi to + /// + static constexpr void + bf_tls_set_rsi(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_rsi_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.rdi + /// + /// + /// @return Returns the value of tls.rdi + /// + [[nodiscard]] static constexpr auto + bf_tls_rdi() noexcept -> bf_uint64_t + { + return bf_tls_rdi_impl(); + } + + /// + /// @brief Sets the value of tls.rdi + /// + /// + /// @param val The value to set tls.rdi to + /// + static constexpr void + bf_tls_set_rdi(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_rdi_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.r8 + /// + /// + /// @return Returns the value of tls.r8 + /// + [[nodiscard]] static constexpr auto + bf_tls_r8() noexcept -> bf_uint64_t + { + return bf_tls_r8_impl(); + } + + /// + /// @brief Sets the value of tls.r8 + /// + /// + /// @param val The value to set tls.r8 to + /// + static constexpr void + bf_tls_set_r8(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_r8_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.r9 + /// + /// + /// @return Returns the value of tls.r9 + /// + [[nodiscard]] static constexpr auto + bf_tls_r9() noexcept -> bf_uint64_t + { + return bf_tls_r9_impl(); + } + + /// + /// @brief Sets the value of tls.r9 + /// + /// + /// @param val The value to set tls.r9 to + /// + static constexpr void + bf_tls_set_r9(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_r9_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.r10 + /// + /// + /// @return Returns the value of tls.r10 + /// + [[nodiscard]] static constexpr auto + bf_tls_r10() noexcept -> bf_uint64_t + { + return bf_tls_r10_impl(); + } + + /// + /// @brief Sets the value of tls.r10 + /// + /// + /// @param val The value to set tls.r10 to + /// + static constexpr void + bf_tls_set_r10(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_r10_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.r11 + /// + /// + /// @return Returns the value of tls.r11 + /// + [[nodiscard]] static constexpr auto + bf_tls_r11() noexcept -> bf_uint64_t + { + return bf_tls_r11_impl(); + } + + /// + /// @brief Sets the value of tls.r11 + /// + /// + /// @param val The value to set tls.r11 to + /// + static constexpr void + bf_tls_set_r11(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_r11_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.r12 + /// + /// + /// @return Returns the value of tls.r12 + /// + [[nodiscard]] static constexpr auto + bf_tls_r12() noexcept -> bf_uint64_t + { + return bf_tls_r12_impl(); + } + + /// + /// @brief Sets the value of tls.r12 + /// + /// + /// @param val The value to set tls.r12 to + /// + static constexpr void + bf_tls_set_r12(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_r12_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.r13 + /// + /// + /// @return Returns the value of tls.r13 + /// + [[nodiscard]] static constexpr auto + bf_tls_r13() noexcept -> bf_uint64_t + { + return bf_tls_r13_impl(); + } + + /// + /// @brief Sets the value of tls.r13 + /// + /// + /// @param val The value to set tls.r13 to + /// + static constexpr void + bf_tls_set_r13(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_r13_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.r14 + /// + /// + /// @return Returns the value of tls.r14 + /// + [[nodiscard]] static constexpr auto + bf_tls_r14() noexcept -> bf_uint64_t + { + return bf_tls_r14_impl(); + } + + /// + /// @brief Sets the value of tls.r14 + /// + /// + /// @param val The value to set tls.r14 to + /// + static constexpr void + bf_tls_set_r14(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_r14_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.r15 + /// + /// + /// @return Returns the value of tls.r15 + /// + [[nodiscard]] static constexpr auto + bf_tls_r15() noexcept -> bf_uint64_t + { + return bf_tls_r15_impl(); + } + + /// + /// @brief Sets the value of tls.r15 + /// + /// + /// @param val The value to set tls.r15 to + /// + static constexpr void + bf_tls_set_r15(bf_uint64_t const &val) noexcept + { + if (bsl::unlikely_assert(!val)) { + bsl::alert() << "invalid val\n" << bsl::here(); + return; + } + + bf_tls_set_r15_impl(val.get()); + } + + /// + /// @brief Returns the value of tls.extid + /// + /// + /// @return Returns the value of tls.extid + /// + [[nodiscard]] static constexpr auto + bf_tls_extid() noexcept -> bsl::safe_uint16 + { + return bf_tls_extid_impl(); + } + + /// + /// @brief Returns the value of tls.vmid + /// + /// + /// @return Returns the value of tls.vmid + /// + [[nodiscard]] static constexpr auto + bf_tls_vmid() noexcept -> bsl::safe_uint16 + { + return bf_tls_vmid_impl(); + } + + /// + /// @brief Returns the value of tls.vpid + /// + /// + /// @return Returns the value of tls.vpid + /// + [[nodiscard]] static constexpr auto + bf_tls_vpid() noexcept -> bsl::safe_uint16 + { + return bf_tls_vpid_impl(); + } + + /// + /// @brief Returns the value of tls.vpsid + /// + /// + /// @return Returns the value of tls.vpsid + /// + [[nodiscard]] static constexpr auto + bf_tls_vpsid() noexcept -> bsl::safe_uint16 + { + return bf_tls_vpsid_impl(); + } + + /// + /// @brief Returns the value of tls.ppid + /// + /// + /// @return Returns the value of tls.ppid + /// + [[nodiscard]] static constexpr auto + bf_tls_ppid() noexcept -> bsl::safe_uint16 + { + return bf_tls_ppid_impl(); + } + + /// + /// @brief Returns the value of tls.online_pps + /// + /// + /// @return Returns the value of tls.online_pps + /// + [[nodiscard]] static constexpr auto + bf_tls_online_pps() noexcept -> bsl::safe_uint16 + { + return bf_tls_online_pps_impl(); + } + + // --------------------------------------------------------------------- + // bf_vm_ops + // --------------------------------------------------------------------- + + /// + /// @brief This syscall tells the microkernel to create a VM + /// and return it's ID. + /// + /// + /// @return Returns the resulting ID, or bf_uint16_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_vm_op_create_vm() noexcept -> bf_uint16_t + { + bf_status_t ret{}; + bf_uint16_t vmid{}; + + ret = bf_vm_op_create_vm_impl(m_hndl.get(), vmid.data()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vm_op_create_vm failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bf_uint16_t::failure(); + } + + return vmid; + } + + /// + /// @brief This syscall tells the microkernel to destroy a VM + /// given an ID. + /// + /// + /// @param vmid The VMID of the VM to destroy + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vm_op_destroy_vm(bf_uint16_t const &vmid) noexcept -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vmid)) { + bsl::error() << "invalid vmid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vm_op_destroy_vm_impl(m_hndl.get(), vmid.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vm_op_destroy_vm failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + // --------------------------------------------------------------------- + // bf_vp_ops + // --------------------------------------------------------------------- + + /// + /// @brief This syscall tells the microkernel to create a VP given the + /// IDs of the VM and PP the VP will be assigned to. Upon success, + /// this syscall returns the ID of the newly created VP. + /// + /// + /// @param vmid The ID of the VM to assign the newly created VP to + /// @param ppid The ID of the PP to assign the newly created VP to + /// @return Returns the resulting ID, or bf_uint16_t::failure() + /// on failure. + /// + /// + [[nodiscard]] constexpr auto + bf_vp_op_create_vp(bf_uint16_t const &vmid, bf_uint16_t const &ppid) noexcept -> bf_uint16_t + { + bf_status_t ret{}; + bf_uint16_t vpid{}; + + if (bsl::unlikely_assert(!vmid)) { + bsl::error() << "invalid vmid\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + ret = bf_vp_op_create_vp_impl(m_hndl.get(), vmid.get(), ppid.get(), vpid.data()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vp_op_create_vp failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bf_uint16_t::failure(); + } + + return vpid; + } + + /// + /// @brief This syscall tells the microkernel to destroy a VP + /// given an ID. + /// + /// + /// @param vpid The VPID of the VP to destroy + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vp_op_destroy_vp(bf_uint16_t const &vpid) noexcept -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vp_op_destroy_vp_impl(m_hndl.get(), vpid.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vp_op_destroy_vp failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief This syscall tells the microkernel to migrate a VP from one PP + /// to another PP. This function does not execute the VP (use + /// bf_vps_op_run for that), but instead allows bf_vps_op_run to + /// execute a VP on a PP that it was not originally assigned to. + /// + /// When a VP is migrated, all of the VPSs that are assigned to the + /// requested VP are also migrated to this new PP as well. From an + /// AMD/Intel point of view, this clears the VMCS/VMCB for each VPS + /// assigned to the VP. On Intel, it also loads the newly cleared VPS + /// and sets the launched state to false, ensuring the next + /// bf_vps_op_run will use VMLaunch instead of VMResume. + /// + /// It should be noted that the migration of a VPS from one PP to + /// another does not happen during the execution of this ABI. This + /// ABI simply tells the microkernel that the requested VP may now + /// execute on the requested PP. This will cause a mismatch between + /// the assigned PP for a VP and the assigned PP for a VPS. The + /// microkernel will detect this mismatch when an extension attempts + /// to execute bf_vps_op_run. When this occurs, the microkernel will + /// ensure the VP is being run on the PP it was assigned to during + /// migration, and then it will check to see if the PP of the VPS + /// matches. If it doesn't, it will then perform a migration of that + /// VPS at that time. This ensures that the microkernel is only + /// migrations VPSs when it needs to, and it ensures the VPS is + /// cleared an loaded (in the case of Intel) on the PP it will be + /// executed on, which is a requirement for VMCS migration. An + /// extension can determine which VPSs have been migrated by looking + /// at the assigned PP of a VPS. If it doesn't match the VP it was + /// assigned to, it has not been migrated. Finally, an extension is + /// free to read/write to the VPSs state, even if it has not been + /// migrated. The only requirement for migration is execution (meaning + /// VMRun/VMLaunch/VMResume). + /// + /// Any additional migration responsibilities, like TSC + /// synchronization, must be performed by the extension. + /// + /// + /// @param vpid The VPID of the VP to migrate + /// @param ppid The ID of the PP to assign the provided VP to + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vp_op_migrate(bf_uint16_t const &vpid, bf_uint16_t const &ppid) noexcept + -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vp_op_migrate_impl(m_hndl.get(), vpid.get(), ppid.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vp_op_migrate failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + // --------------------------------------------------------------------- + // bf_vps_ops + // --------------------------------------------------------------------- + + /// + /// @brief This syscall tells the microkernel to create a VPS + /// and return it's ID. + /// + /// + /// @param vpid The ID of the VP to assign the newly created VPS to + /// @param ppid The resulting VPSID of the newly created VPS + /// @return Returns the resulting ID, or bf_uint16_t::failure() + /// on failure. + /// + /// + [[nodiscard]] constexpr auto + bf_vps_op_create_vps(bf_uint16_t const &vpid, bf_uint16_t const &ppid) noexcept + -> bf_uint16_t + { + bf_status_t ret{}; + bf_uint16_t vpsid{}; + + if (bsl::unlikely_assert(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + if (bsl::unlikely_assert(!ppid)) { + bsl::error() << "invalid ppid\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + ret = bf_vps_op_create_vps_impl(m_hndl.get(), vpid.get(), ppid.get(), vpsid.data()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_create_vps failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bf_uint16_t::failure(); + } + + return vpsid; + } + + /// + /// @brief This syscall tells the microkernel to destroy a VPS + /// given an ID. + /// + /// + /// @param vpsid The VPSID of the VPS to destroy + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_destroy_vps(bf_uint16_t const &vpsid) noexcept -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vps_op_destroy_vps_impl(m_hndl.get(), vpsid.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_destroy_vps failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief This syscall tells the microkernel to initialize a VPS using + /// the root VP state provided by the loader using the current PPID. + /// + /// + /// @param vpsid The VPSID of the VPS to initialize + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_init_as_root(bf_uint16_t const &vpsid) noexcept -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vps_op_init_as_root_impl(m_hndl.get(), vpsid.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_init_as_root failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Reads an 8bit field from the VPS and returns the value. The + /// "index" is architecture-specific. For Intel, Appendix B, "Field + /// Encoding in VMCS," defines the index (or encoding). For AMD, + /// Appendix B, "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @return Returns the value read, or bf_uint8_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_vps_op_read8(bf_uint16_t const &vpsid, bf_uint64_t const &index) const noexcept + -> bf_uint8_t + { + bf_status_t ret{}; + bf_uint8_t value{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bf_uint8_t::failure(); + } + + if (bsl::unlikely_assert(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bf_uint8_t::failure(); + } + + ret = bf_vps_op_read8_impl(m_hndl.get(), vpsid.get(), index.get(), value.data()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_read8 failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bf_uint8_t::failure(); + } + + return value; + } + + /// + /// @brief Reads an 16bit field from the VPS and returns the value. The + /// "index" is architecture-specific. For Intel, Appendix B, "Field + /// Encoding in VMCS," defines the index (or encoding). For AMD, + /// Appendix B, "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @return Returns the value read, or bf_uint16_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_vps_op_read16(bf_uint16_t const &vpsid, bf_uint64_t const &index) const noexcept + -> bf_uint16_t + { + bf_status_t ret{}; + bf_uint16_t value{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + if (bsl::unlikely_assert(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bf_uint16_t::failure(); + } + + ret = bf_vps_op_read16_impl(m_hndl.get(), vpsid.get(), index.get(), value.data()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_read16 failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bf_uint16_t::failure(); + } + + return value; + } + + /// + /// @brief Reads an 32bit field from the VPS and returns the value. The + /// "index" is architecture-specific. For Intel, Appendix B, "Field + /// Encoding in VMCS," defines the index (or encoding). For AMD, + /// Appendix B, "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @return Returns the value read, or bf_uint32_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_vps_op_read32(bf_uint16_t const &vpsid, bf_uint64_t const &index) const noexcept + -> bf_uint32_t + { + bf_status_t ret{}; + bf_uint32_t value{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bf_uint32_t::failure(); + } + + if (bsl::unlikely_assert(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bf_uint32_t::failure(); + } + + ret = bf_vps_op_read32_impl(m_hndl.get(), vpsid.get(), index.get(), value.data()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_read32 failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bf_uint32_t::failure(); + } + + return value; + } + + /// + /// @brief Reads an 64bit field from the VPS and returns the value. The + /// "index" is architecture-specific. For Intel, Appendix B, "Field + /// Encoding in VMCS," defines the index (or encoding). For AMD, + /// Appendix B, "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param index The HVE specific index defining which field to read + /// @return Returns the value read, or bf_uint64_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_vps_op_read64(bf_uint16_t const &vpsid, bf_uint64_t const &index) const noexcept + -> bf_uint64_t + { + bf_status_t ret{}; + bf_uint64_t value{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bf_uint64_t::failure(); + } + + if (bsl::unlikely_assert(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bf_uint64_t::failure(); + } + + ret = bf_vps_op_read64_impl(m_hndl.get(), vpsid.get(), index.get(), value.data()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_read64 failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bf_uint64_t::failure(); + } + + return value; + } + + /// + /// @brief Writes to an 8bit field in the VPS. The "index" is + /// architecture-specific. For Intel, Appendix B, "Field Encoding in + /// VMCS," defines the index (or encoding). For AMD, Appendix B, + /// "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_write8( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint8_t const &value) noexcept + -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vps_op_write8_impl(m_hndl.get(), vpsid.get(), index.get(), value.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_write8 failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Writes to an 16bit field in the VPS. The "index" is + /// architecture-specific. For Intel, Appendix B, "Field Encoding in + /// VMCS," defines the index (or encoding). For AMD, Appendix B, + /// "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_write16( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint16_t const &value) noexcept + -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vps_op_write16_impl(m_hndl.get(), vpsid.get(), index.get(), value.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_write16 failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Writes to an 32bit field in the VPS. The "index" is + /// architecture-specific. For Intel, Appendix B, "Field Encoding in + /// VMCS," defines the index (or encoding). For AMD, Appendix B, + /// "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_write32( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint32_t const &value) noexcept + -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vps_op_write32_impl(m_hndl.get(), vpsid.get(), index.get(), value.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_write32 failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Writes to an 64bit field in the VPS. The "index" is + /// architecture-specific. For Intel, Appendix B, "Field Encoding in + /// VMCS," defines the index (or encoding). For AMD, Appendix B, + /// "Layout of VMCB," defines the index (or offset). + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param index The HVE specific index defining which field to write to + /// @param value The value to write to the requested field + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_write64( + bf_uint16_t const &vpsid, bf_uint64_t const &index, bf_uint64_t const &value) noexcept + -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!index)) { + bsl::error() << "invalid index\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vps_op_write64_impl(m_hndl.get(), vpsid.get(), index.get(), value.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_write64 failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Reads a CPU register from the VPS given a bf_reg_t. Note + /// that the bf_reg_t is architecture specific. + /// + /// + /// @param vpsid The VPSID of the VPS to read from + /// @param reg A bf_reg_t defining which register to read + /// @return Returns the value read, or bf_uint64_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_vps_op_read_reg(bf_uint16_t const &vpsid, bf_reg_t const reg) const noexcept + -> bf_uint64_t + { + bf_status_t ret{}; + bf_uint64_t value{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bf_uint64_t::failure(); + } + + ret = bf_vps_op_read_reg_impl(m_hndl.get(), vpsid.get(), reg, value.data()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_read_reg failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bf_uint64_t::failure(); + } + + return value; + } + + /// + /// @brief Writes to a CPU register in the VPS given a bf_reg_t and the + /// value to write. Note that the bf_reg_t is architecture specific. + /// + /// + /// @param vpsid The VPSID of the VPS to write to + /// @param reg A bf_reg_t defining which register to write to + /// @param value The value to write to the requested register + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_write_reg( + bf_uint16_t const &vpsid, bf_reg_t const reg, bf_uint64_t const &value) noexcept + -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vps_op_write_reg_impl(m_hndl.get(), vpsid.get(), reg, value.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_write_reg failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief bf_vps_op_run tells the microkernel to execute a given VPS on + /// behalf of a given VP and VM. This system call only returns if an + /// error occurs. On success, this system call will physically execute + /// the requested VM and VP using the requested VPS, and the extension + /// will only execute again on the next VMExit. + /// + /// Unless an extension needs to change the active VM, VP or VPS, the + /// extension should use bf_vps_op_run_current instead of + /// bf_vps_op_run. bf_vps_op_run is slow as it must perform a series of + /// checks to determine if it has any work to perform before execution + /// of a VM can occur. + /// + /// Unlike bf_vps_op_run_current which is really just a return to + /// microkernel execution, bf_vps_op_run must perform the following + /// operations: + /// - It first verifies that the provided VM, VP and VPS are all + /// created. Meaning, and extension must first use the create ABI + /// to properly create a VM, VP and VPS before it may be used. + /// - Next, it must ensure VM, VP and VPS assignment is correct. A + /// newly created VP and VPS are unassigned. Once bf_vps_op_run is + /// executed, the VP is assigned to the provided VM and the VPS is + /// assigned to the provided VP. The VP and VPS are also both + /// assigned to the PP bf_vps_op_run is executed on. Once these + /// assignments take place, an extension cannot change them, and any + /// attempt to run a VP or VPS on a VM, VP or PP they are not + /// assigned to will fail. It is impossible to change the assigned of + /// a VM or VP, but an extension can change the assignment of a VP + /// and VPSs PP by using the bf_vp_op_migrate function. + /// - Next, bf_vps_op_run must determine if it needs to migrate a VPS + /// to the PP the VPS is being executed on by bf_vps_op_run. For more + /// information about how this works, please see bf_vp_op_migrate. + /// - Finally, bf_vps_op_run must ensure the active VM, VP and VPS are + /// set to the VM, VP and VPS provided to this ABI. Any changes in + /// the active state could cause additional operations to take place. + /// For example, the VPS must transfer the TLS state of the general + /// purpose registers to its internal cache so that the VPS that is + /// about to become active can use the TLS block instead. + /// + /// + /// @param vmid The VMID of the VM to run + /// @param vpid The VPID of the VP to run + /// @param vpsid The VPSID of the VPS to run + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_run( + bf_uint16_t const &vmid, bf_uint16_t const &vpid, bf_uint16_t const &vpsid) noexcept + -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vmid)) { + bsl::error() << "invalid vmid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vps_op_run_impl(m_hndl.get(), vmid.get(), vpid.get(), vpsid.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_run failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief bf_vps_op_run_current tells the microkernel to execute the + /// currently active VPS, VP and VM. + /// + /// + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_run_current() noexcept -> bsl::errc_type + { + bf_status_t const ret{bf_vps_op_run_current_impl(m_hndl.get())}; + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_run_current failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief This syscall tells the microkernel to advance the instruction + /// pointer in the requested VPS. + /// + /// + /// @param vpsid The VPSID of the VPS advance the IP in + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_advance_ip(bf_uint16_t const &vpsid) noexcept -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vps_op_advance_ip_impl(m_hndl.get(), vpsid.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_advance_ip failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief This syscall tells the microkernel to advance the instruction + /// pointer in the currently active VPS and run the currently active + /// VPS, VP and VM (i.e., this combines bf_vps_op_advance_ip and + /// bf_vps_op_advance_ip). + /// + /// + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_advance_ip_and_run_current() noexcept -> bsl::errc_type + { + bf_status_t const ret{bf_vps_op_advance_ip_and_run_current_impl(m_hndl.get())}; + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_advance_ip_and_run_current failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief This syscall tells the microkernel to promote the requested + /// VPS. This will stop the hypervisor complete on the physical + /// processor that this syscall is executed on and replace it's state + /// with the state in the VPS. Note that this syscall only returns + /// on error. + /// + /// + /// @param vpsid The VPSID of the VPS to promote + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_promote(bf_uint16_t const &vpsid) noexcept -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vps_op_promote_impl(m_hndl.get(), vpsid.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_promote failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief bf_vps_op_clear_vps tells the microkernel to clear the VPS's + /// hardware cache, if one exists. How this is used depends entirely + /// on the hardware and is associated with AMD's VMCB Clean Bits, + /// and Intel's VMClear instruction. See the associated documentation + /// for more details. On AMD, this ABI clears the entire VMCB. For more + /// fine grained control, use the write ABIs to manually modify the + /// VMCB. + /// + /// + /// @param vpsid The VPSID of the VPS to clear + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_vps_op_clear_vps(bf_uint16_t const &vpsid) noexcept -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!vpsid)) { + bsl::error() << "invalid vpsid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_vps_op_clear_vps_impl(m_hndl.get(), vpsid.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_vps_op_clear_vps failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + // --------------------------------------------------------------------- + // bf_intrinsic_ops + // --------------------------------------------------------------------- + + /// + /// @brief Reads an MSR directly from the CPU given the address of + /// the MSR to read. Note that this is specific to Intel/AMD only. + /// Also note that not all MSRs can be read, and which MSRs that + /// can be read is up to the microkernel's internal policy as well + /// as which architecture the hypervisor is running on. + /// + /// + /// @param msr The address of the MSR to read + /// @return Returns the value read, or bf_uint64_t::failure() + /// on failure. + /// + [[nodiscard]] constexpr auto + bf_intrinsic_op_rdmsr(bf_uint32_t const &msr) const noexcept -> bf_uint64_t + { + bf_status_t ret{}; + bf_uint64_t value{}; + + if (bsl::unlikely_assert(!msr)) { + bsl::error() << "invalid msr\n" << bsl::here(); + return bf_uint64_t::failure(); + } + + ret = bf_intrinsic_op_rdmsr_impl(m_hndl.get(), msr.get(), value.data()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_intrinsic_op_rdmsr failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bf_uint64_t::failure(); + } + + return value; + } + + /// + /// @brief Writes to an MSR directly from the CPU given the address of + /// the MSR to write as well as the value to write. Note that this is + /// specific to Intel/AMD only. Also note that not all MSRs can be + /// written to, and which MSRs that can be written to is up to the + /// microkernel's internal policy as well as which architecture the + /// hypervisor is running on. + /// + /// + /// @param msr The address of the MSR to write to + /// @param value The value to write to the requested MSR + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_intrinsic_op_wrmsr(bf_uint32_t const &msr, bf_uint64_t const &value) noexcept + -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!msr)) { + bsl::error() << "invalid msr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!value)) { + bsl::error() << "invalid value\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_intrinsic_op_wrmsr_impl(m_hndl.get(), msr.get(), value.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_intrinsic_op_wrmsr failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Invalidates the TLB mapping for a given virtual page and a + /// given ASID. Note that this is specific to AMD only. + /// + /// + /// @param addr The address to invalidate + /// @param asid The ASID to invalidate + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_intrinsic_op_invlpga(bf_uint64_t const &addr, bf_uint64_t const &asid) noexcept + -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!addr)) { + bsl::error() << "invalid addr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!asid)) { + bsl::error() << "invalid asid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_intrinsic_op_invlpga_impl(m_hndl.get(), addr.get(), asid.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_intrinsic_op_invlpga failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Invalidates mappings in the translation lookaside buffers + /// (TLBs) and paging-structure caches that were derived from extended + /// page tables (EPT). Note that this is specific to Intel only. + /// + /// + /// @param eptp The EPTP to invalidate + /// @param type The INVEPT type (see the Intel SDM for details) + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_intrinsic_op_invept(bf_uint64_t const &eptp, bf_uint64_t const &type) noexcept + -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!eptp)) { + bsl::error() << "invalid eptp\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!type)) { + bsl::error() << "invalid type\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_intrinsic_op_invept_impl(m_hndl.get(), eptp.get(), type.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_intrinsic_op_invept failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief Invalidates mappings in the translation lookaside buffers + /// (TLBs) and paging-structure caches based on virtual-processor + /// identifier (VPID). Note that this is specific to Intel only. + /// + /// + /// @param addr The address to invalidate + /// @param vpid The VPID to invalidate + /// @param type The INVVPID type (see the Intel SDM for details) + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_intrinsic_op_invvpid( + bf_uint64_t const &addr, bf_uint16_t const &vpid, bf_uint64_t const &type) noexcept + -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(!addr)) { + bsl::error() << "invalid addr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!vpid)) { + bsl::error() << "invalid vpid\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!type)) { + bsl::error() << "invalid type\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_intrinsic_op_invvpid_impl(m_hndl.get(), addr.get(), vpid.get(), type.get()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_intrinsic_op_invvpid failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + // --------------------------------------------------------------------- + // bf_mem_ops + // --------------------------------------------------------------------- + + /// + /// @brief bf_mem_op_alloc_page allocates a page, and maps this page + /// into the direct map of the VM. + /// + /// + /// @param phys The physical address of the resulting page + /// @return Returns a pointer to the newly allocated memory on success, + /// or a nullptr on failure. + /// + [[nodiscard]] constexpr auto + bf_mem_op_alloc_page(bf_uint64_t &phys) noexcept -> void * + { + void *ptr{}; + bf_status_t ret{}; + + if (bsl::unlikely_assert(!phys)) { + bsl::error() << "invalid phys\n" << bsl::here(); + return nullptr; + } + + ret = bf_mem_op_alloc_page_impl(m_hndl.get(), &ptr, phys.data()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_mem_op_alloc_page failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return nullptr; + } + + return ptr; + } + + /// + /// @brief bf_mem_op_alloc_page allocates a page, and maps this page + /// into the direct map of the VM. + /// + /// + /// @return Returns a pointer to the newly allocated memory on success, + /// or a nullptr on failure. + /// + [[nodiscard]] constexpr auto + bf_mem_op_alloc_page() noexcept -> void * + { + bf_uint64_t ignored{}; + return this->bf_mem_op_alloc_page(ignored); + } + + /// + /// @brief Frees a page previously allocated by bf_mem_op_alloc_page. + /// This operation is optional and not all microkernels may implement + /// it. + /// + /// + /// @param virt The virtual address of the page to free + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_mem_op_free_page(void *const virt) noexcept -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(nullptr == virt)) { + bsl::error() << "virt is a nullptr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_mem_op_free_page_impl(m_hndl.get(), virt); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_mem_op_free_page failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief bf_mem_op_alloc_huge allocates a physically contiguous block + /// of memory. When allocating a page, the extension should keep in + /// mind the following: + /// - The total memory available to allocate from this pool is + /// extremely limited. This should only be used when absolutely + /// needed, and extensions should not expect more than 1 MB (might + /// be less) of total memory available. + /// - Memory allocated from the huge pool might be allocated using + /// different schemes. For example, the microkernel might allocate + /// in increments of a page, or it might use a buddy allocator that + /// would allocate in multiples of 2. If the allocation size + /// doesn't match the algorithm, internal fragmentation could + /// occur, further limiting the total number of allocations this + /// pool can support. + /// + /// + /// @param size The total number of bytes to allocate + /// @param phys The physical address of the resulting memory + /// @return Returns a pointer to the newly allocated memory on success, + /// or a nullptr on failure. + /// + [[nodiscard]] constexpr auto + bf_mem_op_alloc_huge(bf_uint64_t const &size, bf_uint64_t &phys) noexcept -> void * + { + void *ptr{}; + bf_status_t ret{}; + + if (bsl::unlikely_assert(!size)) { + bsl::error() << "invalid size\n" << bsl::here(); + return nullptr; + } + + if (bsl::unlikely_assert(size.is_zero())) { + bsl::error() << "size cannot be 0\n" << bsl::here(); + return nullptr; + } + + if (bsl::unlikely_assert(!phys)) { + bsl::error() << "invalid phys\n" << bsl::here(); + return nullptr; + } + + ret = bf_mem_op_alloc_huge_impl(m_hndl.get(), size.get(), &ptr, phys.data()); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_mem_op_alloc_huge failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return nullptr; + } + + return ptr; + } + + /// + /// @brief bf_mem_op_alloc_huge allocates a physically contiguous block + /// of memory. When allocating a page, the extension should keep in + /// mind the following: + /// - The total memory available to allocate from this pool is + /// extremely limited. This should only be used when absolutely + /// needed, and extensions should not expect more than 1 MB (might + /// be less) of total memory available. + /// - Memory allocated from the huge pool might be allocated using + /// different schemes. For example, the microkernel might allocate + /// in increments of a page, or it might use a buddy allocator that + /// would allocate in multiples of 2. If the allocation size + /// doesn't match the algorithm, internal fragmentation could + /// occur, further limiting the total number of allocations this + /// pool can support. + /// + /// + /// @param size The total number of bytes to allocate + /// @return Returns a pointer to the newly allocated memory on success, + /// or a nullptr on failure. + /// + [[nodiscard]] constexpr auto + bf_mem_op_alloc_huge(bf_uint64_t const &size) noexcept -> void * + { + bf_uint64_t ignored{}; + return this->bf_mem_op_alloc_huge(size, ignored); + } + + /// + /// @brief Frees memory previously allocated by bf_mem_op_alloc_huge. + /// This operation is optional and not all microkernels may implement + /// it. + /// + /// + /// @param virt The virtual address of the memory to free + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + [[nodiscard]] constexpr auto + bf_mem_op_free_huge(void *const virt) noexcept -> bsl::errc_type + { + bf_status_t ret{}; + + if (bsl::unlikely_assert(nullptr == virt)) { + bsl::error() << "virt is a nullptr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + ret = bf_mem_op_free_huge_impl(m_hndl.get(), virt); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_mem_op_free_huge failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + return bsl::errc_success; + } + + /// + /// @brief bf_mem_op_alloc_heap allocates heap memory. When allocating + /// heap memory, the extension should keep in mind the following: + /// - This ABI is designed to work similar to sbrk() to support + /// malloc/free implementations common with existing open source + /// libraries. + /// - Calling this ABI with with a size of 0 will return the current + /// heap location. + /// - Calling this ABI with a size (in bytes) will result in return + /// the previous heap location. The current heap location will be + /// set to the previous location, plus the provide size, rounded to + /// the nearest page size. + /// - The heap is not mapped into the direct map, so virtual to + /// physical (and vice versa) translations are not possible. + /// - There is no ability to free heap memory + /// + /// + /// @param size The number of bytes to increase the heap by + /// @return Returns a pointer to the newly allocated memory on success, + /// or a nullptr on failure. + /// + [[nodiscard]] constexpr auto + bf_mem_op_alloc_heap(bf_uint64_t const &size) noexcept -> void * + { + void *ptr{}; + bf_status_t ret{}; + + if (bsl::unlikely_assert(!size)) { + bsl::error() << "invalid size\n" << bsl::here(); + return nullptr; + } + + ret = bf_mem_op_alloc_heap_impl(m_hndl.get(), size.get(), &ptr); + if (bsl::unlikely(ret != BF_STATUS_SUCCESS)) { + bsl::error() << "bf_mem_op_alloc_heap failed with status " // -- + << bsl::hex(ret) // -- + << bsl::endl // -- + << bsl::here(); + + return nullptr; + } + + return ptr; + } + + // --------------------------------------------------------------------- + // direct map helpers + // --------------------------------------------------------------------- + + /// + /// @brief Returns the value at the provided physical address + /// on success, or returns bsl::safe_integral::failure() + /// on failure. + /// + /// + /// @tparam T the type of integral to read + /// @param phys the physical address to read + /// @return Returns the value at the provided physical address + /// on success, or returns bsl::safe_integral::failure() + /// on failure. + /// + template + [[nodiscard]] static constexpr auto + bf_read_phys(bf_uint64_t const &phys) noexcept -> bsl::safe_integral + { + static_assert(bsl::is_unsigned::value); + bsl::safe_uintmax virt{}; + + if (bsl::unlikely_assert(!phys)) { + bsl::error() << "invalid phys\n" << bsl::here(); + return bsl::safe_integral::failure(); + } + + if (bsl::unlikely_assert(phys.is_zero())) { + bsl::error() << "phys is a nullptr\n" << bsl::here(); + return bsl::safe_integral::failure(); + } + + virt = phys + HYPERVISOR_EXT_DIRECT_MAP_ADDR; + if (bsl::unlikely_assert(!virt)) { + bsl::error() << "bf_read_phys failed due to invalid physical address " // -- + << bsl::hex(phys) << bsl::endl // -- + << bsl::here(); + + return bsl::safe_integral::failure(); + } + + return bsl::safe_integral{*bsl::to_ptr(virt)}; + } + + /// + /// @brief Writes the provided value at the provided physical address + /// + /// + /// @tparam T the type of integral to write + /// @param phys the physical address to write + /// @param val the value to write to the provided physical address + /// @return Returns bsl::errc_success on success, bsl::errc_failure + /// otherwise + /// + template + [[nodiscard]] static constexpr auto + bf_write_phys(bf_uint64_t const &phys, bsl::safe_integral const &val) noexcept + -> bsl::errc_type + { + static_assert(bsl::is_unsigned::value); + bsl::safe_uintmax virt{}; + + if (bsl::unlikely_assert(!phys)) { + bsl::error() << "invalid phys\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(phys.is_zero())) { + bsl::error() << "phys is a nullptr\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + if (bsl::unlikely_assert(!val)) { + bsl::error() << "invalid val\n" << bsl::here(); + return bsl::errc_invalid_argument; + } + + virt = phys + HYPERVISOR_EXT_DIRECT_MAP_ADDR; + if (bsl::unlikely_assert(!virt)) { + bsl::error() << "bf_write_phys failed due to invalid physical address " // -- + << bsl::hex(phys) << bsl::endl // -- + << bsl::here(); + + return bsl::errc_failure; + } + + *bsl::to_ptr(virt) = val.get(); + return bsl::errc_success; + } + + /// + /// @brief Performs a virtual address to physical address translation. + /// Note that this function only works on direct map memory, which + /// includes direct map addresses, allocated pages and allocated + /// huge memory. + /// + /// + /// @param virt the virtual address to convert + /// @return Returns the resulting physical address + /// + [[nodiscard]] static constexpr auto + bf_virt_to_phys(void *const virt) noexcept -> bf_uint64_t + { + bsl::safe_uintmax phys{}; + + if (bsl::unlikely_assert(nullptr == virt)) { + bsl::error() << "invalid virt\n" << bsl::here(); + return bf_uint64_t::failure(); + } + + phys = bsl::to_umax(virt) - HYPERVISOR_EXT_DIRECT_MAP_ADDR; + if (bsl::unlikely(!phys)) { + bsl::error() << "bf_virt_to_phys arithmetic overflowed\n" << bsl::here(); + return bf_uint64_t::failure(); + } + + return phys; + } + + /// + /// @brief Performs a physical address to virtual address translation. + /// Note that this function only works on direct map memory, which + /// includes direct map addresses, allocated pages and allocated + /// huge memory. + /// + /// + /// @param phys the physical address to convert + /// @return Returns the resulting virtual address + /// + [[nodiscard]] static constexpr auto + bf_phys_to_virt(bf_uint64_t const &phys) noexcept -> void * + { + bsl::safe_uintmax virt{}; + + if (bsl::unlikely_assert(!phys)) { + bsl::error() << "invalid phys\n" << bsl::here(); + return nullptr; + } + + if (bsl::unlikely_assert(phys.is_zero())) { + bsl::error() << "phys is a nullptr\n" << bsl::here(); + return nullptr; + } + + virt = phys + HYPERVISOR_EXT_DIRECT_MAP_ADDR; + if (bsl::unlikely(!virt)) { + bsl::error() << "bf_phys_to_virt arithmetic overflowed\n" << bsl::here(); + return nullptr; + } + + return bsl::to_ptr(virt); + } + }; +} + +#endif diff --git a/syscall/src/x64/bf_callback_op_register_bootstrap_impl.S b/syscall/src/x64/bf_callback_op_register_bootstrap_impl.S index 4dc3a854..e9a02b19 100644 --- a/syscall/src/x64/bf_callback_op_register_bootstrap_impl.S +++ b/syscall/src/x64/bf_callback_op_register_bootstrap_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_callback_op_register_fail_impl.S b/syscall/src/x64/bf_callback_op_register_fail_impl.S index a0a58a5e..82ceb39e 100644 --- a/syscall/src/x64/bf_callback_op_register_fail_impl.S +++ b/syscall/src/x64/bf_callback_op_register_fail_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_callback_op_register_vmexit_impl.S b/syscall/src/x64/bf_callback_op_register_vmexit_impl.S index 30e1c2a1..0b8efcdf 100644 --- a/syscall/src/x64/bf_callback_op_register_vmexit_impl.S +++ b/syscall/src/x64/bf_callback_op_register_vmexit_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_control_op_exit_impl.S b/syscall/src/x64/bf_control_op_exit_impl.S index 67ed1068..4958a0b2 100644 --- a/syscall/src/x64/bf_control_op_exit_impl.S +++ b/syscall/src/x64/bf_control_op_exit_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_mem_op_virt_to_phys_impl.S b/syscall/src/x64/bf_control_op_wait_impl.S similarity index 82% rename from syscall/src/x64/bf_mem_op_virt_to_phys_impl.S rename to syscall/src/x64/bf_control_op_wait_impl.S index a0e24b2f..b898b473 100644 --- a/syscall/src/x64/bf_mem_op_virt_to_phys_impl.S +++ b/syscall/src/x64/bf_control_op_wait_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. @@ -29,16 +27,14 @@ .code64 .intel_syntax noprefix - .globl bf_mem_op_virt_to_phys_impl - .type bf_mem_op_virt_to_phys_impl, @function -bf_mem_op_virt_to_phys_impl: + .globl bf_control_op_wait_impl + .type bf_control_op_wait_impl, @function +bf_control_op_wait_impl: - mov rax, 0x6642000000080006 + mov rax, 0x6642000000000001 syscall - mov [rdx], rdi - ret int 3 - .size bf_mem_op_virt_to_phys_impl, .-bf_mem_op_virt_to_phys_impl + .size bf_control_op_wait_impl, .-bf_control_op_wait_impl diff --git a/syscall/src/x64/bf_callback_op_wait_impl.S b/syscall/src/x64/bf_debug_op_dump_ext_impl.S similarity index 82% rename from syscall/src/x64/bf_callback_op_wait_impl.S rename to syscall/src/x64/bf_debug_op_dump_ext_impl.S index f8419cee..c6790ac9 100644 --- a/syscall/src/x64/bf_callback_op_wait_impl.S +++ b/syscall/src/x64/bf_debug_op_dump_ext_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. @@ -29,14 +27,14 @@ .code64 .intel_syntax noprefix - .globl bf_callback_op_wait_impl - .type bf_callback_op_wait_impl, @function -bf_callback_op_wait_impl: + .globl bf_debug_op_dump_ext_impl + .type bf_debug_op_dump_ext_impl, @function +bf_debug_op_dump_ext_impl: - mov rax, 0x6642000000030000 + mov rax, 0x6642000000020007 syscall ret int 3 - .size bf_callback_op_wait_impl, .-bf_callback_op_wait_impl + .size bf_debug_op_dump_ext_impl, .-bf_debug_op_dump_ext_impl diff --git a/syscall/src/x64/bf_debug_op_dump_huge_pool_impl.S b/syscall/src/x64/bf_debug_op_dump_huge_pool_impl.S new file mode 100644 index 00000000..f9d4edfc --- /dev/null +++ b/syscall/src/x64/bf_debug_op_dump_huge_pool_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_debug_op_dump_huge_pool_impl + .type bf_debug_op_dump_huge_pool_impl, @function +bf_debug_op_dump_huge_pool_impl: + + mov rax, 0x6642000000020009 + syscall + + ret + int 3 + + .size bf_debug_op_dump_huge_pool_impl, .-bf_debug_op_dump_huge_pool_impl diff --git a/syscall/src/x64/bf_debug_op_dump_page_pool_impl.S b/syscall/src/x64/bf_debug_op_dump_page_pool_impl.S new file mode 100644 index 00000000..a2d784a3 --- /dev/null +++ b/syscall/src/x64/bf_debug_op_dump_page_pool_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_debug_op_dump_page_pool_impl + .type bf_debug_op_dump_page_pool_impl, @function +bf_debug_op_dump_page_pool_impl: + + mov rax, 0x6642000000020008 + syscall + + ret + int 3 + + .size bf_debug_op_dump_page_pool_impl, .-bf_debug_op_dump_page_pool_impl diff --git a/syscall/src/x64/bf_debug_op_dump_vm_impl.S b/syscall/src/x64/bf_debug_op_dump_vm_impl.S index efb90bf3..aec9f603 100644 --- a/syscall/src/x64/bf_debug_op_dump_vm_impl.S +++ b/syscall/src/x64/bf_debug_op_dump_vm_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_debug_op_dump_vmexit_log_impl.S b/syscall/src/x64/bf_debug_op_dump_vmexit_log_impl.S index 18e14914..0d11b922 100644 --- a/syscall/src/x64/bf_debug_op_dump_vmexit_log_impl.S +++ b/syscall/src/x64/bf_debug_op_dump_vmexit_log_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_debug_op_dump_vp_impl.S b/syscall/src/x64/bf_debug_op_dump_vp_impl.S index 3dcb2eff..f023a312 100644 --- a/syscall/src/x64/bf_debug_op_dump_vp_impl.S +++ b/syscall/src/x64/bf_debug_op_dump_vp_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_debug_op_dump_vps_impl.S b/syscall/src/x64/bf_debug_op_dump_vps_impl.S index 8514f0b3..0de157b4 100644 --- a/syscall/src/x64/bf_debug_op_dump_vps_impl.S +++ b/syscall/src/x64/bf_debug_op_dump_vps_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_debug_op_out_impl.S b/syscall/src/x64/bf_debug_op_out_impl.S index d96e42be..4b32257b 100644 --- a/syscall/src/x64/bf_debug_op_out_impl.S +++ b/syscall/src/x64/bf_debug_op_out_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_debug_op_write_c_impl.S b/syscall/src/x64/bf_debug_op_write_c_impl.S index 89196ca5..0ddc536e 100644 --- a/syscall/src/x64/bf_debug_op_write_c_impl.S +++ b/syscall/src/x64/bf_debug_op_write_c_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_debug_op_write_str_impl.S b/syscall/src/x64/bf_debug_op_write_str_impl.S index fc460f44..a2197c5a 100644 --- a/syscall/src/x64/bf_debug_op_write_str_impl.S +++ b/syscall/src/x64/bf_debug_op_write_str_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_handle_op_close_handle_impl.S b/syscall/src/x64/bf_handle_op_close_handle_impl.S index 90bf7e25..6baafaba 100644 --- a/syscall/src/x64/bf_handle_op_close_handle_impl.S +++ b/syscall/src/x64/bf_handle_op_close_handle_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_handle_op_open_handle_impl.S b/syscall/src/x64/bf_handle_op_open_handle_impl.S index b47ded01..f78881ad 100644 --- a/syscall/src/x64/bf_handle_op_open_handle_impl.S +++ b/syscall/src/x64/bf_handle_op_open_handle_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_intrinsic_op_invept_impl.S b/syscall/src/x64/bf_intrinsic_op_invept_impl.S new file mode 100644 index 00000000..c19d65b9 --- /dev/null +++ b/syscall/src/x64/bf_intrinsic_op_invept_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_intrinsic_op_invept_impl + .type bf_intrinsic_op_invept_impl, @function +bf_intrinsic_op_invept_impl: + + mov rax, 0x6642000000070003 + syscall + + ret + int 3 + + .size bf_intrinsic_op_invept_impl, .-bf_intrinsic_op_invept_impl diff --git a/syscall/src/x64/bf_intrinsic_op_invlpga_impl.S b/syscall/src/x64/bf_intrinsic_op_invlpga_impl.S new file mode 100644 index 00000000..de288770 --- /dev/null +++ b/syscall/src/x64/bf_intrinsic_op_invlpga_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_intrinsic_op_invlpga_impl + .type bf_intrinsic_op_invlpga_impl, @function +bf_intrinsic_op_invlpga_impl: + + mov rax, 0x6642000000070002 + syscall + + ret + int 3 + + .size bf_intrinsic_op_invlpga_impl, .-bf_intrinsic_op_invlpga_impl diff --git a/syscall/src/x64/bf_intrinsic_op_invvpid_impl.S b/syscall/src/x64/bf_intrinsic_op_invvpid_impl.S new file mode 100644 index 00000000..0578c047 --- /dev/null +++ b/syscall/src/x64/bf_intrinsic_op_invvpid_impl.S @@ -0,0 +1,42 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_intrinsic_op_invvpid_impl + .type bf_intrinsic_op_invvpid_impl, @function +bf_intrinsic_op_invvpid_impl: + + mov r10, rcx + + mov rax, 0x6642000000070004 + syscall + + ret + int 3 + + .size bf_intrinsic_op_invvpid_impl, .-bf_intrinsic_op_invvpid_impl diff --git a/syscall/src/x64/bf_intrinsic_op_read_msr_impl.S b/syscall/src/x64/bf_intrinsic_op_rdmsr_impl.S similarity index 82% rename from syscall/src/x64/bf_intrinsic_op_read_msr_impl.S rename to syscall/src/x64/bf_intrinsic_op_rdmsr_impl.S index e8338cd4..d59c656a 100644 --- a/syscall/src/x64/bf_intrinsic_op_read_msr_impl.S +++ b/syscall/src/x64/bf_intrinsic_op_rdmsr_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. @@ -29,9 +27,9 @@ .code64 .intel_syntax noprefix - .globl bf_intrinsic_op_read_msr_impl - .type bf_intrinsic_op_read_msr_impl, @function -bf_intrinsic_op_read_msr_impl: + .globl bf_intrinsic_op_rdmsr_impl + .type bf_intrinsic_op_rdmsr_impl, @function +bf_intrinsic_op_rdmsr_impl: mov rax, 0x6642000000070000 syscall @@ -41,4 +39,4 @@ bf_intrinsic_op_read_msr_impl: ret int 3 - .size bf_intrinsic_op_read_msr_impl, .-bf_intrinsic_op_read_msr_impl + .size bf_intrinsic_op_rdmsr_impl, .-bf_intrinsic_op_rdmsr_impl diff --git a/syscall/src/x64/bf_intrinsic_op_write_msr_impl.S b/syscall/src/x64/bf_intrinsic_op_wrmsr_impl.S similarity index 82% rename from syscall/src/x64/bf_intrinsic_op_write_msr_impl.S rename to syscall/src/x64/bf_intrinsic_op_wrmsr_impl.S index 46a29ea7..e08849b3 100644 --- a/syscall/src/x64/bf_intrinsic_op_write_msr_impl.S +++ b/syscall/src/x64/bf_intrinsic_op_wrmsr_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. @@ -29,9 +27,9 @@ .code64 .intel_syntax noprefix - .globl bf_intrinsic_op_write_msr_impl - .type bf_intrinsic_op_write_msr_impl, @function -bf_intrinsic_op_write_msr_impl: + .globl bf_intrinsic_op_wrmsr_impl + .type bf_intrinsic_op_wrmsr_impl, @function +bf_intrinsic_op_wrmsr_impl: mov rax, 0x6642000000070001 syscall @@ -39,4 +37,4 @@ bf_intrinsic_op_write_msr_impl: ret int 3 - .size bf_intrinsic_op_write_msr_impl, .-bf_intrinsic_op_write_msr_impl + .size bf_intrinsic_op_wrmsr_impl, .-bf_intrinsic_op_wrmsr_impl diff --git a/kernel/src/x64/smap_guard_t.S b/syscall/src/x64/bf_mem_op_alloc_heap_impl.S similarity index 83% rename from kernel/src/x64/smap_guard_t.S rename to syscall/src/x64/bf_mem_op_alloc_heap_impl.S index a12c0de1..1de4cc0e 100644 --- a/kernel/src/x64/smap_guard_t.S +++ b/syscall/src/x64/bf_mem_op_alloc_heap_impl.S @@ -27,26 +27,16 @@ .code64 .intel_syntax noprefix - .globl unlock_smap - .type unlock_smap, @function -unlock_smap: + .globl bf_mem_op_alloc_heap_impl + .type bf_mem_op_alloc_heap_impl, @function +bf_mem_op_alloc_heap_impl: - stac + mov rax, 0x6642000000080004 + syscall + + mov [rdx], rdi ret int 3 - .size unlock_smap, .-unlock_smap - - - - .globl lock_smap - .type lock_smap, @function -lock_smap: - - clac - - ret - int 3 - - .size lock_smap, .-lock_smap + .size bf_mem_op_alloc_heap_impl, .-bf_mem_op_alloc_heap_impl diff --git a/syscall/src/x64/bf_mem_op_alloc_huge_impl.S b/syscall/src/x64/bf_mem_op_alloc_huge_impl.S new file mode 100644 index 00000000..8e445ad9 --- /dev/null +++ b/syscall/src/x64/bf_mem_op_alloc_huge_impl.S @@ -0,0 +1,45 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_mem_op_alloc_huge_impl + .type bf_mem_op_alloc_huge_impl, @function +bf_mem_op_alloc_huge_impl: + + mov r10, rcx + + mov rax, 0x6642000000080002 + syscall + + mov [rdx], rdi + mov [r10], rsi + + ret + int 3 + + .size bf_mem_op_alloc_huge_impl, .-bf_mem_op_alloc_huge_impl diff --git a/syscall/src/x64/bf_mem_op_alloc_page_impl.S b/syscall/src/x64/bf_mem_op_alloc_page_impl.S index 095e0948..d9e7646d 100644 --- a/syscall/src/x64/bf_mem_op_alloc_page_impl.S +++ b/syscall/src/x64/bf_mem_op_alloc_page_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_mem_op_free_huge_impl.S b/syscall/src/x64/bf_mem_op_free_huge_impl.S new file mode 100644 index 00000000..6fbd91f0 --- /dev/null +++ b/syscall/src/x64/bf_mem_op_free_huge_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_mem_op_free_huge_impl + .type bf_mem_op_free_huge_impl, @function +bf_mem_op_free_huge_impl: + + mov rax, 0x6642000000080003 + syscall + + ret + int 3 + + .size bf_mem_op_free_huge_impl, .-bf_mem_op_free_huge_impl diff --git a/syscall/src/x64/bf_mem_op_free_page_impl.S b/syscall/src/x64/bf_mem_op_free_page_impl.S new file mode 100644 index 00000000..77343001 --- /dev/null +++ b/syscall/src/x64/bf_mem_op_free_page_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_mem_op_free_page_impl + .type bf_mem_op_free_page_impl, @function +bf_mem_op_free_page_impl: + + mov rax, 0x6642000000080001 + syscall + + ret + int 3 + + .size bf_mem_op_free_page_impl, .-bf_mem_op_free_page_impl diff --git a/syscall/src/x64/bf_tls_extid_impl.S b/syscall/src/x64/bf_tls_extid_impl.S new file mode 100644 index 00000000..7dd45539 --- /dev/null +++ b/syscall/src/x64/bf_tls_extid_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_tls_extid_impl + .type bf_tls_extid_impl, @function +bf_tls_extid_impl: + + xor rax, rax + mov ax, fs:[0xFF0] + + ret + int 3 + + .size bf_tls_extid_impl, .-bf_tls_extid_impl diff --git a/syscall/src/x64/bf_tls_online_pps_impl.S b/syscall/src/x64/bf_tls_online_pps_impl.S new file mode 100644 index 00000000..c591235e --- /dev/null +++ b/syscall/src/x64/bf_tls_online_pps_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_tls_ppid_impl + .type bf_tls_ppid_impl, @function +bf_tls_ppid_impl: + + xor rax, rax + mov ax, fs:[0xFF8] + + ret + int 3 + + .size bf_tls_ppid_impl, .-bf_tls_ppid_impl diff --git a/syscall/src/x64/bf_tls_ppid_impl.S b/syscall/src/x64/bf_tls_ppid_impl.S new file mode 100644 index 00000000..8772c604 --- /dev/null +++ b/syscall/src/x64/bf_tls_ppid_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_tls_online_pps_impl + .type bf_tls_online_pps_impl, @function +bf_tls_online_pps_impl: + + xor rax, rax + mov ax, fs:[0xFFA] + + ret + int 3 + + .size bf_tls_online_pps_impl, .-bf_tls_online_pps_impl diff --git a/syscall/src/x64/bf_tls_r10_impl.S b/syscall/src/x64/bf_tls_r10_impl.S index c9f7c553..55842c70 100644 --- a/syscall/src/x64/bf_tls_r10_impl.S +++ b/syscall/src/x64/bf_tls_r10_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_r11_impl.S b/syscall/src/x64/bf_tls_r11_impl.S index cfd01ffe..75519f54 100644 --- a/syscall/src/x64/bf_tls_r11_impl.S +++ b/syscall/src/x64/bf_tls_r11_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_r12_impl.S b/syscall/src/x64/bf_tls_r12_impl.S index d81e6c51..512c6fba 100644 --- a/syscall/src/x64/bf_tls_r12_impl.S +++ b/syscall/src/x64/bf_tls_r12_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_r13_impl.S b/syscall/src/x64/bf_tls_r13_impl.S index 7cbbab6d..af0afe4d 100644 --- a/syscall/src/x64/bf_tls_r13_impl.S +++ b/syscall/src/x64/bf_tls_r13_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_r14_impl.S b/syscall/src/x64/bf_tls_r14_impl.S index 6e79ee7f..88cbcaba 100644 --- a/syscall/src/x64/bf_tls_r14_impl.S +++ b/syscall/src/x64/bf_tls_r14_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_r15_impl.S b/syscall/src/x64/bf_tls_r15_impl.S index 762788da..6fc0cf7b 100644 --- a/syscall/src/x64/bf_tls_r15_impl.S +++ b/syscall/src/x64/bf_tls_r15_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_r8_impl.S b/syscall/src/x64/bf_tls_r8_impl.S index 3ad0cdca..54a739c7 100644 --- a/syscall/src/x64/bf_tls_r8_impl.S +++ b/syscall/src/x64/bf_tls_r8_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_r9_impl.S b/syscall/src/x64/bf_tls_r9_impl.S index 85b9f89d..4ed60bfa 100644 --- a/syscall/src/x64/bf_tls_r9_impl.S +++ b/syscall/src/x64/bf_tls_r9_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_rax_impl.S b/syscall/src/x64/bf_tls_rax_impl.S index f0085c0d..70f8bc29 100644 --- a/syscall/src/x64/bf_tls_rax_impl.S +++ b/syscall/src/x64/bf_tls_rax_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_rbp_impl.S b/syscall/src/x64/bf_tls_rbp_impl.S index ff3e9404..63a5222a 100644 --- a/syscall/src/x64/bf_tls_rbp_impl.S +++ b/syscall/src/x64/bf_tls_rbp_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_rbx_impl.S b/syscall/src/x64/bf_tls_rbx_impl.S index ebe81f6b..3d8e8684 100644 --- a/syscall/src/x64/bf_tls_rbx_impl.S +++ b/syscall/src/x64/bf_tls_rbx_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_rcx_impl.S b/syscall/src/x64/bf_tls_rcx_impl.S index a5c8913f..7670c54a 100644 --- a/syscall/src/x64/bf_tls_rcx_impl.S +++ b/syscall/src/x64/bf_tls_rcx_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_rdi_impl.S b/syscall/src/x64/bf_tls_rdi_impl.S index 91a9989b..7da74655 100644 --- a/syscall/src/x64/bf_tls_rdi_impl.S +++ b/syscall/src/x64/bf_tls_rdi_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_rdx_impl.S b/syscall/src/x64/bf_tls_rdx_impl.S index 58de528e..a4cd7557 100644 --- a/syscall/src/x64/bf_tls_rdx_impl.S +++ b/syscall/src/x64/bf_tls_rdx_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_rsi_impl.S b/syscall/src/x64/bf_tls_rsi_impl.S index 646ab8ed..bf2ba814 100644 --- a/syscall/src/x64/bf_tls_rsi_impl.S +++ b/syscall/src/x64/bf_tls_rsi_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_r10_impl.S b/syscall/src/x64/bf_tls_set_r10_impl.S index fc8abba5..bc5a4577 100644 --- a/syscall/src/x64/bf_tls_set_r10_impl.S +++ b/syscall/src/x64/bf_tls_set_r10_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_r11_impl.S b/syscall/src/x64/bf_tls_set_r11_impl.S index cdbf2fe2..dc8afb59 100644 --- a/syscall/src/x64/bf_tls_set_r11_impl.S +++ b/syscall/src/x64/bf_tls_set_r11_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_r12_impl.S b/syscall/src/x64/bf_tls_set_r12_impl.S index 5f4d7b5e..beadd5b9 100644 --- a/syscall/src/x64/bf_tls_set_r12_impl.S +++ b/syscall/src/x64/bf_tls_set_r12_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_r13_impl.S b/syscall/src/x64/bf_tls_set_r13_impl.S index 9d3306bb..6ba369e9 100644 --- a/syscall/src/x64/bf_tls_set_r13_impl.S +++ b/syscall/src/x64/bf_tls_set_r13_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_r14_impl.S b/syscall/src/x64/bf_tls_set_r14_impl.S index 4c3e9ce0..e3d2a96f 100644 --- a/syscall/src/x64/bf_tls_set_r14_impl.S +++ b/syscall/src/x64/bf_tls_set_r14_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_r15_impl.S b/syscall/src/x64/bf_tls_set_r15_impl.S index b91b02d7..32a7b9bd 100644 --- a/syscall/src/x64/bf_tls_set_r15_impl.S +++ b/syscall/src/x64/bf_tls_set_r15_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_r8_impl.S b/syscall/src/x64/bf_tls_set_r8_impl.S index f52495e7..98d89dd8 100644 --- a/syscall/src/x64/bf_tls_set_r8_impl.S +++ b/syscall/src/x64/bf_tls_set_r8_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_r9_impl.S b/syscall/src/x64/bf_tls_set_r9_impl.S index 39b0ce15..5332b7f5 100644 --- a/syscall/src/x64/bf_tls_set_r9_impl.S +++ b/syscall/src/x64/bf_tls_set_r9_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_rax_impl.S b/syscall/src/x64/bf_tls_set_rax_impl.S index e3c7484c..d70f4e93 100644 --- a/syscall/src/x64/bf_tls_set_rax_impl.S +++ b/syscall/src/x64/bf_tls_set_rax_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_rbp_impl.S b/syscall/src/x64/bf_tls_set_rbp_impl.S index 503da366..0f5703e2 100644 --- a/syscall/src/x64/bf_tls_set_rbp_impl.S +++ b/syscall/src/x64/bf_tls_set_rbp_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_rbx_impl.S b/syscall/src/x64/bf_tls_set_rbx_impl.S index 1d4ad5c3..43b7cdc2 100644 --- a/syscall/src/x64/bf_tls_set_rbx_impl.S +++ b/syscall/src/x64/bf_tls_set_rbx_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_rcx_impl.S b/syscall/src/x64/bf_tls_set_rcx_impl.S index d35385b0..c88b372d 100644 --- a/syscall/src/x64/bf_tls_set_rcx_impl.S +++ b/syscall/src/x64/bf_tls_set_rcx_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_rdi_impl.S b/syscall/src/x64/bf_tls_set_rdi_impl.S index 4030a881..188ae62a 100644 --- a/syscall/src/x64/bf_tls_set_rdi_impl.S +++ b/syscall/src/x64/bf_tls_set_rdi_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_rdx_impl.S b/syscall/src/x64/bf_tls_set_rdx_impl.S index bbc86fde..890c760c 100644 --- a/syscall/src/x64/bf_tls_set_rdx_impl.S +++ b/syscall/src/x64/bf_tls_set_rdx_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_set_rsi_impl.S b/syscall/src/x64/bf_tls_set_rsi_impl.S index db6a034f..98309cdd 100644 --- a/syscall/src/x64/bf_tls_set_rsi_impl.S +++ b/syscall/src/x64/bf_tls_set_rsi_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_thread_id_impl.S b/syscall/src/x64/bf_tls_thread_id_impl.S index dde10a47..92b4622c 100644 --- a/syscall/src/x64/bf_tls_thread_id_impl.S +++ b/syscall/src/x64/bf_tls_thread_id_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_tls_vmid_impl.S b/syscall/src/x64/bf_tls_vmid_impl.S new file mode 100644 index 00000000..72aa56de --- /dev/null +++ b/syscall/src/x64/bf_tls_vmid_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_tls_vmid_impl + .type bf_tls_vmid_impl, @function +bf_tls_vmid_impl: + + xor rax, rax + mov ax, fs:[0xFF2] + + ret + int 3 + + .size bf_tls_vmid_impl, .-bf_tls_vmid_impl diff --git a/syscall/src/x64/bf_tls_vpid_impl.S b/syscall/src/x64/bf_tls_vpid_impl.S new file mode 100644 index 00000000..a7b1ad3f --- /dev/null +++ b/syscall/src/x64/bf_tls_vpid_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_tls_vpid_impl + .type bf_tls_vpid_impl, @function +bf_tls_vpid_impl: + + xor rax, rax + mov ax, fs:[0xFF4] + + ret + int 3 + + .size bf_tls_vpid_impl, .-bf_tls_vpid_impl diff --git a/syscall/src/x64/bf_tls_vpsid_impl.S b/syscall/src/x64/bf_tls_vpsid_impl.S new file mode 100644 index 00000000..250ff250 --- /dev/null +++ b/syscall/src/x64/bf_tls_vpsid_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_tls_vpsid_impl + .type bf_tls_vpsid_impl, @function +bf_tls_vpsid_impl: + + xor rax, rax + mov ax, fs:[0xFF6] + + ret + int 3 + + .size bf_tls_vpsid_impl, .-bf_tls_vpsid_impl diff --git a/syscall/src/x64/bf_vm_op_create_vm_impl.S b/syscall/src/x64/bf_vm_op_create_vm_impl.S index 87075383..f1189ca1 100644 --- a/syscall/src/x64/bf_vm_op_create_vm_impl.S +++ b/syscall/src/x64/bf_vm_op_create_vm_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vm_op_destroy_vm_impl.S b/syscall/src/x64/bf_vm_op_destroy_vm_impl.S index 5da22947..30b9c0ff 100644 --- a/syscall/src/x64/bf_vm_op_destroy_vm_impl.S +++ b/syscall/src/x64/bf_vm_op_destroy_vm_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vp_op_create_vp_impl.S b/syscall/src/x64/bf_vp_op_create_vp_impl.S index 46afeae0..d1022e53 100644 --- a/syscall/src/x64/bf_vp_op_create_vp_impl.S +++ b/syscall/src/x64/bf_vp_op_create_vp_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. @@ -33,10 +31,12 @@ .type bf_vp_op_create_vp_impl, @function bf_vp_op_create_vp_impl: + mov r10, rcx + mov rax, 0x6642000000050000 syscall - mov [rsi], di + mov [r10], di ret int 3 diff --git a/syscall/src/x64/bf_vp_op_destroy_vp_impl.S b/syscall/src/x64/bf_vp_op_destroy_vp_impl.S index 1cec3ba3..233c4c52 100644 --- a/syscall/src/x64/bf_vp_op_destroy_vp_impl.S +++ b/syscall/src/x64/bf_vp_op_destroy_vp_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vp_op_migrate_impl.S b/syscall/src/x64/bf_vp_op_migrate_impl.S new file mode 100644 index 00000000..b2a9ae10 --- /dev/null +++ b/syscall/src/x64/bf_vp_op_migrate_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_vp_op_migrate_impl + .type bf_vp_op_migrate_impl, @function +bf_vp_op_migrate_impl: + + mov rax, 0x6642000000050002 + syscall + + ret + int 3 + + .size bf_vp_op_migrate_impl, .-bf_vp_op_migrate_impl diff --git a/syscall/src/x64/bf_vps_op_advance_ip_and_run_current_impl.S b/syscall/src/x64/bf_vps_op_advance_ip_and_run_current_impl.S index 2715134b..d4e77933 100644 --- a/syscall/src/x64/bf_vps_op_advance_ip_and_run_current_impl.S +++ b/syscall/src/x64/bf_vps_op_advance_ip_and_run_current_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_advance_ip_impl.S b/syscall/src/x64/bf_vps_op_advance_ip_impl.S index 577500e5..c1bc1327 100644 --- a/syscall/src/x64/bf_vps_op_advance_ip_impl.S +++ b/syscall/src/x64/bf_vps_op_advance_ip_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_clear_vps_impl.S b/syscall/src/x64/bf_vps_op_clear_vps_impl.S new file mode 100644 index 00000000..5b214c0f --- /dev/null +++ b/syscall/src/x64/bf_vps_op_clear_vps_impl.S @@ -0,0 +1,40 @@ +/** + * @copyright + * Copyright (C) 2020 Assured Information Security, Inc. + * + * @copyright + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * @copyright + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * @copyright + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + .code64 + .intel_syntax noprefix + + .globl bf_vps_op_clear_vps_impl + .type bf_vps_op_clear_vps_impl, @function +bf_vps_op_clear_vps_impl: + + mov rax, 0x6642000000060012 + syscall + + ret + int 3 + + .size bf_vps_op_clear_vps_impl, .-bf_vps_op_clear_vps_impl diff --git a/syscall/src/x64/bf_vps_op_create_vps_impl.S b/syscall/src/x64/bf_vps_op_create_vps_impl.S index 116d559d..9c54f452 100644 --- a/syscall/src/x64/bf_vps_op_create_vps_impl.S +++ b/syscall/src/x64/bf_vps_op_create_vps_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. @@ -33,10 +31,12 @@ .type bf_vps_op_create_vps_impl, @function bf_vps_op_create_vps_impl: + mov r10, rcx + mov rax, 0x6642000000060000 syscall - mov [rsi], di + mov [r10], di ret int 3 diff --git a/syscall/src/x64/bf_vps_op_destroy_vps_impl.S b/syscall/src/x64/bf_vps_op_destroy_vps_impl.S index 97153c40..2ad5d1d3 100644 --- a/syscall/src/x64/bf_vps_op_destroy_vps_impl.S +++ b/syscall/src/x64/bf_vps_op_destroy_vps_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_init_as_root_impl.S b/syscall/src/x64/bf_vps_op_init_as_root_impl.S index afd619fb..5ef83c0c 100644 --- a/syscall/src/x64/bf_vps_op_init_as_root_impl.S +++ b/syscall/src/x64/bf_vps_op_init_as_root_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_promote_impl.S b/syscall/src/x64/bf_vps_op_promote_impl.S index 5c611b13..35c55f0d 100644 --- a/syscall/src/x64/bf_vps_op_promote_impl.S +++ b/syscall/src/x64/bf_vps_op_promote_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_read16_impl.S b/syscall/src/x64/bf_vps_op_read16_impl.S index d4da7069..8f51ca35 100644 --- a/syscall/src/x64/bf_vps_op_read16_impl.S +++ b/syscall/src/x64/bf_vps_op_read16_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_read32_impl.S b/syscall/src/x64/bf_vps_op_read32_impl.S index b832e04d..fcd93224 100644 --- a/syscall/src/x64/bf_vps_op_read32_impl.S +++ b/syscall/src/x64/bf_vps_op_read32_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_read64_impl.S b/syscall/src/x64/bf_vps_op_read64_impl.S index 505dbd27..478a4aaa 100644 --- a/syscall/src/x64/bf_vps_op_read64_impl.S +++ b/syscall/src/x64/bf_vps_op_read64_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_read8_impl.S b/syscall/src/x64/bf_vps_op_read8_impl.S index 00310267..2ee6e1b6 100644 --- a/syscall/src/x64/bf_vps_op_read8_impl.S +++ b/syscall/src/x64/bf_vps_op_read8_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_read_reg_impl.S b/syscall/src/x64/bf_vps_op_read_reg_impl.S index 6453937c..91d6964c 100644 --- a/syscall/src/x64/bf_vps_op_read_reg_impl.S +++ b/syscall/src/x64/bf_vps_op_read_reg_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_run_current_impl.S b/syscall/src/x64/bf_vps_op_run_current_impl.S index c2e2e5b2..7607c3cb 100644 --- a/syscall/src/x64/bf_vps_op_run_current_impl.S +++ b/syscall/src/x64/bf_vps_op_run_current_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_run_impl.S b/syscall/src/x64/bf_vps_op_run_impl.S index d70bcd49..c6a8a47e 100644 --- a/syscall/src/x64/bf_vps_op_run_impl.S +++ b/syscall/src/x64/bf_vps_op_run_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_write16_impl.S b/syscall/src/x64/bf_vps_op_write16_impl.S index ab25033f..242b6784 100644 --- a/syscall/src/x64/bf_vps_op_write16_impl.S +++ b/syscall/src/x64/bf_vps_op_write16_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_write32_impl.S b/syscall/src/x64/bf_vps_op_write32_impl.S index 10710813..6ef7fd04 100644 --- a/syscall/src/x64/bf_vps_op_write32_impl.S +++ b/syscall/src/x64/bf_vps_op_write32_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_write64_impl.S b/syscall/src/x64/bf_vps_op_write64_impl.S index f8309b55..b1d71c9f 100644 --- a/syscall/src/x64/bf_vps_op_write64_impl.S +++ b/syscall/src/x64/bf_vps_op_write64_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_write8_impl.S b/syscall/src/x64/bf_vps_op_write8_impl.S index a7e1a07d..e1038f7d 100644 --- a/syscall/src/x64/bf_vps_op_write8_impl.S +++ b/syscall/src/x64/bf_vps_op_write8_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/src/x64/bf_vps_op_write_reg_impl.S b/syscall/src/x64/bf_vps_op_write_reg_impl.S index 2a90a741..8e9de2af 100644 --- a/syscall/src/x64/bf_vps_op_write_reg_impl.S +++ b/syscall/src/x64/bf_vps_op_write_reg_impl.S @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: SPDX-License-Identifier: GPL-2.0 OR MIT */ - /** * @copyright * Copyright (C) 2020 Assured Information Security, Inc. diff --git a/syscall/test/.clang-tidy b/syscall/test/.clang-tidy new file mode 100644 index 00000000..074270fc --- /dev/null +++ b/syscall/test/.clang-tidy @@ -0,0 +1,57 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +Checks: + ' + -*, + bsl-*, + -bsl-template-generic-param, + -bsl-literals-user-defined, + -bsl-lambda-implicit-capture, + -bsl-using-ident-unique-namespace, + bugprone-*, + -bugprone-branch-clone, + cert-*, + -cert-dcl21-cpp, + -cert-oop54-cpp, + clang-analyzer-*, + -clang-analyzer-core.CallAndMessage, + cppcoreguidelines-*, + -cppcoreguidelines-avoid-non-const-global-variables, + hicpp-*, + -hicpp-function-size, + misc-*, + -misc-misplaced-const, + -misc-non-private-member-variables-in-classes, + modernize-*, + -modernize-use-default-member-init, + performance-*, + readability-*, + -readability-redundant-member-init, + -readability-avoid-const-params-in-decls, + -readability-static-accessed-through-instance, + -readability-function-size + ' +WarningsAsErrors: '*' +HeaderFilterRegex: '.*' +AnalyzeTemporaryDtors: false +FormatStyle: none +UseColor: true diff --git a/syscall/test/CMakeLists.txt b/syscall/test/CMakeLists.txt new file mode 100644 index 00000000..98098a37 --- /dev/null +++ b/syscall/test/CMakeLists.txt @@ -0,0 +1,54 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +include(${bsl_SOURCE_DIR}/cmake/function/bf_add_test.cmake) + +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + +list(APPEND INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../include/cpp + ${CMAKE_CURRENT_LIST_DIR}/../mocks/cpp +) + +# ------------------------------------------------------------------------------ +# Definitions +# ------------------------------------------------------------------------------ + +list(APPEND DEFINES + HYPERVISOR_PAGE_SIZE=0x1000_umax + HYPERVISOR_EXT_DIRECT_MAP_ADDR=0x1000_umax +) + +# ------------------------------------------------------------------------------ +# Tests +# ------------------------------------------------------------------------------ + +add_subdirectory(mocks/cpp/bf_control_ops) +add_subdirectory(mocks/cpp/bf_debug_ops) +add_subdirectory(mocks/cpp/bf_syscall_impl) +add_subdirectory(mocks/cpp/bf_syscall_t) + +add_subdirectory(src/cpp/bf_control_ops) +add_subdirectory(src/cpp/bf_debug_ops) +add_subdirectory(src/cpp/bf_syscall_impl) +add_subdirectory(src/cpp/bf_syscall_t) diff --git a/syscall/test/mocks/cpp/bf_control_ops/CMakeLists.txt b/syscall/test/mocks/cpp/bf_control_ops/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/syscall/test/mocks/cpp/bf_control_ops/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/syscall/test/mocks/cpp/bf_control_ops/behavior.cpp b/syscall/test/mocks/cpp/bf_control_ops/behavior.cpp new file mode 100644 index 00000000..ff248f51 --- /dev/null +++ b/syscall/test/mocks/cpp/bf_control_ops/behavior.cpp @@ -0,0 +1,86 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../mocks/cpp/bf_control_ops.hpp" + +#include + +namespace syscall +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"bf_control_op_exit"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_control_op_exit_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_control_op_exit(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_control_op_exit_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_control_op_wait"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_control_op_wait_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_control_op_wait(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(syscall::tests() == bsl::ut_success()); + return syscall::tests(); +} diff --git a/syscall/test/mocks/cpp/bf_control_ops/requirements.cpp b/syscall/test/mocks/cpp/bf_control_ops/requirements.cpp new file mode 100644 index 00000000..65c72e81 --- /dev/null +++ b/syscall/test/mocks/cpp/bf_control_ops/requirements.cpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../mocks/cpp/bf_control_ops.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(syscall::bf_control_op_exit())); + static_assert(noexcept(syscall::bf_control_op_wait())); + }; + }; + + return bsl::ut_success(); +} diff --git a/syscall/test/mocks/cpp/bf_debug_ops/CMakeLists.txt b/syscall/test/mocks/cpp/bf_debug_ops/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/syscall/test/mocks/cpp/bf_debug_ops/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/syscall/test/mocks/cpp/bf_debug_ops/behavior.cpp b/syscall/test/mocks/cpp/bf_debug_ops/behavior.cpp new file mode 100644 index 00000000..9e315b58 --- /dev/null +++ b/syscall/test/mocks/cpp/bf_debug_ops/behavior.cpp @@ -0,0 +1,183 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../mocks/cpp/bf_debug_ops.hpp" + +#include +#include + +namespace syscall +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"bf_debug_op_out"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_out_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_out({}, {}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_out_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vm"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_vm_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_vm({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vm_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vp"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_vp_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_vp({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vp_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vps"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_vps_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_vps({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vps_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vmexit_log"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_vmexit_log_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_vmexit_log({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vmexit_log_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_write_c"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_write_c_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_write_c({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_write_c_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_write_str"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_write_str_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_write_str({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_write_str_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_ext"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_ext_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_ext({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_ext_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_page_pool"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_page_pool_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_page_pool(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_page_pool_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_huge_pool"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_huge_pool_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_huge_pool(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_huge_pool_impl_executed); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(syscall::tests() == bsl::ut_success()); + return syscall::tests(); +} diff --git a/syscall/test/mocks/cpp/bf_debug_ops/requirements.cpp b/syscall/test/mocks/cpp/bf_debug_ops/requirements.cpp new file mode 100644 index 00000000..0e3a8168 --- /dev/null +++ b/syscall/test/mocks/cpp/bf_debug_ops/requirements.cpp @@ -0,0 +1,58 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../mocks/cpp/bf_debug_ops.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(syscall::bf_debug_op_out({}, {}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vm({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vp({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vps({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vmexit_log({}))); + static_assert(noexcept(syscall::bf_debug_op_write_c({}))); + static_assert(noexcept(syscall::bf_debug_op_write_str({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_ext({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_page_pool())); + static_assert(noexcept(syscall::bf_debug_op_dump_huge_pool())); + }; + }; + + return bsl::ut_success(); +} diff --git a/syscall/test/mocks/cpp/bf_syscall_impl/CMakeLists.txt b/syscall/test/mocks/cpp/bf_syscall_impl/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/syscall/test/mocks/cpp/bf_syscall_impl/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/syscall/test/mocks/cpp/bf_syscall_impl/behavior.cpp b/syscall/test/mocks/cpp/bf_syscall_impl/behavior.cpp new file mode 100644 index 00000000..c6999dbc --- /dev/null +++ b/syscall/test/mocks/cpp/bf_syscall_impl/behavior.cpp @@ -0,0 +1,1891 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../mocks/cpp/bf_syscall_impl.hpp" + +#include +#include + +#include + +namespace syscall +{ + // ------------------------------------------------------------------------- + // constants + // ------------------------------------------------------------------------- + + /// @brief stores the answer to all things (in 8 bits) + constexpr auto ANSWER8{42_u8}; + /// @brief stores the answer to all things (in 16 bits) + constexpr auto ANSWER16{42_u16}; + /// @brief stores the answer to all things (in 32 bits) + constexpr auto ANSWER32{42_u32}; + /// @brief stores the answer to all things (in 64 bits) + constexpr auto ANSWER64{42_u64}; + + // ------------------------------------------------------------------------- + // tests + // ------------------------------------------------------------------------- + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"quiet dummy_bootstrap_entry"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint16_t arg0{}; + bsl::ut_then{} = [&]() noexcept { + dummy_bootstrap_entry(arg0.get()); + }; + }; + }; + + bsl::ut_scenario{"quiet dummy_vmexit_entry"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + dummy_vmexit_entry(arg0.get(), arg1.get()); + }; + }; + }; + + bsl::ut_scenario{"quiet dummy_fail_entry"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + dummy_fail_entry(arg0.get(), arg1.get()); + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rax_impl/bf_tls_set_rax_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_rax_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_rax_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rbx_impl/bf_tls_set_rbx_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_rbx_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_rbx_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rcx_impl/bf_tls_set_rcx_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_rcx_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_rcx_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rdx_impl/bf_tls_set_rdx_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_rdx_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_rdx_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rbp_impl/bf_tls_set_rbp_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_rbp_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_rbp_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rsi_impl/bf_tls_set_rsi_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_rsi_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_rsi_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rdi_impl/bf_tls_set_rdi_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_rdi_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_rdi_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r8_impl/bf_tls_set_r8_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_r8_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_r8_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r9_impl/bf_tls_set_r9_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_r9_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_r9_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r10_impl/bf_tls_set_r10_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_r10_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_r10_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r11_impl/bf_tls_set_r11_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_r11_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_r11_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r12_impl/bf_tls_set_r12_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_r12_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_r12_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r13_impl/bf_tls_set_r13_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_r13_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_r13_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r14_impl/bf_tls_set_r14_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_r14_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_r14_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r15_impl/bf_tls_set_r15_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + bf_tls_set_r15_impl(ANSWER64.get()); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER64 == bf_tls_r15_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_extid_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + g_data.at("bf_tls_extid") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER16 == bf_tls_extid_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_vmid_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + g_data.at("bf_tls_vmid") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER16 == bf_tls_vmid_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_vpid_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + g_data.at("bf_tls_vpid") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER16 == bf_tls_vpid_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_vpsid_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + g_data.at("bf_tls_vpsid") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER16 == bf_tls_vpsid_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_ppid_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + g_data.at("bf_tls_ppid") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER16 == bf_tls_ppid_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_online_pps_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_data.clear(); + g_data.at("bf_tls_online_pps") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(ANSWER16 == bf_tls_online_pps_impl()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_control_op_exit_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_control_op_exit_impl_executed = {}; + bf_control_op_exit_impl(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_control_op_exit_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_control_op_wait_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_control_op_wait_impl_executed = {}; + bf_control_op_wait_impl(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_handle_op_open_handle_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_handle_op_open_handle_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_handle_op_open_handle_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint64_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_handle_op_open_handle_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_handle_op_open_handle_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_handle_op_open_handle_impl({}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg0_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_handle_op_open_handle_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint64_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_handle_op_open_handle_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_handle_op_open_handle_impl({}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER64 == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_handle_op_close_handle_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_handle_op_close_handle_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_handle_op_close_handle_impl({})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_handle_op_close_handle_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_handle_op_close_handle_impl({})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_out_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_debug_op_out_impl_executed = {}; + bf_debug_op_out_impl({}, {}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_out_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vm_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_debug_op_dump_vm_impl_executed = {}; + bf_debug_op_dump_vm_impl({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vm_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vp_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_debug_op_dump_vp_impl_executed = {}; + bf_debug_op_dump_vp_impl({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vp_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vps_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_debug_op_dump_vps_impl_executed = {}; + bf_debug_op_dump_vps_impl({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vps_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vmexit_log_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_debug_op_dump_vmexit_log_impl_executed = {}; + bf_debug_op_dump_vmexit_log_impl({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vmexit_log_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vmexit_log_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_debug_op_dump_vmexit_log_impl_executed = {}; + bf_debug_op_dump_vmexit_log_impl({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vmexit_log_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_write_c_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_debug_op_write_c_impl_executed = {}; + bf_debug_op_write_c_impl({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_write_c_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_write_str_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_debug_op_write_str_impl_executed = {}; + bf_debug_op_write_str_impl({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_write_str_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_ext_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_debug_op_dump_ext_impl_executed = {}; + bf_debug_op_dump_ext_impl({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_ext_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_page_pool_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_debug_op_dump_page_pool_impl_executed = {}; + bf_debug_op_dump_page_pool_impl(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_page_pool_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_huge_pool_impl"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_bf_debug_op_dump_huge_pool_impl_executed = {}; + bf_debug_op_dump_huge_pool_impl(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_huge_pool_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_callback_op_register_bootstrap_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_callback_op_register_bootstrap_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_callback_op_register_bootstrap_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_callback_op_register_bootstrap_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_callback_op_register_bootstrap_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_callback_op_register_vmexit_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_callback_op_register_vmexit_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_callback_op_register_vmexit_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_callback_op_register_vmexit_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_callback_op_register_vmexit_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_callback_op_register_fail_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_callback_op_register_fail_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_callback_op_register_fail_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_callback_op_register_fail_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_callback_op_register_fail_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_create_vm_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vm_op_create_vm_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_create_vm_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint16_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vm_op_create_vm_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vm_op_create_vm_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vm_op_create_vm_impl({}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg0_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_create_vm_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint16_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vm_op_create_vm_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vm_op_create_vm_impl({}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER16 == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_destroy_vm_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vm_op_destroy_vm_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vm_op_destroy_vm_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_destroy_vm_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vm_op_destroy_vm_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_create_vp_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vp_op_create_vp_impl({}, {}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_create_vp_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint16_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vp_op_create_vp_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vp_op_create_vp_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vp_op_create_vp_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg0_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_create_vp_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint16_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vp_op_create_vp_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vp_op_create_vp_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER16 == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_destroy_vp_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vp_op_destroy_vp_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vp_op_destroy_vp_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_destroy_vp_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vp_op_destroy_vp_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_migrate_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vp_op_migrate_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vp_op_migrate_impl({}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_migrate_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vp_op_migrate_impl({}, {}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_create_vps_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_create_vps_impl({}, {}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_create_vps_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint16_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_create_vps_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_create_vps_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{ + bf_vps_op_create_vps_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg0_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_create_vps_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint16_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_create_vps_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{ + bf_vps_op_create_vps_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER16 == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_destroy_vps_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_destroy_vps_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_destroy_vps_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_destroy_vps_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_destroy_vps_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_init_as_root_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_init_as_root_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_init_as_root_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_init_as_root_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_init_as_root_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read8_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_read8_impl({}, {}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read8_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint8_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_read8_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_read8_impl_reg0_out") = bsl::to_u64(ANSWER8); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vps_op_read8_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg0_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read8_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint8_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read8_impl_reg0_out") = bsl::to_u64(ANSWER8); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vps_op_read8_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER8 == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read16_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_read16_impl({}, {}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read16_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint16_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_read16_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_read16_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vps_op_read16_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg0_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read16_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint16_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read16_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vps_op_read16_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER16 == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read32_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_read32_impl({}, {}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read32_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint32_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_read32_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_read32_impl_reg0_out") = bsl::to_u64(ANSWER32); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vps_op_read32_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg0_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read32_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint32_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read32_impl_reg0_out") = bsl::to_u64(ANSWER32); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vps_op_read32_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER32 == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read64_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_read64_impl({}, {}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read64_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint64_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_read64_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_read64_impl_reg0_out") = bsl::to_u64(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vps_op_read64_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg0_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read64_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint64_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read64_impl_reg0_out") = bsl::to_u64(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vps_op_read64_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER64 == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_write8_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_write8_impl({}, {}, {}, ANSWER8.get())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(g_data.at("bf_vps_op_write8_impl").is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_write8_impl({}, {}, {}, ANSWER8.get())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(g_data.at("bf_vps_op_write8_impl") == bsl::to_u64(ANSWER8)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_write16_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_write16_impl({}, {}, {}, ANSWER16.get())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(g_data.at("bf_vps_op_write16_impl").is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_write16_impl({}, {}, {}, ANSWER16.get())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(g_data.at("bf_vps_op_write16_impl") == bsl::to_u64(ANSWER16)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_write32_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_write32_impl({}, {}, {}, ANSWER32.get())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(g_data.at("bf_vps_op_write32_impl").is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_write32_impl({}, {}, {}, ANSWER32.get())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(g_data.at("bf_vps_op_write32_impl") == bsl::to_u64(ANSWER32)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_write64_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_write64_impl({}, {}, {}, ANSWER64.get())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(g_data.at("bf_vps_op_write64_impl").is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_write64_impl({}, {}, {}, ANSWER64.get())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(g_data.at("bf_vps_op_write64_impl") == bsl::to_u64(ANSWER64)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read_reg_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_read_reg_impl({}, {}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read_reg_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint64_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_read_reg_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_read_reg_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vps_op_read_reg_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg0_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read_reg_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint64_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read_reg_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_vps_op_read_reg_impl({}, {}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER64 == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write_reg_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_write_reg_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_write_reg_impl({}, {}, {}, ANSWER64.get())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(g_data.at("bf_vps_op_write_reg_impl").is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write_reg_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_write_reg_impl({}, {}, {}, ANSWER64.get())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(g_data.at("bf_vps_op_write_reg_impl") == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_run_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_run_impl({}, {}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_run_impl({}, {}, {}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run_current_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_run_current_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_run_current_impl({})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run_current_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_run_current_impl({})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_advance_ip_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_advance_ip_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_advance_ip_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip_and_run_current_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_advance_ip_and_run_current_impl") = + BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_advance_ip_and_run_current_impl({})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip_and_run_current_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_advance_ip_and_run_current_impl({})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_promote_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_promote_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_promote_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_promote_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_promote_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_clear_vps_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_clear_vps_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_clear_vps_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_clear_vps_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_vps_op_clear_vps_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_rdmsr_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_intrinsic_op_rdmsr_impl({}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_rdmsr_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint64_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_intrinsic_op_rdmsr_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_intrinsic_op_rdmsr_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_intrinsic_op_rdmsr_impl({}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg0_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_rdmsr_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint64_t reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_intrinsic_op_rdmsr_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_intrinsic_op_rdmsr_impl({}, {}, reg0_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER64 == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_wrmsr_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_intrinsic_op_wrmsr_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_intrinsic_op_wrmsr_impl({}, {}, ANSWER64.get())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(g_data.at("bf_intrinsic_op_wrmsr_impl").is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_wrmsr_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_intrinsic_op_wrmsr_impl({}, {}, ANSWER64.get())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(g_data.at("bf_intrinsic_op_wrmsr_impl") == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invlpga_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_intrinsic_op_invlpga_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_intrinsic_op_invlpga_impl({}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invlpga_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_intrinsic_op_invlpga_impl({}, {}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invept_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_intrinsic_op_invept_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_intrinsic_op_invept_impl({}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invept_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_intrinsic_op_invept_impl({}, {}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_intrinsic_op_invvpid_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_intrinsic_op_invvpid_impl({}, {}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_intrinsic_op_invvpid_impl({}, {}, {}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_page_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint64_t reg1_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_page_impl_reg1_out") = bsl::to_umax(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_mem_op_alloc_page_impl({}, {}, reg1_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg1_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_page_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + void *reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_page_impl_reg0_out") = bsl::to_umax(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_mem_op_alloc_page_impl({}, ®0_out, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(nullptr == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_page_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + void *reg0_out{}; + bf_uint64_t reg1_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_mem_op_alloc_page_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_mem_op_alloc_page_impl_reg0_out") = bsl::to_umax(ANSWER64); + g_data.at("bf_mem_op_alloc_page_impl_reg1_out") = bsl::to_umax(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{ + bf_mem_op_alloc_page_impl({}, ®0_out, reg1_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(nullptr == reg0_out); + bsl::ut_check(reg1_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_page_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + void *reg0_out{}; + bf_uint64_t reg1_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_mem_op_alloc_page_impl") = BF_STATUS_SUCCESS; + g_data.at("bf_mem_op_alloc_page_impl_reg0_out") = bsl::to_umax(ANSWER64); + g_data.at("bf_mem_op_alloc_page_impl_reg1_out") = bsl::to_umax(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{ + bf_mem_op_alloc_page_impl({}, ®0_out, reg1_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER64 == bsl::to_umax(reg0_out)); + bsl::ut_check(ANSWER64 == reg1_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_page_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_mem_op_free_page_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_mem_op_free_page_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_page_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_mem_op_free_page_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_uint64_t reg1_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_huge_impl_reg1_out") = bsl::to_umax(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{ + bf_mem_op_alloc_huge_impl({}, {}, {}, reg1_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(reg1_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + void *reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_huge_impl_reg0_out") = bsl::to_umax(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_mem_op_alloc_huge_impl({}, {}, ®0_out, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(nullptr == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + void *reg0_out{}; + bf_uint64_t reg1_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_mem_op_alloc_huge_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_mem_op_alloc_huge_impl_reg0_out") = bsl::to_umax(ANSWER64); + g_data.at("bf_mem_op_alloc_huge_impl_reg1_out") = bsl::to_umax(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{ + bf_mem_op_alloc_huge_impl({}, {}, ®0_out, reg1_out.data())}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(nullptr == reg0_out); + bsl::ut_check(reg1_out.is_zero()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + void *reg0_out{}; + bf_uint64_t reg1_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_mem_op_alloc_huge_impl") = BF_STATUS_SUCCESS; + g_data.at("bf_mem_op_alloc_huge_impl_reg0_out") = bsl::to_umax(ANSWER64); + g_data.at("bf_mem_op_alloc_huge_impl_reg1_out") = bsl::to_umax(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{ + bf_mem_op_alloc_huge_impl({}, {}, ®0_out, reg1_out.data())}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER64 == bsl::to_umax(reg0_out)); + bsl::ut_check(ANSWER64 == reg1_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_huge_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_mem_op_free_huge_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_mem_op_free_huge_impl({}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_huge_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_mem_op_free_huge_impl({}, {})}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_heap_impl invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bsl::ut_when{} = []() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = []() noexcept { + bf_status_t const ret{bf_mem_op_alloc_heap_impl({}, {}, {})}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_heap_impl failure"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + void *reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_mem_op_alloc_heap_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_mem_op_alloc_heap_impl_reg0_out") = bsl::to_umax(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_mem_op_alloc_heap_impl({}, {}, ®0_out)}; + bsl::ut_check(BF_STATUS_FAILURE_UNKNOWN == ret); + bsl::ut_check(nullptr == reg0_out); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_heap_impl success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + void *reg0_out{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_heap_impl_reg0_out") = bsl::to_u64(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bf_status_t const ret{bf_mem_op_alloc_heap_impl({}, {}, ®0_out)}; + bsl::ut_check(BF_STATUS_SUCCESS == ret); + bsl::ut_check(ANSWER64 == bsl::to_umax(reg0_out)); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(syscall::tests() == bsl::ut_success()); + return syscall::tests(); +} diff --git a/syscall/test/mocks/cpp/bf_syscall_impl/requirements.cpp b/syscall/test/mocks/cpp/bf_syscall_impl/requirements.cpp new file mode 100644 index 00000000..843895d6 --- /dev/null +++ b/syscall/test/mocks/cpp/bf_syscall_impl/requirements.cpp @@ -0,0 +1,139 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../mocks/cpp/bf_syscall_impl.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(syscall::dummy_bootstrap_entry({}))); + static_assert(noexcept(syscall::dummy_vmexit_entry({}, {}))); + static_assert(noexcept(syscall::dummy_fail_entry({}, {}))); + static_assert(noexcept(syscall::bf_tls_set_rax_impl({}))); + static_assert(noexcept(syscall::bf_tls_rax_impl())); + static_assert(noexcept(syscall::bf_tls_set_rbx_impl({}))); + static_assert(noexcept(syscall::bf_tls_rbx_impl())); + static_assert(noexcept(syscall::bf_tls_set_rcx_impl({}))); + static_assert(noexcept(syscall::bf_tls_rcx_impl())); + static_assert(noexcept(syscall::bf_tls_set_rdx_impl({}))); + static_assert(noexcept(syscall::bf_tls_rdx_impl())); + static_assert(noexcept(syscall::bf_tls_set_rbp_impl({}))); + static_assert(noexcept(syscall::bf_tls_rbp_impl())); + static_assert(noexcept(syscall::bf_tls_set_rsi_impl({}))); + static_assert(noexcept(syscall::bf_tls_rsi_impl())); + static_assert(noexcept(syscall::bf_tls_set_rdi_impl({}))); + static_assert(noexcept(syscall::bf_tls_rdi_impl())); + static_assert(noexcept(syscall::bf_tls_set_r8_impl({}))); + static_assert(noexcept(syscall::bf_tls_r8_impl())); + static_assert(noexcept(syscall::bf_tls_set_r9_impl({}))); + static_assert(noexcept(syscall::bf_tls_r9_impl())); + static_assert(noexcept(syscall::bf_tls_set_r10_impl({}))); + static_assert(noexcept(syscall::bf_tls_r10_impl())); + static_assert(noexcept(syscall::bf_tls_set_r11_impl({}))); + static_assert(noexcept(syscall::bf_tls_r11_impl())); + static_assert(noexcept(syscall::bf_tls_set_r12_impl({}))); + static_assert(noexcept(syscall::bf_tls_r12_impl())); + static_assert(noexcept(syscall::bf_tls_set_r13_impl({}))); + static_assert(noexcept(syscall::bf_tls_r13_impl())); + static_assert(noexcept(syscall::bf_tls_set_r14_impl({}))); + static_assert(noexcept(syscall::bf_tls_r14_impl())); + static_assert(noexcept(syscall::bf_tls_set_r15_impl({}))); + static_assert(noexcept(syscall::bf_tls_r15_impl())); + static_assert(noexcept(syscall::bf_tls_extid_impl())); + static_assert(noexcept(syscall::bf_tls_vmid_impl())); + static_assert(noexcept(syscall::bf_tls_vpid_impl())); + static_assert(noexcept(syscall::bf_tls_vpsid_impl())); + static_assert(noexcept(syscall::bf_tls_ppid_impl())); + static_assert(noexcept(syscall::bf_tls_online_pps_impl())); + static_assert(noexcept(syscall::bf_control_op_exit_impl())); + static_assert(noexcept(syscall::bf_control_op_wait_impl())); + static_assert(noexcept(syscall::bf_handle_op_open_handle_impl({}, {}))); + static_assert(noexcept(syscall::bf_handle_op_close_handle_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_out_impl({}, {}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vm_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vp_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vps_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vmexit_log_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vmexit_log_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_write_c_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_write_str_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_ext_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_page_pool_impl())); + static_assert(noexcept(syscall::bf_debug_op_dump_huge_pool_impl())); + static_assert(noexcept(syscall::bf_callback_op_register_bootstrap_impl({}, {}))); + static_assert(noexcept(syscall::bf_callback_op_register_vmexit_impl({}, {}))); + static_assert(noexcept(syscall::bf_callback_op_register_fail_impl({}, {}))); + static_assert(noexcept(syscall::bf_vm_op_create_vm_impl({}, {}))); + static_assert(noexcept(syscall::bf_vm_op_destroy_vm_impl({}, {}))); + static_assert(noexcept(syscall::bf_vp_op_create_vp_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vp_op_destroy_vp_impl({}, {}))); + static_assert(noexcept(syscall::bf_vp_op_migrate_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_create_vps_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_destroy_vps_impl({}, {}))); + static_assert(noexcept(syscall::bf_vps_op_init_as_root_impl({}, {}))); + static_assert(noexcept(syscall::bf_vps_op_read8_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_read16_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_read32_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_read64_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_write8_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_write16_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_write32_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_write64_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_read_reg_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_write_reg_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_run_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_run_current_impl({}))); + static_assert(noexcept(syscall::bf_vps_op_advance_ip_impl({}, {}))); + static_assert(noexcept(syscall::bf_vps_op_advance_ip_and_run_current_impl({}))); + static_assert(noexcept(syscall::bf_vps_op_promote_impl({}, {}))); + static_assert(noexcept(syscall::bf_vps_op_clear_vps_impl({}, {}))); + static_assert(noexcept(syscall::bf_intrinsic_op_rdmsr_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_intrinsic_op_wrmsr_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_intrinsic_op_invlpga_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_intrinsic_op_invept_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_intrinsic_op_invvpid_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_mem_op_alloc_page_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_mem_op_free_page_impl({}, {}))); + static_assert(noexcept(syscall::bf_mem_op_alloc_huge_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_mem_op_free_huge_impl({}, {}))); + static_assert(noexcept(syscall::bf_mem_op_alloc_heap_impl({}, {}, {}))); + }; + }; + + return bsl::ut_success(); +} diff --git a/syscall/test/mocks/cpp/bf_syscall_t/CMakeLists.txt b/syscall/test/mocks/cpp/bf_syscall_t/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/syscall/test/mocks/cpp/bf_syscall_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/syscall/test/mocks/cpp/bf_syscall_t/behavior.cpp b/syscall/test/mocks/cpp/bf_syscall_t/behavior.cpp new file mode 100644 index 00000000..6965541d --- /dev/null +++ b/syscall/test/mocks/cpp/bf_syscall_t/behavior.cpp @@ -0,0 +1,2684 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../mocks/cpp/bf_syscall_t.hpp" + +#include +#include + +namespace syscall +{ + // ------------------------------------------------------------------------- + // constants + // ------------------------------------------------------------------------- + + /// @brief stores the answer to all things (in 8 bits) + constexpr auto ANSWER8{42_u8}; + /// @brief stores the answer to all things (in 16 bits) + constexpr auto ANSWER16{42_u16}; + /// @brief stores the answer to all things (in 32 bits) + constexpr auto ANSWER32{42_u32}; + /// @brief stores the answer to all things (in 64 bits) + constexpr auto ANSWER64{42_u64}; + + /// @brief stores a bad address + constexpr auto BAD_ADDR{0xFFFFFFFFFFFFFFFF_u64}; + /// @brief stores a bad version + constexpr auto BAD_VERSION{0x80000000_u32}; + + // ------------------------------------------------------------------------- + // tests + // ------------------------------------------------------------------------- + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize invalid version #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + bf_uint32_t::failure(), // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + + bsl::ut_scenario{"initialize invalid version #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + {}, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + + bsl::ut_scenario{"initialize invalid bootstrap_handler"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + BF_ALL_SPECS_SUPPORTED_VAL, // -- + {}, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + + bsl::ut_scenario{"initialize invalid vmexit_handler"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + {}, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + + bsl::ut_scenario{"initialize invalid fail_handler"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + {})); // -- + }; + }; + }; + + bsl::ut_scenario{"initialize bf_is_spec1_supported fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + BAD_VERSION, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize bf_handle_op_open_handle_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize bf_callback_op_register_bootstrap_impl fails"} = + []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize bf_callback_op_register_vmexit_impl fail"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize bf_callback_op_register_fail_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_initialize(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.initialize( + BF_ALL_SPECS_SUPPORTED_VAL, + &dummy_bootstrap_entry, + &dummy_vmexit_entry, + &dummy_fail_entry)); + }; + }; + }; + + bsl::ut_scenario{"release"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_then{} = [&]() noexcept { + sys.release(); + }; + }; + }; + + // --------------------------------------------------------------------- + // TLS ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_tls_rax/bf_tls_set_rax"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rax()); + bsl::ut_check(sys.bf_tls_rax().is_zero()); + }; + + sys.bf_tls_set_rax(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rax() == ANSWER64); + }; + + sys.bf_tls_set_rax(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rax() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rbx/bf_tls_set_rbx"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbx()); + bsl::ut_check(sys.bf_tls_rbx().is_zero()); + }; + + sys.bf_tls_set_rbx(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbx() == ANSWER64); + }; + + sys.bf_tls_set_rbx(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbx() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rcx/bf_tls_set_rcx"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rcx()); + bsl::ut_check(sys.bf_tls_rcx().is_zero()); + }; + + sys.bf_tls_set_rcx(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rcx() == ANSWER64); + }; + + sys.bf_tls_set_rcx(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rcx() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rdx/bf_tls_set_rdx"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdx()); + bsl::ut_check(sys.bf_tls_rdx().is_zero()); + }; + + sys.bf_tls_set_rdx(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdx() == ANSWER64); + }; + + sys.bf_tls_set_rdx(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdx() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rbp/bf_tls_set_rbp"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbp()); + bsl::ut_check(sys.bf_tls_rbp().is_zero()); + }; + + sys.bf_tls_set_rbp(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbp() == ANSWER64); + }; + + sys.bf_tls_set_rbp(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbp() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rsi/bf_tls_set_rsi"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rsi()); + bsl::ut_check(sys.bf_tls_rsi().is_zero()); + }; + + sys.bf_tls_set_rsi(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rsi() == ANSWER64); + }; + + sys.bf_tls_set_rsi(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rsi() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rdi/bf_tls_set_rdi"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdi()); + bsl::ut_check(sys.bf_tls_rdi().is_zero()); + }; + + sys.bf_tls_set_rdi(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdi() == ANSWER64); + }; + + sys.bf_tls_set_rdi(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdi() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r8/bf_tls_set_r8"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r8()); + bsl::ut_check(sys.bf_tls_r8().is_zero()); + }; + + sys.bf_tls_set_r8(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r8() == ANSWER64); + }; + + sys.bf_tls_set_r8(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r8() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r9/bf_tls_set_r9"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r9()); + bsl::ut_check(sys.bf_tls_r9().is_zero()); + }; + + sys.bf_tls_set_r9(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r9() == ANSWER64); + }; + + sys.bf_tls_set_r9(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r9() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r10/bf_tls_set_r10"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r10()); + bsl::ut_check(sys.bf_tls_r10().is_zero()); + }; + + sys.bf_tls_set_r10(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r10() == ANSWER64); + }; + + sys.bf_tls_set_r10(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r10() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r11/bf_tls_set_r11"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r11()); + bsl::ut_check(sys.bf_tls_r11().is_zero()); + }; + + sys.bf_tls_set_r11(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r11() == ANSWER64); + }; + + sys.bf_tls_set_r11(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r11() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r12/bf_tls_set_r12"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r12()); + bsl::ut_check(sys.bf_tls_r12().is_zero()); + }; + + sys.bf_tls_set_r12(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r12() == ANSWER64); + }; + + sys.bf_tls_set_r12(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r12() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r13/bf_tls_set_r13"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r13()); + bsl::ut_check(sys.bf_tls_r13().is_zero()); + }; + + sys.bf_tls_set_r13(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r13() == ANSWER64); + }; + + sys.bf_tls_set_r13(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r13() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r14/bf_tls_set_r14"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r14()); + bsl::ut_check(sys.bf_tls_r14().is_zero()); + }; + + sys.bf_tls_set_r14(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r14() == ANSWER64); + }; + + sys.bf_tls_set_r14(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r14() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r15/bf_tls_set_r15"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r15()); + bsl::ut_check(sys.bf_tls_r15().is_zero()); + }; + + sys.bf_tls_set_r15(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r15() == ANSWER64); + }; + + sys.bf_tls_set_r15(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r15() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_extid/bf_tls_set_extid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_extid()); + bsl::ut_check(sys.bf_tls_extid().is_zero()); + }; + + sys.bf_tls_set_extid(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_extid() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_vmid/bf_tls_set_vmid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vmid()); + bsl::ut_check(sys.bf_tls_vmid().is_zero()); + }; + + sys.bf_tls_set_vmid(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vmid() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_vpid/bf_tls_set_vpid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vpid()); + bsl::ut_check(sys.bf_tls_vpid().is_zero()); + }; + + sys.bf_tls_set_vpid(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vpid() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_vpsid/bf_tls_set_vpsid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vpsid()); + bsl::ut_check(sys.bf_tls_vpsid().is_zero()); + }; + + sys.bf_tls_set_vpsid(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vpsid() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_ppid/bf_tls_set_ppid"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_ppid()); + bsl::ut_check(sys.bf_tls_ppid().is_zero()); + }; + + sys.bf_tls_set_ppid(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_ppid() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_online_pps/bf_tls_set_online_pps"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_online_pps()); + bsl::ut_check(sys.bf_tls_online_pps().is_zero()); + }; + + sys.bf_tls_set_online_pps(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_online_pps() == ANSWER16); + }; + }; + }; + }; + + // --------------------------------------------------------------------- + // bf_vm_ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_vm_op_create_vm bf_vm_op_create_vm_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vm_op_create_vm(bf_uint16_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vm_op_create_vm()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_create_vm success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vm_op_create_vm(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vm_op_create_vm() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_destroy_vm invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vm_op_destroy_vm(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_destroy_vm bf_vm_op_destroy_vm_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vm_op_destroy_vm(arg0, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vm_op_destroy_vm(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_destroy_vm success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vm_op_destroy_vm(arg0)); + }; + }; + }; + + // --------------------------------------------------------------------- + // bf_vp_ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_vp_op_create_vp invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint16_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_create_vp(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_create_vp invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_create_vp(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_create_vp bf_vp_op_create_vp_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vp_op_create_vp(arg0, arg1, bf_uint16_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_create_vp(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_create_vp success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vp_op_create_vp(arg0, arg1, ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vp_op_create_vp(arg0, arg1) == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_destroy_vp invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_destroy_vp(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_destroy_vp bf_vp_op_destroy_vp_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vp_op_destroy_vp(arg0, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_destroy_vp(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_destroy_vp success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vp_op_destroy_vp(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_migrate invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint16_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_migrate(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_migrate invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_migrate(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_migrate bf_vp_op_migrate_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vp_op_migrate(arg0, arg1, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_migrate(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_migrate success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vp_op_migrate(arg0, arg1)); + }; + }; + }; + + // --------------------------------------------------------------------- + // bf_vps_ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_vps_op_create_vps invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint16_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_create_vps(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_create_vps invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_create_vps(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_create_vps bf_vps_op_create_vps_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_create_vps(arg0, arg1, bf_uint16_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_create_vps(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_create_vps success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_create_vps(arg0, arg1, ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_create_vps(arg0, arg1) == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_destroy_vps invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_destroy_vps(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_destroy_vps bf_vps_op_destroy_vps_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_destroy_vps(arg0, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_destroy_vps(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_destroy_vps success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_destroy_vps(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_init_as_root invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_init_as_root(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_init_as_root bf_vps_op_init_as_root_impl fails"} = + []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_init_as_root(arg0, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_init_as_root(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_init_as_root success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_init_as_root(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read8 invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read8(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read8 invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read8(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read8 bf_vps_op_read8_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_read8(arg0, arg1, bf_uint8_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read8(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read8 success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_read8(arg0, arg1, ANSWER8); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_read8(arg0, arg1) == ANSWER8); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read16 invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read16(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read16 invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read16(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read16 bf_vps_op_read16_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_read16(arg0, arg1, bf_uint16_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read16(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read16 success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_read16(arg0, arg1, ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_read16(arg0, arg1) == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read32 invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read32(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read32 invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read32(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read32 bf_vps_op_read32_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_read32(arg0, arg1, bf_uint32_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read32(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read32 success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_read32(arg0, arg1, ANSWER32); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_read32(arg0, arg1) == ANSWER32); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read64 invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read64(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read64 invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read64(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read64 bf_vps_op_read64_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_read64(arg0, arg1, bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read64(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read64 success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_read64(arg0, arg1, ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_read64(arg0, arg1) == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8 invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bf_uint8_t arg2{ANSWER8}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write8(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8 invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bf_uint8_t arg2{ANSWER8}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write8(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8 invalid arg2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint8_t arg2{bf_uint8_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write8(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8 bf_vps_op_write8_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint8_t arg2{ANSWER8}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_write8(arg0, arg1, arg2, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write8(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8 success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint8_t arg2{ANSWER8}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_write8(arg0, arg1, arg2)); + bsl::ut_check(sys.bf_vps_op_read8(arg0, arg1) == arg2); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16 invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bf_uint16_t arg2{ANSWER16}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write16(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16 invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bf_uint16_t arg2{ANSWER16}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write16(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16 invalid arg2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint16_t arg2{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write16(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16 bf_vps_op_write16_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint16_t arg2{ANSWER16}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_write16(arg0, arg1, arg2, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write16(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16 success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint16_t arg2{ANSWER16}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_write16(arg0, arg1, arg2)); + bsl::ut_check(sys.bf_vps_op_read16(arg0, arg1) == arg2); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32 invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bf_uint32_t arg2{ANSWER32}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write32(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32 invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bf_uint32_t arg2{ANSWER32}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write32(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32 invalid arg2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint32_t arg2{bf_uint32_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write32(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32 bf_vps_op_write32_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint32_t arg2{ANSWER32}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_write32(arg0, arg1, arg2, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write32(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32 success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint32_t arg2{ANSWER32}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_write32(arg0, arg1, arg2)); + bsl::ut_check(sys.bf_vps_op_read32(arg0, arg1) == arg2); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64 invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write64(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64 invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write64(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64 invalid arg2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint64_t arg2{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write64(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64 bf_vps_op_write64_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_write64(arg0, arg1, arg2, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write64(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64 success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_write64(arg0, arg1, arg2)); + bsl::ut_check(sys.bf_vps_op_read64(arg0, arg1) == arg2); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read_reg invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_reg_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read_reg(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read_reg bf_vps_op_read_reg_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_reg_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_read_reg(arg0, arg1, bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read_reg(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read_reg success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_reg_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_read_reg(arg0, arg1, ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_read_reg(arg0, arg1) == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write_reg invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_reg_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write_reg(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write_reg invalid arg2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_reg_t arg1{}; + bf_uint64_t arg2{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write_reg(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write_reg bf_vps_op_write_reg_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_reg_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_write_reg(arg0, arg1, arg2, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write_reg(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write_reg success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_reg_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_write_reg(arg0, arg1, arg2)); + bsl::ut_check(sys.bf_vps_op_read_reg(arg0, arg1) == arg2); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint16_t arg1{}; + bf_uint16_t arg2{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_run(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{bf_uint16_t::failure()}; + bf_uint16_t arg2{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_run(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run invalid arg2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bf_uint16_t arg2{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_run(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run bf_vps_op_run_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bf_uint16_t arg2{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_run(arg0, arg1, arg2, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_run(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bf_uint16_t arg2{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_run(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run_current bf_vps_op_run_current_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_run_current(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_run_current()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run_current success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_run_current()); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_advance_ip(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip bf_vps_op_advance_ip_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_advance_ip(arg0, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_advance_ip(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_advance_ip(arg0)); + }; + }; + }; + + bsl::ut_scenario{ + "bf_vps_op_advance_ip_and_run_current bf_vps_op_advance_ip_and_run_current_impl " + "fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_advance_ip_and_run_current(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_advance_ip_and_run_current()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip_and_run_current success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_advance_ip_and_run_current()); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_promote invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_promote(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_promote bf_vps_op_promote_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_promote(arg0, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_promote(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_promote success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_promote(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_clear_vps invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_clear_vps(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_clear_vps bf_vps_op_clear_vps_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_vps_op_clear_vps(arg0, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_clear_vps(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_clear_vps success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_clear_vps(arg0)); + }; + }; + }; + + // --------------------------------------------------------------------- + // bf_intrinsic_ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_intrinsic_op_rdmsr invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{bf_uint32_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_rdmsr(arg0)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_rdmsr bf_intrinsic_op_rdmsr_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_intrinsic_op_rdmsr(arg0, bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_rdmsr(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_rdmsr success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_intrinsic_op_rdmsr(arg0, ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_intrinsic_op_rdmsr(arg0) == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_wrmsr invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{bf_uint32_t::failure()}; + bf_uint64_t arg1{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_wrmsr(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_wrmsr invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_wrmsr(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_wrmsr bf_intrinsic_op_wrmsr_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{}; + bf_uint64_t arg1{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_intrinsic_op_wrmsr(arg0, arg1, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_wrmsr(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_wrmsr success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{}; + bf_uint64_t arg1{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_intrinsic_op_wrmsr(arg0, arg1)); + bsl::ut_check(sys.bf_intrinsic_op_rdmsr(arg0) == arg1); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invlpga invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{bf_uint64_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invlpga(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invlpga invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invlpga(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invlpga bf_intrinsic_op_invlpga_impl fails"} = + []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_intrinsic_op_invlpga(arg0, arg1, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invlpga(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invlpga success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_intrinsic_op_invlpga(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invept invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{bf_uint64_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invept(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invept invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invept(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invept bf_intrinsic_op_invept_impl fails"} = + []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_intrinsic_op_invept(arg0, arg1, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invept(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invept success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_intrinsic_op_invept(arg0, arg1)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid invalid arg0"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{bf_uint64_t::failure()}; + bf_uint16_t arg1{}; + bf_uint64_t arg2{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invvpid(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid invalid arg1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint16_t arg1{bf_uint16_t::failure()}; + bf_uint64_t arg2{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invvpid(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid invalid arg2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint16_t arg1{}; + bf_uint64_t arg2{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invvpid(arg0, arg1, arg2)); + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid bf_intrinsic_op_invvpid_impl fails"} = + []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint16_t arg1{}; + bf_uint64_t arg2{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_intrinsic_op_invvpid(arg0, arg1, arg2, bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invvpid(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint16_t arg1{}; + bf_uint64_t arg2{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_intrinsic_op_invvpid(arg0, arg1, arg2)); + }; + }; + }; + + // --------------------------------------------------------------------- + // bf_mem_ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_mem_op_alloc_page invalid phys"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_page(phys) == nullptr); + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_page bf_mem_op_alloc_page_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_mem_op_alloc_page(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_page(phys) == nullptr); + bsl::ut_check(sys.bf_mem_op_alloc_page() == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_page success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + void *ptr{}; + bsl::ut_when{} = [&]() noexcept { + ptr = sys.bf_mem_op_alloc_page(phys); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(ptr != nullptr); + bsl::ut_check(sys.bf_mem_op_free_page(ptr)); + }; + }; + + bsl::ut_when{} = [&]() noexcept { + ptr = sys.bf_mem_op_alloc_page(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(ptr != nullptr); + bsl::ut_check(sys.bf_mem_op_free_page(ptr)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_page invalid ptr"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + void *ptr{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_mem_op_free_page(ptr)); + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_page failure/success/failure"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + void *ptr{}; + bsl::ut_when{} = [&]() noexcept { + ptr = sys.bf_mem_op_alloc_page(); + sys.set_bf_mem_op_free_page(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_mem_op_free_page(ptr)); + }; + + sys.set_bf_mem_op_free_page(bsl::errc_success); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_free_page(ptr)); + }; + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_mem_op_free_page(ptr)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge invalid size #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{bf_uint64_t::failure()}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_huge(size, phys) == nullptr); + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge invalid size #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_huge(size, phys) == nullptr); + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge invalid phys"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{ANSWER64}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_huge(size, phys) == nullptr); + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge bf_mem_op_alloc_huge_impl fails"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{ANSWER64}; + bf_uint64_t phys{}; + bsl::ut_when{} = [&]() noexcept { + sys.set_bf_mem_op_alloc_huge(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_huge(size, phys) == nullptr); + bsl::ut_check(sys.bf_mem_op_alloc_huge(size) == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{ANSWER64}; + bf_uint64_t phys{}; + void *ptr{}; + bsl::ut_when{} = [&]() noexcept { + ptr = sys.bf_mem_op_alloc_huge(size, phys); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(ptr != nullptr); + bsl::ut_check(sys.bf_mem_op_free_huge(ptr)); + }; + }; + + bsl::ut_when{} = [&]() noexcept { + ptr = sys.bf_mem_op_alloc_huge(size); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(ptr != nullptr); + bsl::ut_check(sys.bf_mem_op_free_huge(ptr)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_huge invalid ptr"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + void *ptr{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_mem_op_free_huge(ptr)); + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_huge failure/success/failure"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{ANSWER64}; + void *ptr{}; + bsl::ut_when{} = [&]() noexcept { + ptr = sys.bf_mem_op_alloc_huge(size); + sys.set_bf_mem_op_free_huge(bsl::errc_failure); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_mem_op_free_huge(ptr)); + }; + + sys.set_bf_mem_op_free_huge(bsl::errc_success); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_free_huge(ptr)); + }; + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_mem_op_free_huge(ptr)); + }; + }; + }; + }; + + bsl::ut_scenario{"quiet bf_mem_op_alloc_heap"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_heap(ANSWER64) == nullptr); + }; + }; + }; + + // --------------------------------------------------------------------- + // direct map helpers + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_read_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(sys.bf_write_phys(phys, ANSWER8)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER8); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(sys.bf_write_phys(phys, ANSWER16)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(sys.bf_write_phys(phys, ANSWER32)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER32); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(sys.bf_write_phys(phys, ANSWER64)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bf_uint8_t val{ANSWER8}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bf_uint8_t val{ANSWER8}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid val"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint8_t val{bf_uint8_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bf_uint8_t val{ANSWER8}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint8_t val{ANSWER8}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_write_phys(phys, val)); + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER8); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bf_uint16_t val{ANSWER16}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bf_uint16_t val{ANSWER16}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid val"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint16_t val{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bf_uint16_t val{ANSWER16}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint16_t val{ANSWER16}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_write_phys(phys, val)); + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER16); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bf_uint32_t val{ANSWER32}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bf_uint32_t val{ANSWER32}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid val"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint32_t val{bf_uint32_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bf_uint32_t val{ANSWER32}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint32_t val{ANSWER32}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_write_phys(phys, val)); + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER32); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bf_uint64_t val{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bf_uint64_t val{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid val"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint64_t val{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bf_uint64_t val{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint64_t val{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_write_phys(phys, val)); + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER64); + }; + }; + }; + + bsl::ut_scenario{"bf_virt_to_phys invalid virt"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + void *virt{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_virt_to_phys(virt)); + }; + }; + }; + + bsl::ut_scenario{"bf_virt_to_phys virt not allocated properly"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + void *virt{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_virt_to_phys(&virt)); + }; + }; + }; + + bsl::ut_scenario{"bf_virt_to_phys success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + void *virt{}; + bsl::ut_when{} = [&]() noexcept { + virt = sys.bf_mem_op_alloc_page(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_virt_to_phys(virt)); + bsl::ut_check(sys.bf_mem_op_free_page(virt)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_phys_to_virt invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_phys_to_virt(phys) == nullptr); + }; + }; + }; + + bsl::ut_scenario{"bf_phys_to_virt invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_phys_to_virt(phys) == nullptr); + }; + }; + }; + + bsl::ut_scenario{"bf_phys_to_virt phys not allocated properly"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_phys_to_virt(phys) == nullptr); + }; + }; + }; + + bsl::ut_scenario{"bf_phys_to_virt success"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + void *virt{}; + bf_uint64_t phys{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + virt = sys.bf_mem_op_alloc_page(phys); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_phys_to_virt(phys) == virt); + bsl::ut_check(sys.bf_mem_op_free_page(virt)); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(syscall::tests() == bsl::ut_success()); + return syscall::tests(); +} diff --git a/syscall/test/mocks/cpp/bf_syscall_t/requirements.cpp b/syscall/test/mocks/cpp/bf_syscall_t/requirements.cpp new file mode 100644 index 00000000..9d76299e --- /dev/null +++ b/syscall/test/mocks/cpp/bf_syscall_t/requirements.cpp @@ -0,0 +1,365 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../mocks/cpp/bf_syscall_t.hpp" + +#include +#include + +namespace syscall +{ + constinit bf_syscall_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + bf_syscall_t m_sys{}; + + public: + [[nodiscard]] constexpr auto + test_member_const() const noexcept -> bool + { + bsl::discard(m_sys.bf_tls_rax()); + bsl::discard(m_sys.bf_tls_rbx()); + bsl::discard(m_sys.bf_tls_rcx()); + bsl::discard(m_sys.bf_tls_rdx()); + bsl::discard(m_sys.bf_tls_rbp()); + bsl::discard(m_sys.bf_tls_rsi()); + bsl::discard(m_sys.bf_tls_rdi()); + bsl::discard(m_sys.bf_tls_r8()); + bsl::discard(m_sys.bf_tls_r9()); + bsl::discard(m_sys.bf_tls_r10()); + bsl::discard(m_sys.bf_tls_r11()); + bsl::discard(m_sys.bf_tls_r12()); + bsl::discard(m_sys.bf_tls_r13()); + bsl::discard(m_sys.bf_tls_r14()); + bsl::discard(m_sys.bf_tls_r15()); + bsl::discard(m_sys.bf_tls_extid()); + bsl::discard(m_sys.bf_tls_vmid()); + bsl::discard(m_sys.bf_tls_vpid()); + bsl::discard(m_sys.bf_tls_vpsid()); + bsl::discard(m_sys.bf_tls_ppid()); + bsl::discard(m_sys.bf_tls_online_pps()); + bsl::discard(m_sys.bf_vps_op_read8({}, {})); + bsl::discard(m_sys.bf_vps_op_read16({}, {})); + bsl::discard(m_sys.bf_vps_op_read32({}, {})); + bsl::discard(m_sys.bf_vps_op_read64({}, {})); + bsl::discard(m_sys.bf_vps_op_read_reg({}, {})); + bsl::discard(m_sys.bf_intrinsic_op_rdmsr({})); + bsl::discard(m_sys.bf_read_phys({})); + bsl::discard(m_sys.bf_virt_to_phys({})); + bsl::discard(m_sys.bf_phys_to_virt({})); + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + bf_uint64_t phys{}; + + bsl::discard(bf_syscall_t{}); + bsl::discard(m_sys.initialize({}, {}, {}, {})); + m_sys.set_initialize({}); + m_sys.release(); + bsl::discard(m_sys.bf_tls_rax()); + m_sys.bf_tls_set_rax({}); + bsl::discard(m_sys.bf_tls_rbx()); + m_sys.bf_tls_set_rbx({}); + bsl::discard(m_sys.bf_tls_rcx()); + m_sys.bf_tls_set_rcx({}); + bsl::discard(m_sys.bf_tls_rdx()); + m_sys.bf_tls_set_rdx({}); + bsl::discard(m_sys.bf_tls_rbp()); + m_sys.bf_tls_set_rbp({}); + bsl::discard(m_sys.bf_tls_rsi()); + m_sys.bf_tls_set_rsi({}); + bsl::discard(m_sys.bf_tls_rdi()); + m_sys.bf_tls_set_rdi({}); + bsl::discard(m_sys.bf_tls_r8()); + m_sys.bf_tls_set_r8({}); + bsl::discard(m_sys.bf_tls_r9()); + m_sys.bf_tls_set_r9({}); + bsl::discard(m_sys.bf_tls_r10()); + m_sys.bf_tls_set_r10({}); + bsl::discard(m_sys.bf_tls_r11()); + m_sys.bf_tls_set_r11({}); + bsl::discard(m_sys.bf_tls_r12()); + m_sys.bf_tls_set_r12({}); + bsl::discard(m_sys.bf_tls_r13()); + m_sys.bf_tls_set_r13({}); + bsl::discard(m_sys.bf_tls_r14()); + m_sys.bf_tls_set_r14({}); + bsl::discard(m_sys.bf_tls_r15()); + m_sys.bf_tls_set_r15({}); + bsl::discard(m_sys.bf_tls_extid()); + m_sys.bf_tls_set_extid({}); + bsl::discard(m_sys.bf_tls_vmid()); + m_sys.bf_tls_set_vmid({}); + bsl::discard(m_sys.bf_tls_vpid()); + m_sys.bf_tls_set_vpid({}); + bsl::discard(m_sys.bf_tls_vpsid()); + m_sys.bf_tls_set_vpsid({}); + bsl::discard(m_sys.bf_tls_ppid()); + m_sys.bf_tls_set_ppid({}); + bsl::discard(m_sys.bf_tls_online_pps()); + m_sys.bf_tls_set_online_pps({}); + bsl::discard(m_sys.bf_vm_op_create_vm()); + m_sys.set_bf_vm_op_create_vm({}); + bsl::discard(m_sys.bf_vm_op_destroy_vm({})); + m_sys.set_bf_vm_op_destroy_vm({}, {}); + bsl::discard(m_sys.bf_vp_op_create_vp({}, {})); + m_sys.set_bf_vp_op_create_vp({}, {}, {}); + bsl::discard(m_sys.bf_vp_op_destroy_vp({})); + m_sys.set_bf_vp_op_destroy_vp({}, {}); + bsl::discard(m_sys.bf_vp_op_migrate({}, {})); + m_sys.set_bf_vp_op_migrate({}, {}, {}); + bsl::discard(m_sys.bf_vps_op_create_vps({}, {})); + m_sys.set_bf_vps_op_create_vps({}, {}, {}); + bsl::discard(m_sys.bf_vps_op_destroy_vps({})); + m_sys.set_bf_vps_op_destroy_vps({}, {}); + bsl::discard(m_sys.bf_vps_op_init_as_root({})); + m_sys.set_bf_vps_op_init_as_root({}, {}); + bsl::discard(m_sys.bf_vps_op_read8({}, {})); + m_sys.set_bf_vps_op_read8({}, {}, {}); + bsl::discard(m_sys.bf_vps_op_read16({}, {})); + m_sys.set_bf_vps_op_read16({}, {}, {}); + bsl::discard(m_sys.bf_vps_op_read32({}, {})); + m_sys.set_bf_vps_op_read32({}, {}, {}); + bsl::discard(m_sys.bf_vps_op_read64({}, {})); + m_sys.set_bf_vps_op_read64({}, {}, {}); + bsl::discard(m_sys.bf_vps_op_write8({}, {}, {})); + m_sys.set_bf_vps_op_write8({}, {}, {}, {}); + bsl::discard(m_sys.bf_vps_op_write16({}, {}, {})); + m_sys.set_bf_vps_op_write16({}, {}, {}, {}); + bsl::discard(m_sys.bf_vps_op_write32({}, {}, {})); + m_sys.set_bf_vps_op_write32({}, {}, {}, {}); + bsl::discard(m_sys.bf_vps_op_write64({}, {}, {})); + m_sys.set_bf_vps_op_write64({}, {}, {}, {}); + bsl::discard(m_sys.bf_vps_op_read_reg({}, {})); + m_sys.set_bf_vps_op_read_reg({}, {}, {}); + bsl::discard(m_sys.bf_vps_op_write_reg({}, {}, {})); + m_sys.set_bf_vps_op_write_reg({}, {}, {}, {}); + bsl::discard(m_sys.bf_vps_op_run({}, {}, {})); + m_sys.set_bf_vps_op_run({}, {}, {}, {}); + bsl::discard(m_sys.bf_vps_op_run_current()); + m_sys.set_bf_vps_op_run_current({}); + bsl::discard(m_sys.bf_vps_op_advance_ip({})); + m_sys.set_bf_vps_op_advance_ip({}, {}); + bsl::discard(m_sys.bf_vps_op_advance_ip_and_run_current()); + m_sys.set_bf_vps_op_advance_ip_and_run_current({}); + bsl::discard(m_sys.bf_vps_op_promote({})); + m_sys.set_bf_vps_op_promote({}, {}); + bsl::discard(m_sys.bf_vps_op_clear_vps({})); + m_sys.set_bf_vps_op_clear_vps({}, {}); + bsl::discard(m_sys.bf_intrinsic_op_rdmsr({})); + m_sys.set_bf_intrinsic_op_rdmsr({}, {}); + bsl::discard(m_sys.bf_intrinsic_op_wrmsr({}, {})); + m_sys.set_bf_intrinsic_op_wrmsr({}, {}, {}); + bsl::discard(m_sys.bf_intrinsic_op_invlpga({}, {})); + m_sys.set_bf_intrinsic_op_invlpga({}, {}, {}); + bsl::discard(m_sys.bf_intrinsic_op_invept({}, {})); + m_sys.set_bf_intrinsic_op_invept({}, {}, {}); + bsl::discard(m_sys.bf_intrinsic_op_invvpid({}, {}, {})); + m_sys.set_bf_intrinsic_op_invvpid({}, {}, {}, {}); + bsl::discard(m_sys.bf_mem_op_free_page(m_sys.bf_mem_op_alloc_page(phys))); + bsl::discard(m_sys.bf_mem_op_free_page(m_sys.bf_mem_op_alloc_page())); + m_sys.set_bf_mem_op_alloc_page({}); + bsl::discard(m_sys.bf_mem_op_free_page({})); + m_sys.set_bf_mem_op_free_page({}); + bsl::discard( + m_sys.bf_mem_op_free_huge(m_sys.bf_mem_op_alloc_huge(HYPERVISOR_PAGE_SIZE, phys))); + bsl::discard( + m_sys.bf_mem_op_free_huge(m_sys.bf_mem_op_alloc_huge(HYPERVISOR_PAGE_SIZE))); + m_sys.set_bf_mem_op_alloc_huge({}); + bsl::discard(m_sys.bf_mem_op_free_huge({})); + m_sys.set_bf_mem_op_free_huge({}); + bsl::discard(m_sys.bf_mem_op_alloc_heap({})); + bsl::discard(m_sys.bf_read_phys({})); + bsl::discard(m_sys.bf_write_phys({}, {})); + bsl::discard(m_sys.bf_virt_to_phys({})); + bsl::discard(m_sys.bf_phys_to_virt({})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(syscall::g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + syscall::bf_syscall_t sys{}; + syscall::bf_uint64_t phys{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(syscall::bf_syscall_t{})); + static_assert(noexcept(sys.initialize({}, {}, {}, {}))); + static_assert(noexcept(sys.set_initialize({}))); + static_assert(noexcept(sys.release())); + static_assert(noexcept(sys.bf_tls_rax())); + static_assert(noexcept(sys.bf_tls_set_rax({}))); + static_assert(noexcept(sys.bf_tls_rbx())); + static_assert(noexcept(sys.bf_tls_set_rbx({}))); + static_assert(noexcept(sys.bf_tls_rcx())); + static_assert(noexcept(sys.bf_tls_set_rcx({}))); + static_assert(noexcept(sys.bf_tls_rdx())); + static_assert(noexcept(sys.bf_tls_set_rdx({}))); + static_assert(noexcept(sys.bf_tls_rbp())); + static_assert(noexcept(sys.bf_tls_set_rbp({}))); + static_assert(noexcept(sys.bf_tls_rsi())); + static_assert(noexcept(sys.bf_tls_set_rsi({}))); + static_assert(noexcept(sys.bf_tls_rdi())); + static_assert(noexcept(sys.bf_tls_set_rdi({}))); + static_assert(noexcept(sys.bf_tls_r8())); + static_assert(noexcept(sys.bf_tls_set_r8({}))); + static_assert(noexcept(sys.bf_tls_r9())); + static_assert(noexcept(sys.bf_tls_set_r9({}))); + static_assert(noexcept(sys.bf_tls_r10())); + static_assert(noexcept(sys.bf_tls_set_r10({}))); + static_assert(noexcept(sys.bf_tls_r11())); + static_assert(noexcept(sys.bf_tls_set_r11({}))); + static_assert(noexcept(sys.bf_tls_r12())); + static_assert(noexcept(sys.bf_tls_set_r12({}))); + static_assert(noexcept(sys.bf_tls_r13())); + static_assert(noexcept(sys.bf_tls_set_r13({}))); + static_assert(noexcept(sys.bf_tls_r14())); + static_assert(noexcept(sys.bf_tls_set_r14({}))); + static_assert(noexcept(sys.bf_tls_r15())); + static_assert(noexcept(sys.bf_tls_set_r15({}))); + static_assert(noexcept(sys.bf_tls_extid())); + static_assert(noexcept(sys.bf_tls_set_extid({}))); + static_assert(noexcept(sys.bf_tls_vmid())); + static_assert(noexcept(sys.bf_tls_set_vmid({}))); + static_assert(noexcept(sys.bf_tls_vpid())); + static_assert(noexcept(sys.bf_tls_set_vpid({}))); + static_assert(noexcept(sys.bf_tls_vpsid())); + static_assert(noexcept(sys.bf_tls_set_vpsid({}))); + static_assert(noexcept(sys.bf_tls_ppid())); + static_assert(noexcept(sys.bf_tls_set_ppid({}))); + static_assert(noexcept(sys.bf_tls_online_pps())); + static_assert(noexcept(sys.bf_tls_set_online_pps({}))); + static_assert(noexcept(sys.bf_vm_op_create_vm())); + static_assert(noexcept(sys.set_bf_vm_op_create_vm({}))); + static_assert(noexcept(sys.bf_vm_op_destroy_vm({}))); + static_assert(noexcept(sys.set_bf_vm_op_destroy_vm({}, {}))); + static_assert(noexcept(sys.bf_vp_op_create_vp({}, {}))); + static_assert(noexcept(sys.set_bf_vp_op_create_vp({}, {}, {}))); + static_assert(noexcept(sys.bf_vp_op_destroy_vp({}))); + static_assert(noexcept(sys.set_bf_vp_op_destroy_vp({}, {}))); + static_assert(noexcept(sys.bf_vp_op_migrate({}, {}))); + static_assert(noexcept(sys.set_bf_vp_op_migrate({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_create_vps({}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_create_vps({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_destroy_vps({}))); + static_assert(noexcept(sys.set_bf_vps_op_destroy_vps({}, {}))); + static_assert(noexcept(sys.bf_vps_op_init_as_root({}))); + static_assert(noexcept(sys.set_bf_vps_op_init_as_root({}, {}))); + static_assert(noexcept(sys.bf_vps_op_read8({}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_read8({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_read16({}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_read16({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_read32({}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_read32({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_read64({}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_read64({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_write8({}, {}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_write8({}, {}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_write16({}, {}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_write16({}, {}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_write32({}, {}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_write32({}, {}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_write64({}, {}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_write64({}, {}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_read_reg({}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_read_reg({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_write_reg({}, {}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_write_reg({}, {}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_run({}, {}, {}))); + static_assert(noexcept(sys.set_bf_vps_op_run({}, {}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_run_current())); + static_assert(noexcept(sys.set_bf_vps_op_run_current({}))); + static_assert(noexcept(sys.bf_vps_op_advance_ip({}))); + static_assert(noexcept(sys.set_bf_vps_op_advance_ip({}, {}))); + static_assert(noexcept(sys.bf_vps_op_advance_ip_and_run_current())); + static_assert(noexcept(sys.set_bf_vps_op_advance_ip_and_run_current({}))); + static_assert(noexcept(sys.bf_vps_op_promote({}))); + static_assert(noexcept(sys.set_bf_vps_op_promote({}, {}))); + static_assert(noexcept(sys.bf_vps_op_clear_vps({}))); + static_assert(noexcept(sys.set_bf_vps_op_clear_vps({}, {}))); + static_assert(noexcept(sys.bf_intrinsic_op_rdmsr({}))); + static_assert(noexcept(sys.set_bf_intrinsic_op_rdmsr({}, {}))); + static_assert(noexcept(sys.bf_intrinsic_op_wrmsr({}, {}))); + static_assert(noexcept(sys.set_bf_intrinsic_op_wrmsr({}, {}, {}))); + static_assert(noexcept(sys.bf_intrinsic_op_invlpga({}, {}))); + static_assert(noexcept(sys.set_bf_intrinsic_op_invlpga({}, {}, {}))); + static_assert(noexcept(sys.bf_intrinsic_op_invept({}, {}))); + static_assert(noexcept(sys.set_bf_intrinsic_op_invept({}, {}, {}))); + static_assert(noexcept(sys.bf_intrinsic_op_invvpid({}, {}, {}))); + static_assert(noexcept(sys.set_bf_intrinsic_op_invvpid({}, {}, {}, {}))); + static_assert(noexcept(sys.bf_mem_op_alloc_page(phys))); + static_assert(noexcept(sys.bf_mem_op_alloc_page())); + static_assert(noexcept(sys.set_bf_mem_op_alloc_page({}))); + static_assert(noexcept(sys.bf_mem_op_free_page({}))); + static_assert(noexcept(sys.set_bf_mem_op_free_page({}))); + static_assert(noexcept(sys.bf_mem_op_alloc_huge({}, phys))); + static_assert(noexcept(sys.bf_mem_op_alloc_huge({}))); + static_assert(noexcept(sys.set_bf_mem_op_alloc_huge({}))); + static_assert(noexcept(sys.bf_mem_op_free_huge({}))); + static_assert(noexcept(sys.set_bf_mem_op_free_huge({}))); + static_assert(noexcept(sys.bf_mem_op_alloc_heap({}))); + static_assert(noexcept(sys.bf_read_phys({}))); + static_assert(noexcept(sys.bf_write_phys({}, {}))); + static_assert(noexcept(sys.bf_virt_to_phys({}))); + static_assert(noexcept(sys.bf_phys_to_virt({}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + syscall::fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + static_assert(syscall::FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/syscall/test/src/cpp/bf_control_ops/CMakeLists.txt b/syscall/test/src/cpp/bf_control_ops/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/syscall/test/src/cpp/bf_control_ops/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/syscall/test/src/cpp/bf_control_ops/behavior.cpp b/syscall/test/src/cpp/bf_control_ops/behavior.cpp new file mode 100644 index 00000000..5ca51829 --- /dev/null +++ b/syscall/test/src/cpp/bf_control_ops/behavior.cpp @@ -0,0 +1,86 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/cpp/bf_control_ops.hpp" + +#include + +namespace syscall +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"bf_control_op_exit"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_control_op_exit_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_control_op_exit(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_control_op_exit_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_control_op_wait"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_control_op_wait_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_control_op_wait(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_control_op_wait_impl_executed); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(syscall::tests() == bsl::ut_success()); + return syscall::tests(); +} diff --git a/syscall/test/src/cpp/bf_control_ops/requirements.cpp b/syscall/test/src/cpp/bf_control_ops/requirements.cpp new file mode 100644 index 00000000..30f74f7a --- /dev/null +++ b/syscall/test/src/cpp/bf_control_ops/requirements.cpp @@ -0,0 +1,50 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/cpp/bf_control_ops.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(syscall::bf_control_op_exit())); + static_assert(noexcept(syscall::bf_control_op_wait())); + }; + }; + + return bsl::ut_success(); +} diff --git a/syscall/test/src/cpp/bf_debug_ops/CMakeLists.txt b/syscall/test/src/cpp/bf_debug_ops/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/syscall/test/src/cpp/bf_debug_ops/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/syscall/test/src/cpp/bf_debug_ops/behavior.cpp b/syscall/test/src/cpp/bf_debug_ops/behavior.cpp new file mode 100644 index 00000000..4d69cf72 --- /dev/null +++ b/syscall/test/src/cpp/bf_debug_ops/behavior.cpp @@ -0,0 +1,183 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/cpp/bf_debug_ops.hpp" + +#include +#include + +namespace syscall +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"bf_debug_op_out"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_out_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_out({}, {}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_out_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vm"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_vm_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_vm({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vm_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vp"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_vp_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_vp({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vp_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vps"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_vps_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_vps({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vps_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_vmexit_log"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_vmexit_log_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_vmexit_log({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_vmexit_log_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_write_c"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_write_c_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_write_c({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_write_c_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_write_str"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_write_str_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_write_str({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_write_str_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_ext"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_ext_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_ext({}); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_ext_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_page_pool"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_page_pool_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_page_pool(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_page_pool_impl_executed); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_debug_op_dump_huge_pool"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + g_bf_debug_op_dump_huge_pool_impl_executed = {}; + bsl::ut_when{} = []() noexcept { + bf_debug_op_dump_huge_pool(); + bsl::ut_then{} = []() noexcept { + bsl::ut_check(g_bf_debug_op_dump_huge_pool_impl_executed); + }; + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(syscall::tests() == bsl::ut_success()); + return syscall::tests(); +} diff --git a/syscall/test/src/cpp/bf_debug_ops/requirements.cpp b/syscall/test/src/cpp/bf_debug_ops/requirements.cpp new file mode 100644 index 00000000..19423b3a --- /dev/null +++ b/syscall/test/src/cpp/bf_debug_ops/requirements.cpp @@ -0,0 +1,58 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/cpp/bf_debug_ops.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(syscall::bf_debug_op_out({}, {}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vm({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vp({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vps({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vmexit_log({}))); + static_assert(noexcept(syscall::bf_debug_op_write_c({}))); + static_assert(noexcept(syscall::bf_debug_op_write_str({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_ext({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_page_pool())); + static_assert(noexcept(syscall::bf_debug_op_dump_huge_pool())); + }; + }; + + return bsl::ut_success(); +} diff --git a/example/CMakeLists.txt b/syscall/test/src/cpp/bf_syscall_impl/CMakeLists.txt similarity index 91% rename from example/CMakeLists.txt rename to syscall/test/src/cpp/bf_syscall_impl/CMakeLists.txt index eff22b30..c091ef27 100644 --- a/example/CMakeLists.txt +++ b/syscall/test/src/cpp/bf_syscall_impl/CMakeLists.txt @@ -19,4 +19,4 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -add_subdirectory(default) +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/syscall/test/src/cpp/bf_syscall_impl/requirements.cpp b/syscall/test/src/cpp/bf_syscall_impl/requirements.cpp new file mode 100644 index 00000000..c4c58311 --- /dev/null +++ b/syscall/test/src/cpp/bf_syscall_impl/requirements.cpp @@ -0,0 +1,136 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/cpp/bf_syscall_impl.hpp" + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(syscall::bf_tls_set_rax_impl({}))); + static_assert(noexcept(syscall::bf_tls_rax_impl())); + static_assert(noexcept(syscall::bf_tls_set_rbx_impl({}))); + static_assert(noexcept(syscall::bf_tls_rbx_impl())); + static_assert(noexcept(syscall::bf_tls_set_rcx_impl({}))); + static_assert(noexcept(syscall::bf_tls_rcx_impl())); + static_assert(noexcept(syscall::bf_tls_set_rdx_impl({}))); + static_assert(noexcept(syscall::bf_tls_rdx_impl())); + static_assert(noexcept(syscall::bf_tls_set_rbp_impl({}))); + static_assert(noexcept(syscall::bf_tls_rbp_impl())); + static_assert(noexcept(syscall::bf_tls_set_rsi_impl({}))); + static_assert(noexcept(syscall::bf_tls_rsi_impl())); + static_assert(noexcept(syscall::bf_tls_set_rdi_impl({}))); + static_assert(noexcept(syscall::bf_tls_rdi_impl())); + static_assert(noexcept(syscall::bf_tls_set_r8_impl({}))); + static_assert(noexcept(syscall::bf_tls_r8_impl())); + static_assert(noexcept(syscall::bf_tls_set_r9_impl({}))); + static_assert(noexcept(syscall::bf_tls_r9_impl())); + static_assert(noexcept(syscall::bf_tls_set_r10_impl({}))); + static_assert(noexcept(syscall::bf_tls_r10_impl())); + static_assert(noexcept(syscall::bf_tls_set_r11_impl({}))); + static_assert(noexcept(syscall::bf_tls_r11_impl())); + static_assert(noexcept(syscall::bf_tls_set_r12_impl({}))); + static_assert(noexcept(syscall::bf_tls_r12_impl())); + static_assert(noexcept(syscall::bf_tls_set_r13_impl({}))); + static_assert(noexcept(syscall::bf_tls_r13_impl())); + static_assert(noexcept(syscall::bf_tls_set_r14_impl({}))); + static_assert(noexcept(syscall::bf_tls_r14_impl())); + static_assert(noexcept(syscall::bf_tls_set_r15_impl({}))); + static_assert(noexcept(syscall::bf_tls_r15_impl())); + static_assert(noexcept(syscall::bf_tls_extid_impl())); + static_assert(noexcept(syscall::bf_tls_vmid_impl())); + static_assert(noexcept(syscall::bf_tls_vpid_impl())); + static_assert(noexcept(syscall::bf_tls_vpsid_impl())); + static_assert(noexcept(syscall::bf_tls_ppid_impl())); + static_assert(noexcept(syscall::bf_tls_online_pps_impl())); + static_assert(noexcept(syscall::bf_control_op_exit_impl())); + static_assert(noexcept(syscall::bf_control_op_wait_impl())); + static_assert(noexcept(syscall::bf_handle_op_open_handle_impl({}, {}))); + static_assert(noexcept(syscall::bf_handle_op_close_handle_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_out_impl({}, {}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vm_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vp_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vps_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vmexit_log_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_vmexit_log_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_write_c_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_write_str_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_ext_impl({}))); + static_assert(noexcept(syscall::bf_debug_op_dump_page_pool_impl())); + static_assert(noexcept(syscall::bf_debug_op_dump_huge_pool_impl())); + static_assert(noexcept(syscall::bf_callback_op_register_bootstrap_impl({}, {}))); + static_assert(noexcept(syscall::bf_callback_op_register_vmexit_impl({}, {}))); + static_assert(noexcept(syscall::bf_callback_op_register_fail_impl({}, {}))); + static_assert(noexcept(syscall::bf_vm_op_create_vm_impl({}, {}))); + static_assert(noexcept(syscall::bf_vm_op_destroy_vm_impl({}, {}))); + static_assert(noexcept(syscall::bf_vp_op_create_vp_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vp_op_destroy_vp_impl({}, {}))); + static_assert(noexcept(syscall::bf_vp_op_migrate_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_create_vps_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_destroy_vps_impl({}, {}))); + static_assert(noexcept(syscall::bf_vps_op_init_as_root_impl({}, {}))); + static_assert(noexcept(syscall::bf_vps_op_read8_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_read16_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_read32_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_read64_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_write8_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_write16_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_write32_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_write64_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_read_reg_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_write_reg_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_run_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_vps_op_run_current_impl({}))); + static_assert(noexcept(syscall::bf_vps_op_advance_ip_impl({}, {}))); + static_assert(noexcept(syscall::bf_vps_op_advance_ip_and_run_current_impl({}))); + static_assert(noexcept(syscall::bf_vps_op_promote_impl({}, {}))); + static_assert(noexcept(syscall::bf_vps_op_clear_vps_impl({}, {}))); + static_assert(noexcept(syscall::bf_intrinsic_op_rdmsr_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_intrinsic_op_wrmsr_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_intrinsic_op_invlpga_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_intrinsic_op_invept_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_intrinsic_op_invvpid_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_mem_op_alloc_page_impl({}, {}, {}))); + static_assert(noexcept(syscall::bf_mem_op_free_page_impl({}, {}))); + static_assert(noexcept(syscall::bf_mem_op_alloc_huge_impl({}, {}, {}, {}))); + static_assert(noexcept(syscall::bf_mem_op_free_huge_impl({}, {}))); + static_assert(noexcept(syscall::bf_mem_op_alloc_heap_impl({}, {}, {}))); + }; + }; + + return bsl::ut_success(); +} diff --git a/syscall/test/src/cpp/bf_syscall_t/CMakeLists.txt b/syscall/test/src/cpp/bf_syscall_t/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/syscall/test/src/cpp/bf_syscall_t/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/syscall/test/src/cpp/bf_syscall_t/behavior.cpp b/syscall/test/src/cpp/bf_syscall_t/behavior.cpp new file mode 100644 index 00000000..159c1388 --- /dev/null +++ b/syscall/test/src/cpp/bf_syscall_t/behavior.cpp @@ -0,0 +1,3156 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/cpp/bf_syscall_t.hpp" + +#include +#include + +#include +#include + +namespace syscall +{ + // ------------------------------------------------------------------------- + // constants + // ------------------------------------------------------------------------- + + /// @brief stores the answer to all things (in 8 bits) + constexpr auto ANSWER8{42_u8}; + /// @brief stores the answer to all things (in 16 bits) + constexpr auto ANSWER16{42_u16}; + /// @brief stores the answer to all things (in 32 bits) + constexpr auto ANSWER32{42_u32}; + /// @brief stores the answer to all things (in 64 bits) + constexpr auto ANSWER64{42_u64}; + + /// @brief stores a bad address + constexpr auto BAD_ADDR{0xFFFFFFFFFFFFFFFF_u64}; + /// @brief stores a bad version + constexpr auto BAD_VERSION{0x80000000_u32}; + + // ------------------------------------------------------------------------- + // tests + // ------------------------------------------------------------------------- + + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + bsl::ut_scenario{"initialize invalid version #1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + bf_uint32_t::failure(), // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize invalid version #2"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + {}, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize invalid bootstrap_handler"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + BF_ALL_SPECS_SUPPORTED_VAL, // -- + {}, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize invalid vmexit_handler"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + {}, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize invalid fail_handler"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + {})); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize bf_is_spec1_supported fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + BAD_VERSION, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize bf_handle_op_open_handle_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_handle_op_open_handle_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{ + "initialize bf_callback_op_register_bootstrap_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_callback_op_register_bootstrap_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize bf_callback_op_register_vmexit_impl fail"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_callback_op_register_vmexit_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize bf_callback_op_register_fail_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_callback_op_register_fail_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.initialize( // -- + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"initialize success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.initialize( // -- + BF_ALL_SPECS_SUPPORTED_VAL, // -- + &dummy_bootstrap_entry, // -- + &dummy_vmexit_entry, // -- + &dummy_fail_entry)); // -- + }; + }; + }; + }; + + bsl::ut_scenario{"release"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + sys.release(); + }; + }; + }; + }; + + // --------------------------------------------------------------------- + // TLS ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_tls_rax/bf_tls_set_rax"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rax()); + bsl::ut_check(sys.bf_tls_rax().is_zero()); + }; + + sys.bf_tls_set_rax(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rax() == ANSWER64); + }; + + sys.bf_tls_set_rax(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rax() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rbx/bf_tls_set_rbx"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbx()); + bsl::ut_check(sys.bf_tls_rbx().is_zero()); + }; + + sys.bf_tls_set_rbx(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbx() == ANSWER64); + }; + + sys.bf_tls_set_rbx(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbx() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rcx/bf_tls_set_rcx"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rcx()); + bsl::ut_check(sys.bf_tls_rcx().is_zero()); + }; + + sys.bf_tls_set_rcx(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rcx() == ANSWER64); + }; + + sys.bf_tls_set_rcx(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rcx() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rdx/bf_tls_set_rdx"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdx()); + bsl::ut_check(sys.bf_tls_rdx().is_zero()); + }; + + sys.bf_tls_set_rdx(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdx() == ANSWER64); + }; + + sys.bf_tls_set_rdx(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdx() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rbp/bf_tls_set_rbp"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbp()); + bsl::ut_check(sys.bf_tls_rbp().is_zero()); + }; + + sys.bf_tls_set_rbp(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbp() == ANSWER64); + }; + + sys.bf_tls_set_rbp(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rbp() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rsi/bf_tls_set_rsi"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rsi()); + bsl::ut_check(sys.bf_tls_rsi().is_zero()); + }; + + sys.bf_tls_set_rsi(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rsi() == ANSWER64); + }; + + sys.bf_tls_set_rsi(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rsi() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_rdi/bf_tls_set_rdi"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdi()); + bsl::ut_check(sys.bf_tls_rdi().is_zero()); + }; + + sys.bf_tls_set_rdi(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdi() == ANSWER64); + }; + + sys.bf_tls_set_rdi(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_rdi() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r8/bf_tls_set_r8"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r8()); + bsl::ut_check(sys.bf_tls_r8().is_zero()); + }; + + sys.bf_tls_set_r8(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r8() == ANSWER64); + }; + + sys.bf_tls_set_r8(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r8() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r9/bf_tls_set_r9"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r9()); + bsl::ut_check(sys.bf_tls_r9().is_zero()); + }; + + sys.bf_tls_set_r9(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r9() == ANSWER64); + }; + + sys.bf_tls_set_r9(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r9() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r10/bf_tls_set_r10"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r10()); + bsl::ut_check(sys.bf_tls_r10().is_zero()); + }; + + sys.bf_tls_set_r10(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r10() == ANSWER64); + }; + + sys.bf_tls_set_r10(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r10() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r11/bf_tls_set_r11"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r11()); + bsl::ut_check(sys.bf_tls_r11().is_zero()); + }; + + sys.bf_tls_set_r11(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r11() == ANSWER64); + }; + + sys.bf_tls_set_r11(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r11() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r12/bf_tls_set_r12"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r12()); + bsl::ut_check(sys.bf_tls_r12().is_zero()); + }; + + sys.bf_tls_set_r12(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r12() == ANSWER64); + }; + + sys.bf_tls_set_r12(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r12() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r13/bf_tls_set_r13"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r13()); + bsl::ut_check(sys.bf_tls_r13().is_zero()); + }; + + sys.bf_tls_set_r13(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r13() == ANSWER64); + }; + + sys.bf_tls_set_r13(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r13() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r14/bf_tls_set_r14"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r14()); + bsl::ut_check(sys.bf_tls_r14().is_zero()); + }; + + sys.bf_tls_set_r14(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r14() == ANSWER64); + }; + + sys.bf_tls_set_r14(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r14() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_r15/bf_tls_set_r15"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r15()); + bsl::ut_check(sys.bf_tls_r15().is_zero()); + }; + + sys.bf_tls_set_r15(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r15() == ANSWER64); + }; + + sys.bf_tls_set_r15(bf_uint64_t::failure()); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_r15() == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_extid/bf_tls_set_extid"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_extid()); + bsl::ut_check(sys.bf_tls_extid().is_zero()); + }; + + g_data.at("bf_tls_extid") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_extid() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_vmid/bf_tls_set_vmid"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vmid()); + bsl::ut_check(sys.bf_tls_vmid().is_zero()); + }; + + g_data.at("bf_tls_vmid") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vmid() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_vpid/bf_tls_set_vpid"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vpid()); + bsl::ut_check(sys.bf_tls_vpid().is_zero()); + }; + + g_data.at("bf_tls_vpid") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vpid() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_vpsid/bf_tls_set_vpsid"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vpsid()); + bsl::ut_check(sys.bf_tls_vpsid().is_zero()); + }; + + g_data.at("bf_tls_vpsid") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_vpsid() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_ppid/bf_tls_set_ppid"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_ppid()); + bsl::ut_check(sys.bf_tls_ppid().is_zero()); + }; + + g_data.at("bf_tls_ppid") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_ppid() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_tls_online_pps/bf_tls_set_online_pps"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_data.clear(); + + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_online_pps()); + bsl::ut_check(sys.bf_tls_online_pps().is_zero()); + }; + + g_data.at("bf_tls_online_pps") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_tls_online_pps() == ANSWER16); + }; + }; + }; + }; + + // --------------------------------------------------------------------- + // bf_vm_ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_vm_op_create_vm bf_vm_op_create_vm_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vm_op_create_vm_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vm_op_create_vm_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vm_op_create_vm()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_create_vm success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vm_op_create_vm_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vm_op_create_vm() == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_destroy_vm invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vm_op_destroy_vm(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_destroy_vm bf_vm_op_destroy_vm_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_vm_op_destroy_vm_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vm_op_destroy_vm(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vm_op_destroy_vm success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vm_op_destroy_vm(arg0)); + }; + }; + }; + }; + + // --------------------------------------------------------------------- + // bf_vp_ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_vp_op_create_vp invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vp_op_create_vp_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_create_vp(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_create_vp invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vp_op_create_vp_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_create_vp(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_create_vp bf_vp_op_create_vp_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vp_op_create_vp_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vp_op_create_vp_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_create_vp(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_create_vp success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vp_op_create_vp_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vp_op_create_vp(arg0, arg1) == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_destroy_vp invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_destroy_vp(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_destroy_vp bf_vp_op_destroy_vp_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_vp_op_destroy_vp_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_destroy_vp(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_destroy_vp success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vp_op_destroy_vp(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_migrate invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_migrate(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_migrate invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_migrate(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_migrate bf_vp_op_migrate_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_vp_op_migrate_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vp_op_migrate(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vp_op_migrate success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vp_op_migrate(arg0, arg1)); + }; + }; + }; + }; + + // --------------------------------------------------------------------- + // bf_vps_ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_vps_op_create_vps invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_create_vps_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_create_vps(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_create_vps invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_create_vps_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_create_vps(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_create_vps bf_vps_op_create_vps_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_create_vps_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_create_vps_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_create_vps(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_create_vps success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_create_vps_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_create_vps(arg0, arg1) == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_destroy_vps invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_destroy_vps(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_destroy_vps bf_vps_op_destroy_vps_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_vps_op_destroy_vps_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_destroy_vps(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_destroy_vps success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_destroy_vps(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_init_as_root invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_init_as_root(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_init_as_root bf_vps_op_init_as_root_impl fails"} = + []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_vps_op_init_as_root_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_init_as_root(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_init_as_root success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_init_as_root(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read8 invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read8_impl_reg0_out") = bsl::to_u64(ANSWER8); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read8(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read8 invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read8_impl_reg0_out") = bsl::to_u64(ANSWER8); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read8(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read8 bf_vps_op_read8_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_read8_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_read8_impl_reg0_out") = bsl::to_u64(ANSWER8); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read8(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read8 success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read8_impl_reg0_out") = bsl::to_u64(ANSWER8); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_read8(arg0, arg1) == ANSWER8); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read16 invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read16_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read16(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read16 invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read16_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read16(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read16 bf_vps_op_read16_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_read16_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_read16_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read16(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read16 success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read16_impl_reg0_out") = bsl::to_u64(ANSWER16); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_read16(arg0, arg1) == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read32 invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read32_impl_reg0_out") = bsl::to_u64(ANSWER32); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read32(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read32 invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read32_impl_reg0_out") = bsl::to_u64(ANSWER32); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read32(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read32 bf_vps_op_read32_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_read32_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_read32_impl_reg0_out") = bsl::to_u64(ANSWER32); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read32(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read32 success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read32_impl_reg0_out") = bsl::to_u64(ANSWER32); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_read32(arg0, arg1) == ANSWER32); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read64 invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read64_impl_reg0_out") = bsl::to_u64(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read64(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read64 invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read64_impl_reg0_out") = bsl::to_u64(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read64(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read64 bf_vps_op_read64_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_read64_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_read64_impl_reg0_out") = bsl::to_u64(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read64(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read64 success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read64_impl_reg0_out") = bsl::to_u64(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_read64(arg0, arg1) == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8 invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bf_uint8_t arg2{ANSWER8}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write8(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8 invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bf_uint8_t arg2{ANSWER8}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write8(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8 invalid arg2"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint8_t arg2{bf_uint8_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write8(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8 bf_vps_op_write8_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint8_t arg2{ANSWER8}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_write8_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write8(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write8 success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint8_t arg2{ANSWER8}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_write8(arg0, arg1, arg2)); + bsl::ut_check(g_data.at("bf_vps_op_write8_impl") == bsl::to_u64(arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16 invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bf_uint16_t arg2{ANSWER16}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write16(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16 invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bf_uint16_t arg2{ANSWER16}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write16(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16 invalid arg2"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint16_t arg2{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write16(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16 bf_vps_op_write16_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint16_t arg2{ANSWER16}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_write16_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write16(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write16 success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint16_t arg2{ANSWER16}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_write16(arg0, arg1, arg2)); + bsl::ut_check(g_data.at("bf_vps_op_write16_impl") == bsl::to_u64(arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32 invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bf_uint32_t arg2{ANSWER32}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write32(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32 invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bf_uint32_t arg2{ANSWER32}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write32(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32 invalid arg2"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint32_t arg2{bf_uint32_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write32(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32 bf_vps_op_write32_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint32_t arg2{ANSWER32}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_write32_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write32(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write32 success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint32_t arg2{ANSWER32}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_write32(arg0, arg1, arg2)); + bsl::ut_check(g_data.at("bf_vps_op_write32_impl") == bsl::to_u64(arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64 invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint64_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write64(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64 invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write64(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64 invalid arg2"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint64_t arg2{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write64(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64 bf_vps_op_write64_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_write64_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write64(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write64 success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint64_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_write64(arg0, arg1, arg2)); + bsl::ut_check(g_data.at("bf_vps_op_write64_impl") == bsl::to_u64(arg2)); + }; + }; + }; + }; + bsl::ut_scenario{"bf_vps_op_read_reg invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_reg_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read_reg_impl_reg0_out") = bsl::to_u64(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read_reg(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read_reg bf_vps_op_read_reg_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_reg_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_read_reg_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_vps_op_read_reg_impl_reg0_out") = bsl::to_u64(ANSWER64); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_read_reg(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_read_reg success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_reg_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_vps_op_read_reg_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_read_reg(arg0, arg1) == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write_reg invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_reg_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write_reg(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write_reg invalid arg2"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_reg_t arg1{}; + bf_uint64_t arg2{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write_reg(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write_reg bf_vps_op_write_reg_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_reg_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_vps_op_write_reg_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_write_reg(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_write_reg success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_reg_t arg1{}; + bf_uint64_t arg2{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_write_reg(arg0, arg1, arg2)); + bsl::ut_check(g_data.at("bf_vps_op_write_reg_impl") == arg2); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bf_uint16_t arg1{}; + bf_uint16_t arg2{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_run(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{bf_uint16_t::failure()}; + bf_uint16_t arg2{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_run(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run invalid arg2"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bf_uint16_t arg2{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_run(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run bf_vps_op_run_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bf_uint16_t arg2{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_vps_op_run_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_run(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bf_uint16_t arg1{}; + bf_uint16_t arg2{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_run(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run_current bf_vps_op_run_current_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_vps_op_run_current_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_run_current()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_run_current success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_run_current()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_advance_ip(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip bf_vps_op_advance_ip_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_vps_op_advance_ip_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_advance_ip(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_advance_ip(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{ + "bf_vps_op_advance_ip_and_run_current bf_vps_op_advance_ip_and_run_current_impl " + "fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_vps_op_advance_ip_and_run_current_impl") = + BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_advance_ip_and_run_current()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_advance_ip_and_run_current success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_advance_ip_and_run_current()); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_promote invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_promote(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_promote bf_vps_op_promote_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_vps_op_promote_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_promote(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_promote success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_promote(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_clear_vps invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{bf_uint16_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_clear_vps(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_clear_vps bf_vps_op_clear_vps_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_vps_op_clear_vps_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_vps_op_clear_vps(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_vps_op_clear_vps success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_vps_op_clear_vps(arg0)); + }; + }; + }; + }; + + // --------------------------------------------------------------------- + // bf_intrinsic_ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_intrinsic_op_rdmsr invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{bf_uint32_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_intrinsic_op_rdmsr_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_rdmsr(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_rdmsr bf_intrinsic_op_rdmsr_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_intrinsic_op_rdmsr_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_intrinsic_op_rdmsr_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_rdmsr(arg0)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_rdmsr success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_intrinsic_op_rdmsr_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_intrinsic_op_rdmsr(arg0) == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_wrmsr invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{bf_uint32_t::failure()}; + bf_uint64_t arg1{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_wrmsr(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_wrmsr invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_wrmsr(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_wrmsr bf_intrinsic_op_wrmsr_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{}; + bf_uint64_t arg1{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_intrinsic_op_wrmsr_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_wrmsr(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_wrmsr success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t arg0{}; + bf_uint64_t arg1{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_intrinsic_op_wrmsr(arg0, arg1)); + bsl::ut_check(g_data.at("bf_intrinsic_op_wrmsr_impl") == arg1); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invlpga invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{bf_uint64_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invlpga(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invlpga invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invlpga(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invlpga bf_intrinsic_op_invlpga_impl fails"} = + []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_intrinsic_op_invlpga_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invlpga(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invlpga success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_intrinsic_op_invlpga(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invept invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{bf_uint64_t::failure()}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invept(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invept invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invept(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invept bf_intrinsic_op_invept_impl fails"} = + []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_intrinsic_op_invept_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invept(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invept success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint64_t arg1{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_intrinsic_op_invept(arg0, arg1)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid invalid arg0"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{bf_uint64_t::failure()}; + bf_uint16_t arg1{}; + bf_uint64_t arg2{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invvpid(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid invalid arg1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint16_t arg1{bf_uint16_t::failure()}; + bf_uint64_t arg2{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invvpid(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid invalid arg2"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint16_t arg1{}; + bf_uint64_t arg2{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invvpid(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid bf_intrinsic_op_invvpid_impl fails"} = + []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint16_t arg1{}; + bf_uint64_t arg2{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_errc.at("bf_intrinsic_op_invvpid_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_intrinsic_op_invvpid(arg0, arg1, arg2)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_intrinsic_op_invvpid success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t arg0{}; + bf_uint16_t arg1{}; + bf_uint64_t arg2{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_intrinsic_op_invvpid(arg0, arg1, arg2)); + }; + }; + }; + }; + + // --------------------------------------------------------------------- + // bf_mem_ops + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_mem_op_alloc_page invalid phys"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_page_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_page(phys) == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_page bf_mem_op_alloc_page_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_mem_op_alloc_page_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_mem_op_alloc_page_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_page(phys) == nullptr); + bsl::ut_check(sys.bf_mem_op_alloc_page() == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_page success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + void *ptr{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_page_impl_reg0_out") = ANSWER64; + + ptr = sys.bf_mem_op_alloc_page(phys); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(ptr != nullptr); + bsl::ut_check(sys.bf_mem_op_free_page(ptr)); + }; + }; + + bsl::ut_when{} = [&]() noexcept { + ptr = sys.bf_mem_op_alloc_page(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(ptr != nullptr); + bsl::ut_check(sys.bf_mem_op_free_page(ptr)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_page invalid ptr"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + void *ptr{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_mem_op_free_page(ptr)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_page failure/success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + void *ptr{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_page_impl_reg0_out") = ANSWER64; + + ptr = sys.bf_mem_op_alloc_page(); + g_errc.at("bf_mem_op_free_page_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_mem_op_free_page(ptr)); + }; + + g_errc.at("bf_mem_op_free_page_impl") = BF_STATUS_SUCCESS; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_free_page(ptr)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge invalid size #1"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{bf_uint64_t::failure()}; + bf_uint64_t phys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_huge_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_huge(size, phys) == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge invalid size #2"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{}; + bf_uint64_t phys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_huge_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_huge(size, phys) == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge invalid phys"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{ANSWER64}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_huge_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_huge(size, phys) == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge bf_mem_op_alloc_huge_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{ANSWER64}; + bf_uint64_t phys{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_mem_op_alloc_huge_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_mem_op_alloc_huge_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_huge(size, phys) == nullptr); + bsl::ut_check(sys.bf_mem_op_alloc_huge(size) == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_huge success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{ANSWER64}; + bf_uint64_t phys{}; + void *ptr{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_huge_impl_reg0_out") = ANSWER64; + + ptr = sys.bf_mem_op_alloc_huge(size, phys); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(ptr != nullptr); + bsl::ut_check(sys.bf_mem_op_free_huge(ptr)); + }; + }; + + bsl::ut_when{} = [&]() noexcept { + ptr = sys.bf_mem_op_alloc_huge(size); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(ptr != nullptr); + bsl::ut_check(sys.bf_mem_op_free_huge(ptr)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_huge invalid ptr"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + void *ptr{}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_mem_op_free_huge(ptr)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_free_huge failure/success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{ANSWER64}; + void *ptr{}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_huge_impl_reg0_out") = ANSWER64; + + ptr = sys.bf_mem_op_alloc_huge(size); + g_errc.at("bf_mem_op_free_huge_impl") = BF_STATUS_FAILURE_UNKNOWN; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_mem_op_free_huge(ptr)); + }; + + g_errc.at("bf_mem_op_free_huge_impl") = BF_STATUS_SUCCESS; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_free_huge(ptr)); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_heap invalid size"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{bf_uint64_t::failure()}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_heap_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_heap(size) == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_heap bf_mem_op_alloc_heap_impl fails"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_errc.at("bf_mem_op_alloc_heap_impl") = BF_STATUS_FAILURE_UNKNOWN; + g_data.at("bf_mem_op_alloc_heap_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_mem_op_alloc_heap(size) == nullptr); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_mem_op_alloc_heap success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t size{ANSWER64}; + bsl::ut_when{} = [&]() noexcept { + g_errc.clear(); + g_data.clear(); + g_data.at("bf_mem_op_alloc_heap_impl_reg0_out") = ANSWER64; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(nullptr != sys.bf_mem_op_alloc_heap(size)); + }; + }; + }; + }; + + // --------------------------------------------------------------------- + // direct map helpers + // --------------------------------------------------------------------- + + bsl::ut_scenario{"bf_read_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint8_t val{}; + bf_uint64_t phys{bsl::to_umax(&val) - HYPERVISOR_EXT_DIRECT_MAP_ADDR}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(sys.bf_write_phys(phys, ANSWER8)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER8); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t val{}; + bf_uint64_t phys{bsl::to_umax(&val) - HYPERVISOR_EXT_DIRECT_MAP_ADDR}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(sys.bf_write_phys(phys, ANSWER16)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER16); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t val{}; + bf_uint64_t phys{bsl::to_umax(&val) - HYPERVISOR_EXT_DIRECT_MAP_ADDR}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(sys.bf_write_phys(phys, ANSWER32)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER32); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_read_phys(phys)); + }; + }; + }; + + bsl::ut_scenario{"bf_read_phys success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t val{}; + bf_uint64_t phys{bsl::to_umax(&val) - HYPERVISOR_EXT_DIRECT_MAP_ADDR}; + bsl::ut_when{} = [&]() noexcept { + bsl::ut_required_step(sys.bf_write_phys(phys, ANSWER64)); + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER64); + }; + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bf_uint8_t val{ANSWER8}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bf_uint8_t val{ANSWER8}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid val"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint8_t val{bf_uint8_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bf_uint8_t val{ANSWER8}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint8_t val{ANSWER8}; + bf_uint64_t phys{bsl::to_umax(&val) - HYPERVISOR_EXT_DIRECT_MAP_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_write_phys(phys, val)); + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER8); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bf_uint16_t val{ANSWER16}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bf_uint16_t val{ANSWER16}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid val"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint16_t val{bf_uint16_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bf_uint16_t val{ANSWER16}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint16_t val{ANSWER16}; + bf_uint64_t phys{bsl::to_umax(&val) - HYPERVISOR_EXT_DIRECT_MAP_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_write_phys(phys, val)); + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER16); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bf_uint32_t val{ANSWER32}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bf_uint32_t val{ANSWER32}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid val"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint32_t val{bf_uint32_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bf_uint32_t val{ANSWER32}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint32_t val{ANSWER32}; + bf_uint64_t phys{bsl::to_umax(&val) - HYPERVISOR_EXT_DIRECT_MAP_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_write_phys(phys, val)); + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER32); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bf_uint64_t val{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bf_uint64_t val{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys invalid val"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{ANSWER64}; + bf_uint64_t val{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys address out of range"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bf_uint64_t val{ANSWER64}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_write_phys(phys, val)); + }; + }; + }; + + bsl::ut_scenario{"bf_write_phys success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t val{ANSWER64}; + bf_uint64_t phys{bsl::to_umax(&val) - HYPERVISOR_EXT_DIRECT_MAP_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_write_phys(phys, val)); + bsl::ut_check(sys.bf_read_phys(phys) == ANSWER64); + }; + }; + }; + + bsl::ut_scenario{"bf_virt_to_phys invalid virt"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + void *virt{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_virt_to_phys(virt)); + }; + }; + }; + + bsl::ut_scenario{"bf_virt_to_phys overflow"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + void *virt{bsl::to_ptr(ANSWER64)}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(!sys.bf_virt_to_phys(virt)); + }; + }; + }; + + bsl::ut_scenario{"bf_virt_to_phys success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + void *virt{}; + bf_uint64_t phys{bsl::to_umax(&virt) - HYPERVISOR_EXT_DIRECT_MAP_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_virt_to_phys(&virt) == phys); + }; + }; + }; + + bsl::ut_scenario{"bf_phys_to_virt invalid phys #1"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{bf_uint64_t::failure()}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_phys_to_virt(phys) == nullptr); + }; + }; + }; + + bsl::ut_scenario{"bf_phys_to_virt invalid phys #2"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_phys_to_virt(phys) == nullptr); + }; + }; + }; + + bsl::ut_scenario{"bf_phys_to_virt overflow"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + bf_uint64_t phys{BAD_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_phys_to_virt(phys) == nullptr); + }; + }; + }; + + bsl::ut_scenario{"bf_phys_to_virt success"} = []() noexcept { + bsl::ut_given_at_runtime{} = []() noexcept { + bf_syscall_t sys{}; + void *virt{}; + bf_uint64_t phys{bsl::to_umax(&virt) - HYPERVISOR_EXT_DIRECT_MAP_ADDR}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(sys.bf_phys_to_virt(phys) == &virt); + }; + }; + }; + + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(syscall::tests() == bsl::ut_success()); + return syscall::tests(); +} diff --git a/syscall/test/src/cpp/bf_syscall_t/requirements.cpp b/syscall/test/src/cpp/bf_syscall_t/requirements.cpp new file mode 100644 index 00000000..e0f4b491 --- /dev/null +++ b/syscall/test/src/cpp/bf_syscall_t/requirements.cpp @@ -0,0 +1,283 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include "../../../../src/cpp/bf_syscall_t.hpp" + +#include +#include + +namespace syscall +{ + constinit bf_syscall_t const g_verify_constinit{}; + + // NOLINTNEXTLINE(bsl-user-defined-type-names-match-header-name) + class fixture_t final + { + bf_syscall_t m_sys{}; + + public: + [[nodiscard]] constexpr auto + test_member_const() const noexcept -> bool + { + bsl::discard(m_sys.bf_tls_rax()); + bsl::discard(m_sys.bf_tls_rbx()); + bsl::discard(m_sys.bf_tls_rcx()); + bsl::discard(m_sys.bf_tls_rdx()); + bsl::discard(m_sys.bf_tls_rbp()); + bsl::discard(m_sys.bf_tls_rsi()); + bsl::discard(m_sys.bf_tls_rdi()); + bsl::discard(m_sys.bf_tls_r8()); + bsl::discard(m_sys.bf_tls_r9()); + bsl::discard(m_sys.bf_tls_r10()); + bsl::discard(m_sys.bf_tls_r11()); + bsl::discard(m_sys.bf_tls_r12()); + bsl::discard(m_sys.bf_tls_r13()); + bsl::discard(m_sys.bf_tls_r14()); + bsl::discard(m_sys.bf_tls_r15()); + bsl::discard(m_sys.bf_tls_extid()); + bsl::discard(m_sys.bf_tls_vmid()); + bsl::discard(m_sys.bf_tls_vpid()); + bsl::discard(m_sys.bf_tls_vpsid()); + bsl::discard(m_sys.bf_tls_ppid()); + bsl::discard(m_sys.bf_tls_online_pps()); + bsl::discard(m_sys.bf_vps_op_read8({}, {})); + bsl::discard(m_sys.bf_vps_op_read16({}, {})); + bsl::discard(m_sys.bf_vps_op_read32({}, {})); + bsl::discard(m_sys.bf_vps_op_read64({}, {})); + bsl::discard(m_sys.bf_vps_op_read_reg({}, {})); + bsl::discard(m_sys.bf_intrinsic_op_rdmsr({})); + bsl::discard(m_sys.bf_read_phys({})); + bsl::discard(m_sys.bf_virt_to_phys({})); + bsl::discard(m_sys.bf_phys_to_virt({})); + + return true; + } + + [[nodiscard]] constexpr auto + test_member_nonconst() noexcept -> bool + { + bf_uint64_t phys{}; + + bsl::discard(bf_syscall_t{}); + bsl::discard(m_sys.initialize({}, {}, {}, {})); + m_sys.release(); + bsl::discard(m_sys.bf_tls_rax()); + m_sys.bf_tls_set_rax({}); + bsl::discard(m_sys.bf_tls_rbx()); + m_sys.bf_tls_set_rbx({}); + bsl::discard(m_sys.bf_tls_rcx()); + m_sys.bf_tls_set_rcx({}); + bsl::discard(m_sys.bf_tls_rdx()); + m_sys.bf_tls_set_rdx({}); + bsl::discard(m_sys.bf_tls_rbp()); + m_sys.bf_tls_set_rbp({}); + bsl::discard(m_sys.bf_tls_rsi()); + m_sys.bf_tls_set_rsi({}); + bsl::discard(m_sys.bf_tls_rdi()); + m_sys.bf_tls_set_rdi({}); + bsl::discard(m_sys.bf_tls_r8()); + m_sys.bf_tls_set_r8({}); + bsl::discard(m_sys.bf_tls_r9()); + m_sys.bf_tls_set_r9({}); + bsl::discard(m_sys.bf_tls_r10()); + m_sys.bf_tls_set_r10({}); + bsl::discard(m_sys.bf_tls_r11()); + m_sys.bf_tls_set_r11({}); + bsl::discard(m_sys.bf_tls_r12()); + m_sys.bf_tls_set_r12({}); + bsl::discard(m_sys.bf_tls_r13()); + m_sys.bf_tls_set_r13({}); + bsl::discard(m_sys.bf_tls_r14()); + m_sys.bf_tls_set_r14({}); + bsl::discard(m_sys.bf_tls_r15()); + m_sys.bf_tls_set_r15({}); + bsl::discard(m_sys.bf_tls_extid()); + bsl::discard(m_sys.bf_tls_vmid()); + bsl::discard(m_sys.bf_tls_vpid()); + bsl::discard(m_sys.bf_tls_vpsid()); + bsl::discard(m_sys.bf_tls_ppid()); + bsl::discard(m_sys.bf_tls_online_pps()); + bsl::discard(m_sys.bf_vm_op_create_vm()); + bsl::discard(m_sys.bf_vm_op_destroy_vm({})); + bsl::discard(m_sys.bf_vp_op_create_vp({}, {})); + bsl::discard(m_sys.bf_vp_op_destroy_vp({})); + bsl::discard(m_sys.bf_vp_op_migrate({}, {})); + bsl::discard(m_sys.bf_vps_op_create_vps({}, {})); + bsl::discard(m_sys.bf_vps_op_destroy_vps({})); + bsl::discard(m_sys.bf_vps_op_init_as_root({})); + bsl::discard(m_sys.bf_vps_op_read8({}, {})); + bsl::discard(m_sys.bf_vps_op_read16({}, {})); + bsl::discard(m_sys.bf_vps_op_read32({}, {})); + bsl::discard(m_sys.bf_vps_op_read64({}, {})); + bsl::discard(m_sys.bf_vps_op_write8({}, {}, {})); + bsl::discard(m_sys.bf_vps_op_write16({}, {}, {})); + bsl::discard(m_sys.bf_vps_op_write32({}, {}, {})); + bsl::discard(m_sys.bf_vps_op_write64({}, {}, {})); + bsl::discard(m_sys.bf_vps_op_read_reg({}, {})); + bsl::discard(m_sys.bf_vps_op_write_reg({}, {}, {})); + bsl::discard(m_sys.bf_vps_op_run({}, {}, {})); + bsl::discard(m_sys.bf_vps_op_run_current()); + bsl::discard(m_sys.bf_vps_op_advance_ip({})); + bsl::discard(m_sys.bf_vps_op_advance_ip_and_run_current()); + bsl::discard(m_sys.bf_vps_op_promote({})); + bsl::discard(m_sys.bf_vps_op_clear_vps({})); + bsl::discard(m_sys.bf_intrinsic_op_rdmsr({})); + bsl::discard(m_sys.bf_intrinsic_op_wrmsr({}, {})); + bsl::discard(m_sys.bf_intrinsic_op_invlpga({}, {})); + bsl::discard(m_sys.bf_intrinsic_op_invept({}, {})); + bsl::discard(m_sys.bf_intrinsic_op_invvpid({}, {}, {})); + bsl::discard(m_sys.bf_mem_op_alloc_page(phys)); + bsl::discard(m_sys.bf_mem_op_alloc_page()); + bsl::discard(m_sys.bf_mem_op_free_page({})); + bsl::discard(m_sys.bf_mem_op_alloc_huge({}, phys)); + bsl::discard(m_sys.bf_mem_op_alloc_huge({})); + bsl::discard(m_sys.bf_mem_op_free_huge({})); + bsl::discard(m_sys.bf_mem_op_alloc_heap({})); + bsl::discard(m_sys.bf_read_phys({})); + bsl::discard(m_sys.bf_write_phys({}, {})); + bsl::discard(m_sys.bf_virt_to_phys({})); + bsl::discard(m_sys.bf_phys_to_virt({})); + + return true; + } + }; + + constexpr fixture_t FIXTURE1{}; +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::ut_scenario{"verify supports constinit"} = []() noexcept { + bsl::discard(syscall::g_verify_constinit); + }; + + bsl::ut_scenario{"verify noexcept"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + syscall::bf_syscall_t sys{}; + syscall::bf_uint64_t phys{}; + bsl::ut_then{} = []() noexcept { + static_assert(noexcept(syscall::bf_syscall_t{})); + static_assert(noexcept(sys.initialize({}, {}, {}, {}))); + static_assert(noexcept(sys.release())); + static_assert(noexcept(sys.bf_tls_rax())); + static_assert(noexcept(sys.bf_tls_set_rax({}))); + static_assert(noexcept(sys.bf_tls_rbx())); + static_assert(noexcept(sys.bf_tls_set_rbx({}))); + static_assert(noexcept(sys.bf_tls_rcx())); + static_assert(noexcept(sys.bf_tls_set_rcx({}))); + static_assert(noexcept(sys.bf_tls_rdx())); + static_assert(noexcept(sys.bf_tls_set_rdx({}))); + static_assert(noexcept(sys.bf_tls_rbp())); + static_assert(noexcept(sys.bf_tls_set_rbp({}))); + static_assert(noexcept(sys.bf_tls_rsi())); + static_assert(noexcept(sys.bf_tls_set_rsi({}))); + static_assert(noexcept(sys.bf_tls_rdi())); + static_assert(noexcept(sys.bf_tls_set_rdi({}))); + static_assert(noexcept(sys.bf_tls_r8())); + static_assert(noexcept(sys.bf_tls_set_r8({}))); + static_assert(noexcept(sys.bf_tls_r9())); + static_assert(noexcept(sys.bf_tls_set_r9({}))); + static_assert(noexcept(sys.bf_tls_r10())); + static_assert(noexcept(sys.bf_tls_set_r10({}))); + static_assert(noexcept(sys.bf_tls_r11())); + static_assert(noexcept(sys.bf_tls_set_r11({}))); + static_assert(noexcept(sys.bf_tls_r12())); + static_assert(noexcept(sys.bf_tls_set_r12({}))); + static_assert(noexcept(sys.bf_tls_r13())); + static_assert(noexcept(sys.bf_tls_set_r13({}))); + static_assert(noexcept(sys.bf_tls_r14())); + static_assert(noexcept(sys.bf_tls_set_r14({}))); + static_assert(noexcept(sys.bf_tls_r15())); + static_assert(noexcept(sys.bf_tls_set_r15({}))); + static_assert(noexcept(sys.bf_tls_extid())); + static_assert(noexcept(sys.bf_tls_vmid())); + static_assert(noexcept(sys.bf_tls_vpid())); + static_assert(noexcept(sys.bf_tls_vpsid())); + static_assert(noexcept(sys.bf_tls_ppid())); + static_assert(noexcept(sys.bf_tls_online_pps())); + static_assert(noexcept(sys.bf_vm_op_create_vm())); + static_assert(noexcept(sys.bf_vm_op_destroy_vm({}))); + static_assert(noexcept(sys.bf_vp_op_create_vp({}, {}))); + static_assert(noexcept(sys.bf_vp_op_destroy_vp({}))); + static_assert(noexcept(sys.bf_vp_op_migrate({}, {}))); + static_assert(noexcept(sys.bf_vps_op_create_vps({}, {}))); + static_assert(noexcept(sys.bf_vps_op_destroy_vps({}))); + static_assert(noexcept(sys.bf_vps_op_init_as_root({}))); + static_assert(noexcept(sys.bf_vps_op_read8({}, {}))); + static_assert(noexcept(sys.bf_vps_op_read16({}, {}))); + static_assert(noexcept(sys.bf_vps_op_read32({}, {}))); + static_assert(noexcept(sys.bf_vps_op_read64({}, {}))); + static_assert(noexcept(sys.bf_vps_op_write8({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_write16({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_write32({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_write64({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_read_reg({}, {}))); + static_assert(noexcept(sys.bf_vps_op_write_reg({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_run({}, {}, {}))); + static_assert(noexcept(sys.bf_vps_op_run_current())); + static_assert(noexcept(sys.bf_vps_op_advance_ip({}))); + static_assert(noexcept(sys.bf_vps_op_advance_ip_and_run_current())); + static_assert(noexcept(sys.bf_vps_op_promote({}))); + static_assert(noexcept(sys.bf_vps_op_clear_vps({}))); + static_assert(noexcept(sys.bf_intrinsic_op_rdmsr({}))); + static_assert(noexcept(sys.bf_intrinsic_op_wrmsr({}, {}))); + static_assert(noexcept(sys.bf_intrinsic_op_invlpga({}, {}))); + static_assert(noexcept(sys.bf_intrinsic_op_invept({}, {}))); + static_assert(noexcept(sys.bf_intrinsic_op_invvpid({}, {}, {}))); + static_assert(noexcept(sys.bf_mem_op_alloc_page(phys))); + static_assert(noexcept(sys.bf_mem_op_alloc_page())); + static_assert(noexcept(sys.bf_mem_op_free_page({}))); + static_assert(noexcept(sys.bf_mem_op_alloc_huge({}, phys))); + static_assert(noexcept(sys.bf_mem_op_alloc_huge({}))); + static_assert(noexcept(sys.bf_mem_op_free_huge({}))); + static_assert(noexcept(sys.bf_mem_op_alloc_heap({}))); + static_assert(noexcept(sys.bf_read_phys({}))); + static_assert(noexcept(sys.bf_write_phys({}, {}))); + static_assert(noexcept(sys.bf_virt_to_phys({}))); + static_assert(noexcept(sys.bf_phys_to_virt({}))); + }; + }; + }; + + bsl::ut_scenario{"verify constness"} = []() noexcept { + bsl::ut_given{} = []() noexcept { + syscall::fixture_t fixture2{}; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(syscall::FIXTURE1.test_member_const()); + bsl::ut_check(fixture2.test_member_nonconst()); + }; + }; + }; + + return bsl::ut_success(); +} diff --git a/utils/linux/llvm-bareflank.tar.gz b/utils/linux/llvm-bareflank.tar.gz index f909de18..3429af6a 100644 Binary files a/utils/linux/llvm-bareflank.tar.gz and b/utils/linux/llvm-bareflank.tar.gz differ diff --git a/vmmctl/CMakeLists.txt b/vmmctl/CMakeLists.txt index bbfb784e..093dad1f 100644 --- a/vmmctl/CMakeLists.txt +++ b/vmmctl/CMakeLists.txt @@ -19,10 +19,14 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -include(${CMAKE_CURRENT_LIST_DIR}/../cmake/function/hypervisor_add_header_depends.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/function/hypervisor_target_source.cmake) add_executable(vmmctl) +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + target_include_directories(vmmctl PRIVATE src $<$:${CMAKE_CURRENT_LIST_DIR}/src/linux> @@ -33,6 +37,10 @@ target_include_directories(vmmctl SYSTEM PRIVATE ${CMAKE_BINARY_DIR}/include ) +# ------------------------------------------------------------------------------ +# Headers +# ------------------------------------------------------------------------------ + list(APPEND HEADERS ${CMAKE_CURRENT_LIST_DIR}/src/linux/ifmap.hpp ${CMAKE_CURRENT_LIST_DIR}/src/linux/ioctl.hpp @@ -41,11 +49,15 @@ list(APPEND HEADERS ${CMAKE_CURRENT_LIST_DIR}/src/vmmctl_main.hpp ) -target_sources(vmmctl PRIVATE - src/main.cpp -) +# ------------------------------------------------------------------------------ +# Sources +# ------------------------------------------------------------------------------ -hypervisor_add_header_depends(src/main.cpp ${HEADERS}) +hypervisor_target_source(vmmctl src/main.cpp ${HEADERS}) + +# ------------------------------------------------------------------------------ +# Libraries +# ------------------------------------------------------------------------------ target_link_libraries(vmmctl PRIVATE bsl @@ -54,3 +66,17 @@ target_link_libraries(vmmctl PRIVATE $<$:SetupAPI> $<$:libcmt.lib> ) + +# ------------------------------------------------------------------------------ +# Options +# ------------------------------------------------------------------------------ + +target_compile_options(vmmctl PRIVATE + -Wno-frame-larger-than= +) + +# ------------------------------------------------------------------------------ +# Install +# ------------------------------------------------------------------------------ + +install(TARGETS vmmctl DESTINATION bin) diff --git a/vmmctl/src/linux/ifmap.hpp b/vmmctl/src/linux/ifmap.hpp index 681d48da..3b6a3059 100644 --- a/vmmctl/src/linux/ifmap.hpp +++ b/vmmctl/src/linux/ifmap.hpp @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -46,13 +45,10 @@ namespace vmmctl { - namespace details - { - /// @brief defines what an error looks like from a POSIX call. - constexpr bsl::safe_int32 IFMAP_POSIX_ERROR{-1}; - /// @brief defines what an invalid file is. - constexpr bsl::safe_int32 IFMAP_INVALID_FILE{-1}; - } + /// @brief defines what an error looks like from a POSIX call. + constexpr bsl::safe_int32 IFMAP_POSIX_ERROR{-1}; + /// @brief defines what an invalid file is. + constexpr bsl::safe_int32 IFMAP_INVALID_FILE{-1}; /// @class bsl::ifmap /// @@ -63,9 +59,9 @@ namespace vmmctl class ifmap final { /// @brief stores a handle to the mapped file. - bsl::int32 m_file{details::IFMAP_INVALID_FILE.get()}; + bsl::int32 m_file{IFMAP_INVALID_FILE.get()}; /// @brief stores a view of the file that is mapped. - bsl::span m_data{}; + bsl::span m_data{}; /// /// @brief Swaps *this with other @@ -96,7 +92,7 @@ namespace vmmctl /// /// @brief Creates a default ifmap that has not yet been mapped. /// - ifmap() noexcept = default; + constexpr ifmap() noexcept = default; /// /// @brief Creates a bsl::ifmap given a the filename and path of @@ -105,30 +101,30 @@ namespace vmmctl /// /// @param filename the filename and path of the file to map /// - explicit ifmap(bsl::string_view const &filename) noexcept + explicit constexpr ifmap(bsl::string_view const &filename) noexcept { using stat_t = struct stat; // We don't have a choice here // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) m_file = open(filename.data(), O_RDONLY); - if (bsl::unlikely(details::IFMAP_POSIX_ERROR.get() == m_file)) { + if (bsl::unlikely(IFMAP_POSIX_ERROR.get() == m_file)) { bsl::alert() << "failed to open read-only file: " // -- << filename // -- << bsl::endl; - m_file = details::IFMAP_INVALID_FILE.get(); + m_file = IFMAP_INVALID_FILE.get(); return; } stat_t s{}; - if (bsl::unlikely(details::IFMAP_POSIX_ERROR.get() == fstat(m_file, &s))) { + if (bsl::unlikely(IFMAP_POSIX_ERROR.get() == fstat(m_file, &s))) { bsl::alert() << "failed to get the size of the read-only file: " // -- << filename // -- << bsl::endl; bsl::discard(close(m_file)); - m_file = details::IFMAP_INVALID_FILE.get(); + m_file = IFMAP_INVALID_FILE.get(); return; } @@ -150,29 +146,29 @@ namespace vmmctl << bsl::endl; bsl::discard(close(m_file)); - m_file = details::IFMAP_INVALID_FILE.get(); + m_file = IFMAP_INVALID_FILE.get(); return; } - m_data = {static_cast(ptr), bsl::to_umax(s.st_size)}; + m_data = {static_cast(ptr), bsl::to_umax(s.st_size)}; } /// /// @brief Destructor unmaps a previously mapped file. /// - ~ifmap() noexcept = default; - // { - // // if (details::IFMAP_INVALID_FILE.get() != m_file) { - // // // Not given a choice here due to the APIs provided by Linux - // // // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast,-warnings-as-errors) - // // bsl::discard(munmap(const_cast(m_data.data()), m_data.size().get())); - // // bsl::discard(close(m_file)); - // // m_file = details::IFMAP_INVALID_FILE.get(); - // // } - // // else { - // // bsl::touch(); - // // } - // } + constexpr ~ifmap() noexcept + { + if (IFMAP_INVALID_FILE.get() != m_file) { + // Not given a choice here due to the APIs provided by Linux + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast,-warnings-as-errors) + bsl::discard(munmap(const_cast(m_data.data()), m_data.size().get())); + bsl::discard(close(m_file)); + m_file = IFMAP_INVALID_FILE.get(); + } + else { + bsl::touch(); + } + } /// /// @brief copy constructor @@ -191,7 +187,7 @@ namespace vmmctl constexpr ifmap(ifmap &&o) noexcept : m_file{bsl::move(o.m_file)}, m_data{bsl::move(o.m_data)} { - o.m_file = details::IFMAP_INVALID_FILE.get(); + o.m_file = IFMAP_INVALID_FILE.get(); o.m_data = {}; } @@ -226,7 +222,7 @@ namespace vmmctl /// @return Returns a span to the read-only mapped file. /// [[nodiscard]] constexpr auto - view() const noexcept -> bsl::span + view() const noexcept -> bsl::span { return m_data; } @@ -263,7 +259,7 @@ namespace vmmctl /// /// @return Returns !empty() /// - [[nodiscard]] constexpr explicit operator bool() const noexcept + [[nodiscard]] explicit constexpr operator bool() const noexcept { return !this->empty(); } diff --git a/vmmctl/src/linux/ioctl.hpp b/vmmctl/src/linux/ioctl.hpp index 97eb1655..9038f49a 100644 --- a/vmmctl/src/linux/ioctl.hpp +++ b/vmmctl/src/linux/ioctl.hpp @@ -40,11 +40,8 @@ namespace vmmctl { - namespace details - { - /// @brief defines what an invalid handle is. - constexpr bsl::safe_int32 IOCTL_INVALID_HNDL{-1}; - } + /// @brief defines what an invalid handle is. + constexpr bsl::safe_int32 IOCTL_INVALID_HNDL{-1}; /// @class bsl::ioctl /// @@ -56,7 +53,7 @@ namespace vmmctl class ioctl final { /// @brief stores a handle to the device driver. - bsl::int32 m_hndl{details::IOCTL_INVALID_HNDL.get()}; + bsl::int32 m_hndl{IOCTL_INVALID_HNDL.get()}; /// /// @brief Swaps *this with other @@ -77,16 +74,14 @@ namespace vmmctl /// with a device driver through an IOCTL interface. /// /// - /// @tparam CSTR the string type that used to describe "name" /// @param name the name of the device driver to IOCTL. /// - template - explicit ioctl(CSTR name) noexcept + explicit constexpr ioctl(bsl::string_view const &name) noexcept { // We don't have a choice here // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-vararg) m_hndl = open(name.data(), O_RDWR); - if (bsl::unlikely(details::IOCTL_INVALID_HNDL.get() == m_hndl)) { + if (bsl::unlikely(IOCTL_INVALID_HNDL.get() == m_hndl)) { bsl::error() << "ioctl open failed\n"; return; } @@ -97,9 +92,9 @@ namespace vmmctl /// /// @brief Destructor /// - ~ioctl() noexcept + constexpr ~ioctl() noexcept { - if (bsl::unlikely(details::IOCTL_INVALID_HNDL.get() != m_hndl)) { + if (bsl::unlikely(IOCTL_INVALID_HNDL.get() != m_hndl)) { bsl::discard(close(m_hndl)); } else { @@ -123,7 +118,7 @@ namespace vmmctl /// constexpr ioctl(ioctl &&o) noexcept : m_hndl{bsl::move(o.m_hndl)} { - o.m_hndl = details::IOCTL_INVALID_HNDL.get(); + o.m_hndl = IOCTL_INVALID_HNDL.get(); } /// @@ -161,7 +156,7 @@ namespace vmmctl [[nodiscard]] constexpr auto is_open() const noexcept -> bool { - return details::IOCTL_INVALID_HNDL.get() != m_hndl; + return IOCTL_INVALID_HNDL.get() != m_hndl; } /// @@ -170,7 +165,7 @@ namespace vmmctl /// /// @return Returns is_open() /// - [[nodiscard]] constexpr explicit operator bool() const noexcept + [[nodiscard]] explicit constexpr operator bool() const noexcept { return this->is_open(); } @@ -180,15 +175,13 @@ namespace vmmctl /// data. /// /// - /// @tparam REQUEST the type of request /// @param req the request /// @return Returns true if the IOCTL succeeded, false otherwise. /// - template [[nodiscard]] constexpr auto - send(bsl::safe_integral const &req) const noexcept -> bool + send(bsl::safe_uintmax const &req) const noexcept -> bool { - if (bsl::unlikely(details::IOCTL_INVALID_HNDL.get() == m_hndl)) { + if (bsl::unlikely(IOCTL_INVALID_HNDL.get() == m_hndl)) { bsl::error() << "failed to send, ioctl not properly initialized\n"; return false; } @@ -212,24 +205,20 @@ namespace vmmctl /// @brief Reads data from the device driver /// /// - /// @tparam REQUEST the type of request /// @param req the request /// @param data a pointer to read data to /// @param size the size of the buffer being read to /// @return Returns true if the IOCTL succeeded, false otherwise. /// - template [[nodiscard]] constexpr auto // This conflicts with read() from unistd.h when it is included. // NOLINTNEXTLINE(bsl-using-ident-unique-namespace) - read( - bsl::safe_integral const &req, - void *const data, - bsl::safe_uintmax const &size) const noexcept -> bool + read_data(bsl::safe_uintmax const &req, void *const data, bsl::safe_uintmax const &size) + const noexcept -> bool { bsl::discard(size); - if (bsl::unlikely(details::IOCTL_INVALID_HNDL.get() == m_hndl)) { + if (bsl::unlikely(IOCTL_INVALID_HNDL.get() == m_hndl)) { bsl::error() << "failed to read, ioctl not properly initialized\n"; return false; } @@ -258,22 +247,20 @@ namespace vmmctl /// @brief Writes data to the device driver /// /// - /// @tparam REQUEST the type of request /// @param req the request /// @param data a pointer to write data from /// @param size the size of the buffer being written from /// @return Returns true if the IOCTL succeeded, false otherwise. /// - template [[nodiscard]] constexpr auto - write( - bsl::safe_integral const &req, + write_data( + bsl::safe_uintmax const &req, void const *const data, bsl::safe_uintmax const &size) const noexcept -> bool { bsl::discard(size); - if (bsl::unlikely(details::IOCTL_INVALID_HNDL.get() == m_hndl)) { + if (bsl::unlikely(IOCTL_INVALID_HNDL.get() == m_hndl)) { bsl::error() << "failed to write, ioctl not properly initialized\n"; return false; } @@ -302,22 +289,20 @@ namespace vmmctl /// @brief Reads/writes data from/to the device driver /// /// - /// @tparam REQUEST the type of request /// @param req the request /// @param data a pointer to read/write data to/from /// @param size the size of the buffer being read/written to/from /// @return Returns true if the IOCTL succeeded, false otherwise. /// - template [[nodiscard]] constexpr auto - read_write( - bsl::safe_integral const &req, + read_write_data( + bsl::safe_uintmax const &req, void *const data, bsl::safe_uintmax const &size) const noexcept -> bool { bsl::discard(size); - if (bsl::unlikely(details::IOCTL_INVALID_HNDL.get() == m_hndl)) { + if (bsl::unlikely(IOCTL_INVALID_HNDL.get() == m_hndl)) { bsl::error() << "failed to read/write, ioctl not properly initialized\n"; return false; } diff --git a/vmmctl/src/main.cpp b/vmmctl/src/main.cpp index c3a34015..becae078 100644 --- a/vmmctl/src/main.cpp +++ b/vmmctl/src/main.cpp @@ -31,15 +31,11 @@ #include #include #include +#include +#include #include #include -namespace vmmctl -{ - /// @brief stores the main app for the VMCTL - constinit vmmctl_main g_app{}; -} - /// /// @brief Provides the main entry point for this application. /// @@ -51,8 +47,11 @@ namespace vmmctl [[nodiscard]] auto main(bsl::int32 const argc, bsl::cstr_type const argv[]) noexcept -> bsl::exit_code { + bsl::enable_color(); + bsl::arguments args{bsl::to_umax(argc), argv}; ++args; - return vmmctl::g_app.process(bsl::move(args)); + vmmctl::vmmctl_main app{}; + return app.process(bsl::move(args)); } diff --git a/vmmctl/src/vmmctl_main.hpp b/vmmctl/src/vmmctl_main.hpp index d52849c2..93b53a06 100644 --- a/vmmctl/src/vmmctl_main.hpp +++ b/vmmctl/src/vmmctl_main.hpp @@ -26,13 +26,14 @@ #define VMMCTL_MAIN_HPP #include +#include +#include #include #include #include #include #include -#include #include #include #include @@ -46,6 +47,9 @@ namespace vmmctl { + /// @brief defines the IOCTL version this code supports. + constexpr auto IOCTL_VERSION{1_umax}; + /// @class vmmctl::vmmctl_main /// /// @@ -54,29 +58,22 @@ namespace vmmctl /// to dump the contents of the VMM's internal debug ring to the /// console for debugging. /// - /// - /// @tparam IOCTL the ioctl implementation to use. Normally this is just - /// bsl::ioctl, but during testing this might be a mock. - /// @tparam IFMAP the ifmap implementation to use. Normally this is just - /// bsl::ifmap, but during testing this might be a mock. - /// - template class vmmctl_main final { /// @brief stores the mapped ELF file for the microkernel - IFMAP m_mapped_mk_elf_file{}; + ifmap m_mapped_mk_elf_file{}; /// @brief stores the mapped ELF files for each extension - bsl::array m_mapped_ext_elf_files{}; + bsl::array m_mapped_ext_elf_files{}; /// @brief stores the arguments for stopping the VMM. - loader::stop_vmm_args_t m_stop_vmm_ctl_args{bsl::ONE_UMAX.get()}; + loader::stop_vmm_args_t m_stop_vmm_ctl_args{IOCTL_VERSION.get()}; /// @brief stores the arguments for dumping the VMM. - loader::dump_vmm_args_t m_dump_vmm_ctl_args{bsl::ONE_UMAX.get(), {}}; + loader::dump_vmm_args_t m_dump_vmm_ctl_args{IOCTL_VERSION.get(), {}}; /// /// @brief Displays the help menu for vmmctl /// - constexpr void - help() const noexcept + static constexpr void + help() noexcept { bsl::print() << "Usage: vmmctl start microkernel ext1 ..." << bsl::endl; bsl::print() << " or: vmmctl stop" << bsl::endl; @@ -87,24 +84,24 @@ namespace vmmctl } /// - /// @brief Writes a provided request to the loader given an IOCTL + /// @brief Writes a provided request to the loader given an ioctl /// to the loader as well as the arguments to send to the loader. /// /// /// @tparam R the type that defines the request to give the loader /// @tparam A the type that defines the arguments to give the loader /// @param request the request to give the loader - /// @param ctl the IOCTL to the loader + /// @param ctl the ioctl to the loader /// @param ctl_args the arguments to give the loader /// @return Returns bsl::exit_success on success, bsl::exit_failure /// otherwise /// template [[nodiscard]] constexpr auto - write(R const &request, IOCTL const &ctl, A const *const ctl_args) const noexcept + write_data(R const &request, ioctl const &ctl, A const *const ctl_args) const noexcept -> bsl::exit_code { - if (!ctl.write(request, ctl_args, bsl::size_of())) { + if (!ctl.write_data(request, ctl_args, bsl::size_of())) { bsl::error() << "vmmctl failed. check kernel logs details\n"; return bsl::exit_failure; } @@ -113,25 +110,25 @@ namespace vmmctl } /// - /// @brief Writes a provided request to the loader given an IOCTL + /// @brief Writes a provided request to the loader given an ioctl /// to the loader as well as the arguments to send to the loader. - /// The results of the IOCTL are returned in the provided args. + /// The results of the ioctl are returned in the provided args. /// /// /// @tparam R the type that defines the request to give the loader /// @tparam A the type that defines the arguments to give the loader /// @param request the request to give the loader - /// @param ctl the IOCTL to the loader + /// @param ctl the ioctl to the loader /// @param ctl_args the arguments to give the loader /// @return Returns bsl::exit_success on success, bsl::exit_failure /// otherwise /// template [[nodiscard]] constexpr auto - read_write(R const &request, IOCTL const &ctl, A *const ctl_args) const noexcept + read_write_data(R const &request, ioctl const &ctl, A *const ctl_args) const noexcept -> bsl::exit_code { - if (!ctl.read_write(request, ctl_args, bsl::size_of())) { + if (!ctl.read_write_data(request, ctl_args, bsl::size_of())) { bsl::error() << "vmmctl failed. check kernel logs details\n"; return bsl::exit_failure; } @@ -140,7 +137,7 @@ namespace vmmctl } /// - /// @brief Starts the VMM given a set of IOCTL arguments to send + /// @brief Starts the VMM given a set of ioctl arguments to send /// to the loader. /// /// @@ -151,16 +148,16 @@ namespace vmmctl [[nodiscard]] constexpr auto start_vmm(loader::start_vmm_args_t const *const ctl_args) const noexcept -> bsl::exit_code { - IOCTL ctl{loader::DEVICE_NAME}; + ioctl ctl{loader::DEVICE_NAME}; if (ctl) { - return this->write(loader::START_VMM, ctl, ctl_args); + return this->write_data(loader::START_VMM, ctl, ctl_args); } return bsl::exit_failure; } /// - /// @brief Stops the VMM given a set of IOCTL arguments to send + /// @brief Stops the VMM given a set of ioctl arguments to send /// to the loader. /// /// @@ -171,16 +168,16 @@ namespace vmmctl [[nodiscard]] constexpr auto stop_vmm(loader::stop_vmm_args_t const *const ctl_args) const noexcept -> bsl::exit_code { - IOCTL ctl{loader::DEVICE_NAME}; + ioctl ctl{loader::DEVICE_NAME}; if (ctl) { - return this->write(loader::STOP_VMM, ctl, ctl_args); + return this->write_data(loader::STOP_VMM, ctl, ctl_args); } return bsl::exit_failure; } /// - /// @brief Dumps the VMM given a set of IOCTL arguments to send + /// @brief Dumps the VMM given a set of ioctl arguments to send /// to the loader. /// /// @@ -191,9 +188,9 @@ namespace vmmctl [[nodiscard]] constexpr auto dump_vmm(loader::dump_vmm_args_t *const ctl_args) const noexcept -> bsl::exit_code { - IOCTL ctl{loader::DEVICE_NAME}; + ioctl ctl{loader::DEVICE_NAME}; if (ctl) { - if (bsl::exit_success != this->read_write(loader::DUMP_VMM, ctl, ctl_args)) { + if (bsl::exit_success != this->read_write_data(loader::DUMP_VMM, ctl, ctl_args)) { return bsl::exit_failure; } @@ -251,10 +248,10 @@ namespace vmmctl /// arguments if the ELF file was successfully mapped, otherwise /// this function returns bsl::errc_failure. /// - [[nodiscard]] constexpr auto - map_elf_file(bsl::arguments &args, IFMAP *const map) const noexcept -> bsl::errc_type + [[nodiscard]] static constexpr auto + map_elf_file(bsl::arguments &args, ifmap *const map) noexcept -> bsl::errc_type { - if ((*map = IFMAP{args.front()})) { + if ((*map = ifmap{args.front()})) { ++args; return bsl::errc_success; } @@ -295,7 +292,7 @@ namespace vmmctl [[nodiscard]] constexpr auto map_ext_elf_files_from_user(bsl::arguments &args) noexcept -> bsl::errc_type { - for (auto const &elem : m_mapped_ext_elf_files) { + for (auto const elem : m_mapped_ext_elf_files) { if (!args) { break; } @@ -311,7 +308,7 @@ namespace vmmctl } /// - /// @brief Converts the extension ELF files from an array of IFMAPs + /// @brief Converts the extension ELF files from an array of ifmaps /// to an array of buffer_t structs so that the ELF files can be /// passed to the loader. /// @@ -320,10 +317,10 @@ namespace vmmctl /// [[nodiscard]] constexpr auto convert_mapped_ext_elf_files_to_array_of_spans() const noexcept - -> bsl::array, HYPERVISOR_MAX_EXTENSIONS> + -> bsl::array, HYPERVISOR_MAX_EXTENSIONS.get()> { - bsl::array, HYPERVISOR_MAX_EXTENSIONS> files{}; - for (auto const &elem : m_mapped_ext_elf_files) { + bsl::array, HYPERVISOR_MAX_EXTENSIONS.get()> files{}; + for (auto const elem : m_mapped_ext_elf_files) { if (nullptr != elem.data) { *files.at_if(elem.index) = elem.data->view(); } @@ -337,24 +334,27 @@ namespace vmmctl /// /// @brief Given arguments from the user, this function creates the - /// IOCTL equivalent arguments that the loader expects for + /// ioctl equivalent arguments that the loader expects for /// starting the VMM /// /// /// @param args the user provided arguments - /// @return The resulting IOCTL arguments + /// @return The resulting ioctl arguments /// [[nodiscard]] constexpr auto make_start_vmm_args(bsl::arguments &args) noexcept -> bsl::result { + constexpr auto missing_microkernel{0_umax}; + constexpr auto missing_extensions{1_umax}; + auto remaining{args.remaining()}; - if (bsl::to_umax(0) == remaining) { + if (missing_microkernel == remaining) { bsl::error() << "missing the microkernel elf file\n"; return {bsl::errc_failure}; } - if (bsl::to_umax(1) == remaining) { + if (missing_extensions == remaining) { bsl::error() << "at least one extension is required\n"; return {bsl::errc_failure}; } @@ -368,7 +368,7 @@ namespace vmmctl } return {loader::start_vmm_args_t{ - bsl::ONE_UMAX.get(), + IOCTL_VERSION.get(), 0U, 0U, m_mapped_mk_elf_file.view(), @@ -382,7 +382,7 @@ namespace vmmctl /// /// @param cmd the user provided command /// - constexpr void + static constexpr void process_cmd_output_error(bsl::string_view const &cmd) noexcept { if (cmd.empty()) { @@ -416,7 +416,7 @@ namespace vmmctl if (cmd == "start") { auto ctl_args{this->make_start_vmm_args(args)}; - if (auto ptr{ctl_args.get_if()}) { + if (auto const *const ptr{ctl_args.get_if()}) { return this->start_vmm(ptr); } diff --git a/vmmctl/src/windows/ifmap.hpp b/vmmctl/src/windows/ifmap.hpp index b2e9f909..ce7f9f73 100644 --- a/vmmctl/src/windows/ifmap.hpp +++ b/vmmctl/src/windows/ifmap.hpp @@ -39,7 +39,6 @@ // clang-format on -#include #include #include #include @@ -67,7 +66,7 @@ namespace vmmctl /// @brief stores a handle to the mapped file. HANDLE m_view{}; /// @brief stores a view of the file that is mapped. - bsl::span m_data{}; + bsl::span m_data{}; /// /// @brief Swaps *this with other @@ -99,7 +98,7 @@ namespace vmmctl /// /// @brief Creates a default ifmap that has not yet been mapped. /// - ifmap() noexcept = default; + constexpr ifmap() noexcept = default; /// /// @brief Creates a vmmctl::ifmap given a the filename and path of @@ -108,7 +107,7 @@ namespace vmmctl /// /// @param filename the filename and path of the file to map /// - explicit ifmap(bsl::string_view const &filename) noexcept + explicit constexpr ifmap(bsl::string_view const &filename) noexcept { m_file = CreateFileA( filename.data(), @@ -156,26 +155,26 @@ namespace vmmctl } m_data = { - static_cast(ptr), + static_cast(ptr), (bsl::to_umax(high) << bsl::to_umax(32)) | bsl::to_umax(size)}; } /// /// @brief Destructor unmaps a previously mapped file. /// - ~ifmap() noexcept = default; - // { - // if (nullptr != m_file) { - // bsl::discard(UnmapViewOfFile(m_data.data())); - // bsl::discard(CloseHandle(m_view)); - // bsl::discard(CloseHandle(m_file)); - // m_file = nullptr; - // m_view = nullptr; - // } - // else { - // bsl::touch(); - // } - // } + constexpr ~ifmap() noexcept + { + if (nullptr != m_file) { + bsl::discard(UnmapViewOfFile(m_data.data())); + bsl::discard(CloseHandle(m_view)); + bsl::discard(CloseHandle(m_file)); + m_file = nullptr; + m_view = nullptr; + } + else { + bsl::touch(); + } + } /// /// @brief copy constructor @@ -230,7 +229,7 @@ namespace vmmctl /// @return Returns a span to the read-only mapped file. /// [[nodiscard]] constexpr auto - view() const noexcept -> bsl::span + view() const noexcept -> bsl::span { return m_data; } @@ -267,7 +266,7 @@ namespace vmmctl /// /// @return Returns !empty() /// - [[nodiscard]] constexpr explicit operator bool() const noexcept + [[nodiscard]] explicit constexpr operator bool() const noexcept { return !this->empty(); } diff --git a/vmmctl/src/windows/ioctl.hpp b/vmmctl/src/windows/ioctl.hpp index d703e20b..4339851b 100644 --- a/vmmctl/src/windows/ioctl.hpp +++ b/vmmctl/src/windows/ioctl.hpp @@ -80,7 +80,7 @@ namespace vmmctl /// @param name the name of the device driver to IOCTL. /// template - explicit ioctl(GUID name) noexcept + explicit constexpr ioctl(GUID name) noexcept { BOOL ret{}; HANDLE info{}; @@ -165,7 +165,7 @@ namespace vmmctl /// /// @brief Destructor /// - ~ioctl() noexcept + constexpr ~ioctl() noexcept { if (bsl::unlikely(nullptr != m_hndl)) { bsl::discard(CloseHandle(m_hndl)); @@ -238,7 +238,7 @@ namespace vmmctl /// /// @return Returns is_open() /// - [[nodiscard]] constexpr explicit operator bool() const noexcept + [[nodiscard]] explicit constexpr operator bool() const noexcept { return this->is_open(); } @@ -248,13 +248,11 @@ namespace vmmctl /// data. /// /// - /// @tparam REQUEST the type of request /// @param req the request /// @return Returns true if the IOCTL succeeded, false otherwise. /// - template [[nodiscard]] constexpr auto - send(bsl::safe_integral const &req) const noexcept -> bool + send(bsl::safe_uintmax const &req) const noexcept -> bool { if (bsl::unlikely(nullptr == m_hndl)) { bsl::error() << "failed to send, ioctl not properly initialized\n"; @@ -283,18 +281,14 @@ namespace vmmctl /// @brief Reads data from the device driver /// /// - /// @tparam REQUEST the type of request /// @param req the request /// @param data a pointer to read data to /// @param size the size of the buffer being read to /// @return Returns true if the IOCTL succeeded, false otherwise. /// - template [[nodiscard]] constexpr auto - read( - bsl::safe_integral const &req, - void *const data, - bsl::safe_uintmax const &size) const noexcept -> bool + read_data(bsl::safe_uintmax const &req, void *const data, bsl::safe_uintmax const &size) + const noexcept -> bool { if (bsl::unlikely(nullptr == m_hndl)) { bsl::error() << "failed to read, ioctl not properly initialized\n"; @@ -334,16 +328,14 @@ namespace vmmctl /// @brief Writes data to the device driver /// /// - /// @tparam REQUEST the type of request /// @param req the request /// @param data a pointer to write data from /// @param size the size of the buffer being written from /// @return Returns true if the IOCTL succeeded, false otherwise. /// - template [[nodiscard]] constexpr auto - write( - bsl::safe_integral const &req, + write_data( + bsl::safe_uintmax const &req, void const *const data, bsl::safe_uintmax const &size) const noexcept -> bool { @@ -387,16 +379,14 @@ namespace vmmctl /// @brief Reads/writes data from/to the device driver /// /// - /// @tparam REQUEST the type of request /// @param req the request /// @param data a pointer to read/write data to/from /// @param size the size of the buffer being read/written to/from /// @return Returns true if the IOCTL succeeded, false otherwise. /// - template [[nodiscard]] constexpr auto - read_write( - bsl::safe_integral const &req, + read_write_data( + bsl::safe_uintmax const &req, void *const data, bsl::safe_uintmax const &size) const noexcept -> bool { diff --git a/vmmctl/test/.clang-tidy b/vmmctl/test/.clang-tidy new file mode 100644 index 00000000..6c0fe6ca --- /dev/null +++ b/vmmctl/test/.clang-tidy @@ -0,0 +1,61 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +Checks: + ' + -*, + bsl-*, + -bsl-template-generic-param, + -bsl-comparison-operators-forbidden, + -bsl-boolean-operators-forbidden, + -bsl-function-noexcept, + -bsl-name-prefixes, + -bsl-name-case, + -bsl-using-ident-unique-namespace, + -bsl-literals-user-defined, + bugprone-*, + -bugprone-branch-clone, + cert-*, + -cert-dcl21-cpp, + -cert-oop54-cpp, + clang-analyzer-*, + -clang-analyzer-core.CallAndMessage, + cppcoreguidelines-*, + -cppcoreguidelines-avoid-non-const-global-variables, + hicpp-*, + -hicpp-function-size, + misc-*, + -misc-misplaced-const, + -misc-non-private-member-variables-in-classes, + modernize-*, + -modernize-use-default-member-init, + performance-*, + readability-*, + -readability-redundant-member-init, + -readability-avoid-const-params-in-decls, + -readability-static-accessed-through-instance, + -readability-function-size + ' +WarningsAsErrors: '*' +HeaderFilterRegex: '.*' +AnalyzeTemporaryDtors: false +FormatStyle: none +UseColor: true diff --git a/vmmctl/test/CMakeLists.txt b/vmmctl/test/CMakeLists.txt new file mode 100644 index 00000000..dce183eb --- /dev/null +++ b/vmmctl/test/CMakeLists.txt @@ -0,0 +1,55 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +include(${bsl_SOURCE_DIR}/cmake/function/bf_add_test.cmake) + +# ------------------------------------------------------------------------------ +# Includes +# ------------------------------------------------------------------------------ + +list(APPEND INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/. +) + +list(APPEND SYSTEM_INCLUDES + ${CMAKE_CURRENT_LIST_DIR}/../../loader/include/interface/cpp +) + +# ------------------------------------------------------------------------------ +# Definitions +# ------------------------------------------------------------------------------ + +list(APPEND DEFINES + HYPERVISOR_DEBUG_RING_SIZE=0x7FF0 +) + +# ------------------------------------------------------------------------------ +# Tests +# ------------------------------------------------------------------------------ + +add_subdirectory(main) +add_subdirectory(vmmctl_main) + +add_subdirectory(linux/ifmap) +add_subdirectory(linux/ioctl) + +add_subdirectory(windows/ifmap) +add_subdirectory(windows/ioctl) diff --git a/vmmctl/test/linux/ifmap/CMakeLists.txt b/vmmctl/test/linux/ifmap/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/vmmctl/test/linux/ifmap/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/vmmctl/test/linux/ifmap/behavior.cpp b/vmmctl/test/linux/ifmap/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/vmmctl/test/linux/ifmap/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/vmmctl/test/linux/ifmap/requirements.cpp b/vmmctl/test/linux/ifmap/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/vmmctl/test/linux/ifmap/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/vmmctl/test/linux/ioctl/CMakeLists.txt b/vmmctl/test/linux/ioctl/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/vmmctl/test/linux/ioctl/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/vmmctl/test/linux/ioctl/behavior.cpp b/vmmctl/test/linux/ioctl/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/vmmctl/test/linux/ioctl/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/vmmctl/test/linux/ioctl/requirements.cpp b/vmmctl/test/linux/ioctl/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/vmmctl/test/linux/ioctl/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/vmmctl/test/main/CMakeLists.txt b/vmmctl/test/main/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/vmmctl/test/main/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/vmmctl/test/main/behavior.cpp b/vmmctl/test/main/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/vmmctl/test/main/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/vmmctl/test/main/requirements.cpp b/vmmctl/test/main/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/vmmctl/test/main/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/vmmctl/test/vmmctl_main/CMakeLists.txt b/vmmctl/test/vmmctl_main/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/vmmctl/test/vmmctl_main/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/vmmctl/test/vmmctl_main/behavior.cpp b/vmmctl/test/vmmctl_main/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/vmmctl/test/vmmctl_main/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/vmmctl/test/vmmctl_main/requirements.cpp b/vmmctl/test/vmmctl_main/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/vmmctl/test/vmmctl_main/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/vmmctl/test/windows/ifmap/CMakeLists.txt b/vmmctl/test/windows/ifmap/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/vmmctl/test/windows/ifmap/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/vmmctl/test/windows/ifmap/behavior.cpp b/vmmctl/test/windows/ifmap/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/vmmctl/test/windows/ifmap/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/vmmctl/test/windows/ifmap/requirements.cpp b/vmmctl/test/windows/ifmap/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/vmmctl/test/windows/ifmap/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +} diff --git a/vmmctl/test/windows/ioctl/CMakeLists.txt b/vmmctl/test/windows/ioctl/CMakeLists.txt new file mode 100644 index 00000000..676fac0a --- /dev/null +++ b/vmmctl/test/windows/ioctl/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (C) 2020 Assured Information Security, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +bf_add_test(requirements INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) +bf_add_test(behavior INCLUDES ${INCLUDES} SYSTEM_INCLUDES ${SYSTEM_INCLUDES} DEFINES ${DEFINES}) diff --git a/vmmctl/test/windows/ioctl/behavior.cpp b/vmmctl/test/windows/ioctl/behavior.cpp new file mode 100644 index 00000000..4ec9da72 --- /dev/null +++ b/vmmctl/test/windows/ioctl/behavior.cpp @@ -0,0 +1,60 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +namespace mk +{ + /// + /// @brief Used to execute the actual checks. We put the checks in this + /// function so that we can validate the tests both at compile-time + /// and at run-time. If a bsl::ut_check fails, the tests will either + /// fail fast at run-time, or will produce a compile-time error. + /// + /// + /// @return Always returns bsl::exit_success. + /// + [[nodiscard]] constexpr auto + tests() noexcept -> bsl::exit_code + { + return bsl::ut_success(); + } +} + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + + static_assert(mk::tests() == bsl::ut_success()); + return mk::tests(); +} diff --git a/vmmctl/test/windows/ioctl/requirements.cpp b/vmmctl/test/windows/ioctl/requirements.cpp new file mode 100644 index 00000000..088b5802 --- /dev/null +++ b/vmmctl/test/windows/ioctl/requirements.cpp @@ -0,0 +1,40 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +/// SOFTWARE. + +#include + +/// +/// @brief Main function for this unit test. If a call to bsl::ut_check() fails +/// the application will fast fail. If all calls to bsl::ut_check() pass, this +/// function will successfully return with bsl::exit_success. +/// +/// +/// @return Always returns bsl::exit_success. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + return bsl::ut_success(); +}