From 981bf387457a5525b864547b2dc950a5477ca08f Mon Sep 17 00:00:00 2001 From: Harshad Poshtiwala Date: Sun, 16 Jan 2022 16:43:06 +0000 Subject: [PATCH] SET GET LAPIC, Implement ioctl --- shim/include/handle_vcpu_kvm_get_lapic.h | 9 ++- shim/include/handle_vcpu_kvm_set_lapic.h | 7 ++- shim/include/kvm_lapic_state.h | 6 +- shim/include/kvm_lapic_state.hpp | 55 ++++++++++++++++++ shim/integration/CMakeLists.txt | 2 + shim/integration/kvm_get_lapic.cpp | 56 +++++++++++++++++++ shim/integration/kvm_set_lapic.cpp | 56 +++++++++++++++++++ .../shim_platform_interface.hpp | 12 ++-- shim/linux/src/entry.c | 53 +++++++++++++++--- shim/src/handle_vcpu_kvm_get_lapic.c | 17 +++++- shim/src/handle_vcpu_kvm_set_lapic.c | 17 +++++- .../src/test_handle_vcpu_kvm_get_lapic.cpp | 23 +++++++- .../src/test_handle_vcpu_kvm_set_lapic.cpp | 23 +++++++- 13 files changed, 308 insertions(+), 28 deletions(-) create mode 100644 shim/include/kvm_lapic_state.hpp create mode 100644 shim/integration/kvm_get_lapic.cpp create mode 100644 shim/integration/kvm_set_lapic.cpp diff --git a/shim/include/handle_vcpu_kvm_get_lapic.h b/shim/include/handle_vcpu_kvm_get_lapic.h index 5f204cfc4..c2ce6e9e2 100644 --- a/shim/include/handle_vcpu_kvm_get_lapic.h +++ b/shim/include/handle_vcpu_kvm_get_lapic.h @@ -29,6 +29,7 @@ #include #include +#include #ifdef __cplusplus extern "C" @@ -40,11 +41,13 @@ extern "C" * @brief Handles the execution of kvm_get_lapic. * * - * @param pmut_ioctl_args the arguments provided by userspace + * @param vcpu arguments received from private data + * @param pmut_ioctl_args returns the virtual lapic args * @return SHIM_SUCCESS on success, SHIM_FAILURE on failure. */ - NODISCARD int64_t - handle_vcpu_kvm_get_lapic(struct kvm_lapic_state *const pmut_ioctl_args) NOEXCEPT; + NODISCARD int64_t handle_vcpu_kvm_get_lapic( + struct shim_vcpu_t const *const vcpu, + struct kvm_lapic_state *const pmut_ioctl_args) NOEXCEPT; #ifdef __cplusplus } diff --git a/shim/include/handle_vcpu_kvm_set_lapic.h b/shim/include/handle_vcpu_kvm_set_lapic.h index 70d08031a..b4278fde8 100644 --- a/shim/include/handle_vcpu_kvm_set_lapic.h +++ b/shim/include/handle_vcpu_kvm_set_lapic.h @@ -29,6 +29,7 @@ #include #include +#include #ifdef __cplusplus extern "C" @@ -40,11 +41,13 @@ extern "C" * @brief Handles the execution of kvm_set_lapic. * * + * @param vcpu arguments received from private data * @param pmut_ioctl_args the arguments provided by userspace * @return SHIM_SUCCESS on success, SHIM_FAILURE on failure. */ - NODISCARD int64_t - handle_vcpu_kvm_set_lapic(struct kvm_lapic_state *const pmut_ioctl_args) NOEXCEPT; + NODISCARD int64_t handle_vcpu_kvm_set_lapic( + struct shim_vcpu_t const *const vcpu, + struct kvm_lapic_state *const pmut_ioctl_args) NOEXCEPT; #ifdef __cplusplus } diff --git a/shim/include/kvm_lapic_state.h b/shim/include/kvm_lapic_state.h index 8f5ce4f59..795fa7656 100644 --- a/shim/include/kvm_lapic_state.h +++ b/shim/include/kvm_lapic_state.h @@ -27,6 +27,7 @@ #ifndef KVM_LAPIC_STATE_H #define KVM_LAPIC_STATE_H +#define KVM_APIC_REG_SIZE 1024 #include #ifdef __cplusplus @@ -44,8 +45,9 @@ extern "C" */ struct kvm_lapic_state { - /** @brief replace me with contents from KVM API */ - int32_t dummy; + + /** @brief the registers of lapic to set or get */ + char regs[KVM_APIC_REG_SIZE]; }; #pragma pack(pop) diff --git a/shim/include/kvm_lapic_state.hpp b/shim/include/kvm_lapic_state.hpp new file mode 100644 index 000000000..cfd1871aa --- /dev/null +++ b/shim/include/kvm_lapic_state.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 KVM_LAPIC_STATE_HPP +#define KVM_LAPIC_STATE_HPP + +#include +#include +#include + +#pragma pack(push, 1) + +namespace shim +{ + /// @brief defines the size of the padding3 field + constexpr auto KVM_APIC_REG_SIZE{1024_umx}; + /// @struct kvm_lapic_state + /// + /// + /// @brief see /include/uapi/linux/kvm.h in Linux for more details. + /// + struct kvm_lapic_state final + { + /// @brief TODO + bsl::array regs; + }; + +} + +#pragma pack(pop) + +#endif \ No newline at end of file diff --git a/shim/integration/CMakeLists.txt b/shim/integration/CMakeLists.txt index 7b5af9bb8..df572ba2c 100644 --- a/shim/integration/CMakeLists.txt +++ b/shim/integration/CMakeLists.txt @@ -49,3 +49,5 @@ microv_add_shim_integration(kvm_get_msr_index_list HEADERS) microv_add_shim_integration(kvm_get_supported_cpuid HEADERS) microv_add_shim_integration(kvm_get_msrs HEADERS) microv_add_shim_integration(kvm_set_msrs HEADERS) +microv_add_shim_integration(kvm_get_lapic HEADERS) +microv_add_shim_integration(kvm_set_lapic HEADERS) diff --git a/shim/integration/kvm_get_lapic.cpp b/shim/integration/kvm_get_lapic.cpp new file mode 100644 index 000000000..1828d9b7e --- /dev/null +++ b/shim/integration/kvm_get_lapic.cpp @@ -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 +#include +#include + +/// +/// @brief Provides the main entry point for this application. +/// +/// +/// @return bsl::exit_success on success, bsl::exit_failure otherwise. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + integration::ioctl_t mut_system_ctl{shim::DEVICE_NAME}; + auto const vmfd{mut_system_ctl.send(shim::KVM_CREATE_VM)}; + integration::ioctl_t mut_vm{bsl::to_i32(vmfd)}; + auto const vcpufd{mut_vm.send(shim::KVM_CREATE_VCPU)}; + integration::ioctl_t mut_vcpu{bsl::to_i32(vcpufd)}; + constexpr auto mut_ret{0_i64}; + { + auto const lapic{mut_vcpu.send(shim::KVM_GET_LAPIC)}; + integration::verify(lapic.is_pos()); + integration::verify(lapic >= mut_ret.get()); + } + return bsl::exit_success; +} diff --git a/shim/integration/kvm_set_lapic.cpp b/shim/integration/kvm_set_lapic.cpp new file mode 100644 index 000000000..cb324e866 --- /dev/null +++ b/shim/integration/kvm_set_lapic.cpp @@ -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 +#include +#include + +/// +/// @brief Provides the main entry point for this application. +/// +/// +/// @return bsl::exit_success on success, bsl::exit_failure otherwise. +/// +[[nodiscard]] auto +main() noexcept -> bsl::exit_code +{ + bsl::enable_color(); + integration::ioctl_t mut_system_ctl{shim::DEVICE_NAME}; + auto const vmfd{mut_system_ctl.send(shim::KVM_CREATE_VM)}; + integration::ioctl_t mut_vm{bsl::to_i32(vmfd)}; + auto const vcpufd{mut_vm.send(shim::KVM_CREATE_VCPU)}; + integration::ioctl_t mut_vcpu{bsl::to_i32(vcpufd)}; + constexpr auto mut_ret{0_i64}; + { + auto const lapic{mut_vcpu.send(shim::KVM_SET_LAPIC)}; + integration::verify(lapic.is_pos()); + integration::verify(lapic >= mut_ret.get()); + } + return bsl::exit_success; +} diff --git a/shim/linux/include/platform_interface/shim_platform_interface.hpp b/shim/linux/include/platform_interface/shim_platform_interface.hpp index 6fada866d..3e8372a7f 100644 --- a/shim/linux/include/platform_interface/shim_platform_interface.hpp +++ b/shim/linux/include/platform_interface/shim_platform_interface.hpp @@ -62,7 +62,7 @@ // #include // #include // #include -// #include +#include // #include // #include // #include @@ -218,10 +218,12 @@ namespace shim constexpr bsl::safe_umx KVM_GET_TSC_KHZ{static_cast(_IO(SHIMIO.get(), 0xa3))}; /// @brief defines KVM's KVM_SET_TSC_KHZ IOCTL constexpr bsl::safe_umx KVM_SET_TSC_KHZ{static_cast(_IO(SHIMIO.get(), 0xa2))}; - // /// @brief defines KVM's KVM_GET_LAPIC IOCTL - // constexpr bsl::safe_umx KVM_GET_LAPIC{static_cast(_IOR(SHIMIO.get(), 0x8e, struct kvm_lapic_state))}; - // /// @brief defines KVM's KVM_SET_LAPIC IOCTL - // constexpr bsl::safe_umx KVM_SET_LAPIC{static_cast(_IOW(SHIMIO.get(), 0x8f, struct kvm_lapic_state))}; + /// @brief defines KVM's KVM_GET_LAPIC IOCTL + constexpr bsl::safe_umx KVM_GET_LAPIC{ + static_cast(_IOR(SHIMIO.get(), 0x8e, struct kvm_lapic_state))}; + /// @brief defines KVM's KVM_SET_LAPIC IOCTL + constexpr bsl::safe_umx KVM_SET_LAPIC{ + static_cast(_IOW(SHIMIO.get(), 0x8f, struct kvm_lapic_state))}; // /// @brief defines KVM's KVM_IOEVENTFD IOCTL // constexpr bsl::safe_umx KVM_IOEVENTFD{static_cast(_IOW(SHIMIO.get(), 0x79, struct kvm_ioeventfd))}; /// @brief defines KVM's KVM_NMI IOCTL diff --git a/shim/linux/src/entry.c b/shim/linux/src/entry.c index 95110e721..bf78dfca9 100644 --- a/shim/linux/src/entry.c +++ b/shim/linux/src/entry.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -976,10 +978,27 @@ dispatch_vcpu_kvm_get_fpu( } static long -dispatch_vcpu_kvm_get_lapic(struct kvm_lapic_state *const ioctl_args) +dispatch_vcpu_kvm_get_lapic( + struct shim_vcpu_t const *const vcpu, + struct kvm_lapic_state *const user_args) { - (void)ioctl_args; - return -EINVAL; + struct kvm_lapic_state mut_args; + + if (NULL == user_args) { + bferror("user_args are null"); + return -EINVAL; + } + + if (handle_vcpu_kvm_get_lapic(vcpu, &mut_args)) { + bferror("handle_vcpu_kvm_get_lapic failed"); + return -EINVAL; + } + + if (platform_copy_to_user(user_args, &mut_args, sizeof(mut_args))) { + bferror("platform_copy_to_user failed"); + return -EINVAL; + } + return 0; } static long @@ -1230,10 +1249,28 @@ dispatch_vcpu_kvm_set_guest_debug(struct kvm_guest_debug *const ioctl_args) } static long -dispatch_vcpu_kvm_set_lapic(struct kvm_lapic_state *const ioctl_args) +dispatch_vcpu_kvm_set_lapic( + struct shim_vcpu_t const *const vcpu, + struct kvm_lapic_state *const user_args) { - (void)ioctl_args; - return -EINVAL; + struct kvm_lapic_state mut_args; + + if (NULL == user_args) { + bferror("user_args are null"); + return -EINVAL; + } + + if (platform_copy_from_user(&mut_args, user_args, sizeof(mut_args))) { + bferror("platform_copy_from_user failed"); + return -EINVAL; + } + + if (handle_vcpu_kvm_set_lapic(vcpu, &mut_args)) { + bferror("handle_vcpu_kvm_set_lapic failed"); + return -EINVAL; + } + + return 0; } static long @@ -1451,7 +1488,7 @@ dev_unlocked_ioctl_vcpu( case KVM_GET_LAPIC: { return dispatch_vcpu_kvm_get_lapic( - (struct kvm_lapic_state *)ioctl_args); + pmut_mut_vcpu, (struct kvm_lapic_state *)ioctl_args); } case KVM_GET_MP_STATE: { @@ -1548,7 +1585,7 @@ dev_unlocked_ioctl_vcpu( case KVM_SET_LAPIC: { return dispatch_vcpu_kvm_set_lapic( - (struct kvm_lapic_state *)ioctl_args); + pmut_mut_vcpu, (struct kvm_lapic_state *)ioctl_args); } case KVM_SET_MP_STATE: { diff --git a/shim/src/handle_vcpu_kvm_get_lapic.c b/shim/src/handle_vcpu_kvm_get_lapic.c index c8c90ea60..eaea6f084 100644 --- a/shim/src/handle_vcpu_kvm_get_lapic.c +++ b/shim/src/handle_vcpu_kvm_get_lapic.c @@ -24,20 +24,33 @@ * SOFTWARE. */ +#include +#include #include #include +#include +#include /** * * @brief Handles the execution of kvm_get_lapic. * * + * @param vcpu arguments received from private data * @param pmut_ioctl_args the arguments provided by userspace * @return SHIM_SUCCESS on success, SHIM_FAILURE on failure. */ NODISCARD int64_t -handle_vcpu_kvm_get_lapic(struct kvm_lapic_state *const pmut_ioctl_args) NOEXCEPT +handle_vcpu_kvm_get_lapic( + struct shim_vcpu_t const *const vcpu, struct kvm_lapic_state *const pmut_ioctl_args) NOEXCEPT { - (void)pmut_ioctl_args; + platform_expects(NULL != vcpu); + platform_expects(NULL != pmut_ioctl_args); + + if (detect_hypervisor()) { + bferror("The shim is not running in a VM. Did you forget to start MicroV?"); + return SHIM_FAILURE; + } + //TODO: Cally the hypercall here after its implementation return SHIM_SUCCESS; } diff --git a/shim/src/handle_vcpu_kvm_set_lapic.c b/shim/src/handle_vcpu_kvm_set_lapic.c index ab6389b60..f09914bed 100644 --- a/shim/src/handle_vcpu_kvm_set_lapic.c +++ b/shim/src/handle_vcpu_kvm_set_lapic.c @@ -24,20 +24,33 @@ * SOFTWARE. */ +#include +#include #include #include +#include +#include /** * * @brief Handles the execution of kvm_set_lapic. * * + * @param vcpu arguments received from private data * @param pmut_ioctl_args the arguments provided by userspace * @return SHIM_SUCCESS on success, SHIM_FAILURE on failure. */ NODISCARD int64_t -handle_vcpu_kvm_set_lapic(struct kvm_lapic_state *const pmut_ioctl_args) NOEXCEPT +handle_vcpu_kvm_set_lapic( + struct shim_vcpu_t const *const vcpu, struct kvm_lapic_state *const pmut_ioctl_args) NOEXCEPT { - (void)pmut_ioctl_args; + platform_expects(NULL != vcpu); + platform_expects(NULL != pmut_ioctl_args); + + if (detect_hypervisor()) { + bferror("The shim is not running in a VM. Did you forget to start MicroV?"); + return SHIM_FAILURE; + } + //TODO: Cally the hypercall here after its implementation return SHIM_SUCCESS; } diff --git a/shim/tests/src/test_handle_vcpu_kvm_get_lapic.cpp b/shim/tests/src/test_handle_vcpu_kvm_get_lapic.cpp index 5ed9186a7..65833bffa 100644 --- a/shim/tests/src/test_handle_vcpu_kvm_get_lapic.cpp +++ b/shim/tests/src/test_handle_vcpu_kvm_get_lapic.cpp @@ -23,9 +23,10 @@ /// SOFTWARE. #include "../../include/handle_vcpu_kvm_get_lapic.h" +#include "shim_vcpu_t.h" +#include #include -#include #include @@ -43,12 +44,30 @@ namespace shim [[nodiscard]] constexpr auto tests() noexcept -> bsl::exit_code { + init_tests(); bsl::ut_scenario{"description"} = []() noexcept { bsl::ut_given{} = [&]() noexcept { kvm_lapic_state mut_args{}; + shim_vcpu_t const vcpu{}; bsl::ut_when{} = [&]() noexcept { bsl::ut_then{} = [&]() noexcept { - bsl::ut_check(SHIM_SUCCESS == handle_vcpu_kvm_get_lapic(&mut_args)); + bsl::ut_check(SHIM_SUCCESS == handle_vcpu_kvm_get_lapic(&vcpu, &mut_args)); + }; + }; + }; + }; + + bsl::ut_scenario{"hypervisor not detected"} = []() noexcept { + bsl::ut_given{} = [&]() noexcept { + kvm_lapic_state mut_args{}; + shim_vcpu_t const vcpu{}; + bsl::ut_when{} = [&]() noexcept { + g_mut_hypervisor_detected = false; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(SHIM_FAILURE == handle_vcpu_kvm_get_lapic(&vcpu, &mut_args)); + }; + bsl::ut_cleanup{} = [&]() noexcept { + g_mut_hypervisor_detected = true; }; }; }; diff --git a/shim/tests/src/test_handle_vcpu_kvm_set_lapic.cpp b/shim/tests/src/test_handle_vcpu_kvm_set_lapic.cpp index 05494a3b5..e3eb0be76 100644 --- a/shim/tests/src/test_handle_vcpu_kvm_set_lapic.cpp +++ b/shim/tests/src/test_handle_vcpu_kvm_set_lapic.cpp @@ -23,9 +23,10 @@ /// SOFTWARE. #include "../../include/handle_vcpu_kvm_set_lapic.h" +#include "shim_vcpu_t.h" +#include #include -#include #include @@ -43,12 +44,30 @@ namespace shim [[nodiscard]] constexpr auto tests() noexcept -> bsl::exit_code { + init_tests(); bsl::ut_scenario{"description"} = []() noexcept { bsl::ut_given{} = [&]() noexcept { kvm_lapic_state mut_args{}; + shim_vcpu_t const vcpu{}; bsl::ut_when{} = [&]() noexcept { bsl::ut_then{} = [&]() noexcept { - bsl::ut_check(SHIM_SUCCESS == handle_vcpu_kvm_set_lapic(&mut_args)); + bsl::ut_check(SHIM_SUCCESS == handle_vcpu_kvm_set_lapic(&vcpu, &mut_args)); + }; + }; + }; + }; + + bsl::ut_scenario{"hypervisor not detected"} = []() noexcept { + bsl::ut_given{} = [&]() noexcept { + kvm_lapic_state mut_args{}; + shim_vcpu_t const vcpu{}; + bsl::ut_when{} = [&]() noexcept { + g_mut_hypervisor_detected = false; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(SHIM_FAILURE == handle_vcpu_kvm_set_lapic(&vcpu, &mut_args)); + }; + bsl::ut_cleanup{} = [&]() noexcept { + g_mut_hypervisor_detected = true; }; }; };