From 64daddf3d05f226cfec3f65852a19ede61557e9e Mon Sep 17 00:00:00 2001 From: Harshad Poshtiwala Date: Mon, 24 Jan 2022 08:38:10 +0000 Subject: [PATCH] KVM_IRQ_LINE, Implement Ioctl --- hypercall/include/mv_constants.hpp | 2 +- shim/include/handle_vm_kvm_irq_line.h | 5 +- shim/include/kvm_irq_level.h | 22 ++++++- shim/include/kvm_irq_level.hpp | 59 +++++++++++++++++++ shim/integration/CMakeLists.txt | 1 + shim/integration/kvm_irq_line.cpp | 56 ++++++++++++++++++ .../shim_platform_interface.hpp | 6 +- shim/linux/src/entry.c | 25 ++++++-- shim/src/handle_vm_kvm_irq_line.c | 17 +++++- .../tests/src/test_handle_vm_kvm_irq_line.cpp | 23 +++++++- 10 files changed, 202 insertions(+), 14 deletions(-) create mode 100644 shim/include/kvm_irq_level.hpp create mode 100644 shim/integration/kvm_irq_line.cpp diff --git a/hypercall/include/mv_constants.hpp b/hypercall/include/mv_constants.hpp index 7bb5cb6be..070b9e6a4 100644 --- a/hypercall/include/mv_constants.hpp +++ b/hypercall/include/mv_constants.hpp @@ -129,7 +129,7 @@ namespace hypercall constexpr auto MV_MAP_FLAG_UNCACHEABLE_MINUS{0x0400000000000000_u64}; /// @brief Indicates the map is mapped as WC constexpr auto MV_MAP_FLAG_WRITE_COMBINING{0x0800000000000000_u64}; - /// @brief Indicates the map is mapped as WC+ + /// @brief Indicates the map is mapped as WC constexpr auto MV_MAP_FLAG_WRITE_COMBINING_PLUS{0x1000000000000000_u64}; /// @brief Indicates the map is mapped as WT constexpr auto MV_MAP_FLAG_WRITE_THROUGH{0x2000000000000000_u64}; diff --git a/shim/include/handle_vm_kvm_irq_line.h b/shim/include/handle_vm_kvm_irq_line.h index 8f9f33bca..1251cb102 100644 --- a/shim/include/handle_vm_kvm_irq_line.h +++ b/shim/include/handle_vm_kvm_irq_line.h @@ -29,6 +29,7 @@ #include #include +#include #ifdef __cplusplus extern "C" @@ -40,10 +41,12 @@ extern "C" * @brief Handles the execution of kvm_irq_line. * * + * @param pmut_vm the argumento hold vm details of type shim_vm_t * @param pmut_ioctl_args the arguments provided by userspace * @return SHIM_SUCCESS on success, SHIM_FAILURE on failure. */ - NODISCARD int64_t handle_vm_kvm_irq_line(struct kvm_irq_level *const pmut_ioctl_args) NOEXCEPT; + NODISCARD int64_t handle_vm_kvm_irq_line( + struct shim_vm_t *const pmut_vm, struct kvm_irq_level *const pmut_ioctl_args) NOEXCEPT; #ifdef __cplusplus } diff --git a/shim/include/kvm_irq_level.h b/shim/include/kvm_irq_level.h index c959a0071..a5d1ffe19 100644 --- a/shim/include/kvm_irq_level.h +++ b/shim/include/kvm_irq_level.h @@ -29,6 +29,10 @@ #include +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wold-style-cast" +#endif + #ifdef __cplusplus extern "C" { @@ -44,8 +48,22 @@ extern "C" */ struct kvm_irq_level { - /** @brief replace me with contents from KVM API */ - int32_t dummy; + /** + * + * @brief TODO + */ + // NOLINTNEXTLINE(bsl-decl-forbidden) + union + { + /** @brief GSI*/ + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + uint32_t irq; + /** @brief not used for KVM_IRQ_LEVEL*/ + // NOLINTNEXTLINE(bsl-non-safe-integral-types-are-forbidden) + uint32_t status; + }; + /** @brief 0 or 1*/ + uint32_t level; }; #pragma pack(pop) diff --git a/shim/include/kvm_irq_level.hpp b/shim/include/kvm_irq_level.hpp new file mode 100644 index 000000000..968dc2c34 --- /dev/null +++ b/shim/include/kvm_irq_level.hpp @@ -0,0 +1,59 @@ +/// @copyright +/// Copyright (C) 2020 Assured Information Security, Inc. +/// +/// @copyright +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// @copyright +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// @copyright +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION 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_IRQ_LEVEL_HPP +#define KVM_IRQ_LEVEL_HPP + +#include +#include + +#pragma pack(push, 1) + +namespace shim +{ + /// @brief defines the size of the padding field + constexpr auto PAD_SIZE_MSI{16_umx}; + /// @struct kvm_irq_level + /// + /// + /// @brief see /include/uapi/linux/kvm.h in Linux for more details. + /// + struct kvm_irq_level final + { + // NOLINTNEXTLINE(bsl-decl-forbidden) + union + { + /** @brief GSI*/ + bsl::uint32 irq; + /** @brief not used for KVM_IRQ_LEVEL*/ + bsl::uint32 status; + }; + /** @brief 0 or 1*/ + bsl::uint32 level; + }; +} + +#pragma pack(pop) + +#endif diff --git a/shim/integration/CMakeLists.txt b/shim/integration/CMakeLists.txt index 7b5af9bb8..a4d0e5153 100644 --- a/shim/integration/CMakeLists.txt +++ b/shim/integration/CMakeLists.txt @@ -49,3 +49,4 @@ 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_irq_line HEADERS) diff --git a/shim/integration/kvm_irq_line.cpp b/shim/integration/kvm_irq_line.cpp new file mode 100644 index 000000000..af9ed5633 --- /dev/null +++ b/shim/integration/kvm_irq_line.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 irqline{mut_vcpu.send(shim::KVM_IRQ_LINE)}; + integration::verify(irqline.is_pos()); + integration::verify(irqline >= 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..fd81b538f 100644 --- a/shim/linux/include/platform_interface/shim_platform_interface.hpp +++ b/shim/linux/include/platform_interface/shim_platform_interface.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -163,8 +164,9 @@ namespace shim static_cast(_IOW(SHIMIO.get(), 0x8d, struct kvm_fpu))}; /// @brief defines KVM's KVM_CREATE_IRQCHIP IOCTL constexpr bsl::safe_umx KVM_CREATE_IRQCHIP{static_cast(_IO(SHIMIO.get(), 0x60))}; - // /// @brief defines KVM's KVM_IRQ_LINE IOCTL - // constexpr bsl::safe_umx KVM_IRQ_LINE{static_cast(_IOW(SHIMIO.get(), 0x61, struct kvm_irq_level))}; + /// @brief defines KVM's KVM_IRQ_LINE IOCTL + constexpr bsl::safe_umx KVM_IRQ_LINE{ + static_cast(_IOW(SHIMIO.get(), 0x61, struct kvm_irq_level))}; // /// @brief defines KVM's KVM_GET_IRQCHIP IOCTL // constexpr bsl::safe_umx KVM_GET_IRQCHIP{static_cast(_IOWR(SHIMIO.get(), 0x62, struct kvm_irqchip))}; // /// @brief defines KVM's KVM_SET_IRQCHIP IOCTL diff --git a/shim/linux/src/entry.c b/shim/linux/src/entry.c index 95110e721..cdd27701f 100644 --- a/shim/linux/src/entry.c +++ b/shim/linux/src/entry.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -616,10 +617,24 @@ dispatch_vm_kvm_ioeventfd(struct kvm_ioeventfd *const ioctl_args) } static long -dispatch_vm_kvm_irq_line(struct kvm_irq_level *const ioctl_args) +dispatch_vm_kvm_irq_line( + struct shim_vm_t *const pmut_vm, + struct kvm_irq_level *const pmut_ioctl_args) { - (void)ioctl_args; - return -EINVAL; + struct kvm_irq_level mut_args; + uint64_t const size = sizeof(mut_args); + + if (platform_copy_from_user(&mut_args, pmut_ioctl_args, size)) { + bferror("platform_copy_from_user failed"); + return -EINVAL; + } + + if (handle_vm_kvm_irq_line(pmut_vm, &mut_args)) { + bferror("handle_vm_kvm_irq_line failed"); + return -EINVAL; + } + + return 0; } static long @@ -844,7 +859,9 @@ dev_unlocked_ioctl_vm( } case KVM_IRQ_LINE: { - return dispatch_vm_kvm_irq_line((struct kvm_irq_level *)ioctl_args); + return dispatch_vm_kvm_irq_line( + (struct shim_vm_t *)pmut_mut_vm, + (struct kvm_irq_level *)ioctl_args); } case KVM_IRQFD: { diff --git a/shim/src/handle_vm_kvm_irq_line.c b/shim/src/handle_vm_kvm_irq_line.c index 681359dac..64378af3d 100644 --- a/shim/src/handle_vm_kvm_irq_line.c +++ b/shim/src/handle_vm_kvm_irq_line.c @@ -24,20 +24,33 @@ * SOFTWARE. */ +#include +#include #include #include +#include +#include /** * * @brief Handles the execution of kvm_irq_line. * * + * @param pmut_vm the argumento hold vm details of type shim_vm_t * @param pmut_ioctl_args the arguments provided by userspace * @return SHIM_SUCCESS on success, SHIM_FAILURE on failure. */ NODISCARD int64_t -handle_vm_kvm_irq_line(struct kvm_irq_level *const pmut_ioctl_args) NOEXCEPT +handle_vm_kvm_irq_line( + struct shim_vm_t *const pmut_vm, struct kvm_irq_level *const pmut_ioctl_args) NOEXCEPT { - (void)pmut_ioctl_args; + platform_expects(NULL != pmut_vm); + 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_vm_kvm_irq_line.cpp b/shim/tests/src/test_handle_vm_kvm_irq_line.cpp index f20ee6795..00b39154c 100644 --- a/shim/tests/src/test_handle_vm_kvm_irq_line.cpp +++ b/shim/tests/src/test_handle_vm_kvm_irq_line.cpp @@ -23,9 +23,10 @@ /// SOFTWARE. #include "../../include/handle_vm_kvm_irq_line.h" +#include "shim_vm_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_irq_level mut_args{}; + shim_vm_t mut_vm{}; bsl::ut_when{} = [&]() noexcept { bsl::ut_then{} = [&]() noexcept { - bsl::ut_check(SHIM_SUCCESS == handle_vm_kvm_irq_line(&mut_args)); + bsl::ut_check(SHIM_SUCCESS == handle_vm_kvm_irq_line(&mut_vm, &mut_args)); + }; + }; + }; + }; + + bsl::ut_scenario{"hypervisor not detected"} = []() noexcept { + bsl::ut_given{} = [&]() noexcept { + kvm_irq_level mut_args{}; + shim_vm_t mut_vm{}; + bsl::ut_when{} = [&]() noexcept { + g_mut_hypervisor_detected = false; + bsl::ut_then{} = [&]() noexcept { + bsl::ut_check(SHIM_FAILURE == handle_vm_kvm_irq_line(&mut_vm, &mut_args)); + }; + bsl::ut_cleanup{} = [&]() noexcept { + g_mut_hypervisor_detected = true; }; }; };