diff --git a/shim/include/handle_vm_kvm_set_gsi_routing.h b/shim/include/handle_vm_kvm_set_gsi_routing.h index b05a49aaa..42d7c88d5 100644 --- a/shim/include/handle_vm_kvm_set_gsi_routing.h +++ b/shim/include/handle_vm_kvm_set_gsi_routing.h @@ -40,11 +40,12 @@ extern "C" * @brief Handles the execution of kvm_set_gsi_routing. * * + * @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_set_gsi_routing(struct kvm_irq_routing *const pmut_ioctl_args) NOEXCEPT; + NODISCARD int64_t handle_vm_kvm_set_gsi_routing( + struct shim_vm_t *const pmut_vm, struct kvm_irq_routing *const pmut_ioctl_args) NOEXCEPT; #ifdef __cplusplus } diff --git a/shim/include/kvm_irq_routing.h b/shim/include/kvm_irq_routing.h index f108ecbc7..3cf038526 100644 --- a/shim/include/kvm_irq_routing.h +++ b/shim/include/kvm_irq_routing.h @@ -27,8 +27,20 @@ #ifndef KVM_IRQ_ROUTING_H #define KVM_IRQ_ROUTING_H +#define KVM_ENTRY ((uint32_t)0) +#define KVM_PAD ((uint32_t)8) + #include +#define KVM_IRQ_ROUTING_IRQCHIP 1 +#define KVM_IRQ_ROUTING_MSI 2 +#define KVM_IRQ_ROUTING_S390_ADAPTER 3 + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wold-style-cast" +#pragma clang diagnostic ignored "-Wzero-length-array" +#endif + #ifdef __cplusplus extern "C" { @@ -36,6 +48,94 @@ extern "C" #pragma pack(push, 1) + /** + * @struct kvm_irq_routing_irqchip + * + * + * @brief see /include/uapi/linux/kvm.h in Linux for more details. + */ + //NOLINTNEXTLINE + struct kvm_irq_routing_irqchip + { + /** @brief TODO */ + uint32_t irqchip; + /** @brief TODO */ + uint32_t pin; + }; + + /** + * @struct kvm_irq_routing_msi + * + * + * @brief see /include/uapi/linux/kvm.h in Linux for more details. + */ + //NOLINTNEXTLINE + struct kvm_irq_routing_msi + { + /** @brief TODO */ + uint32_t address_lo; + /** @brief TODO */ + uint32_t address_hi; + /** @brief TODO */ + uint32_t data; + /** @brief TODO */ + uint32_t pad; + }; + + /** + * @struct kvm_irq_routing_s390_adapter + * + * + * @brief see /include/uapi/linux/kvm.h in Linux for more details. + */ + //NOLINTNEXTLINE + struct kvm_irq_routing_s390_adapter + { + /** @brief TODO */ + uint64_t ind_addr; + /** @brief TODO */ + uint64_t summary_addr; + /** @brief TODO */ + uint64_t ind_offset; + /** @brief TODO */ + uint32_t summary_offset; + /** @brief TODO */ + uint32_t adapter_id; + }; + + /** + * @struct kvm_irq_routing_entry + * + * + * @brief see /include/uapi/linux/kvm.h in Linux for more details. + */ + struct kvm_irq_routing_entry //NOLINT + { + /** @brief TODO */ + uint32_t gsi; + /** @brief TODO */ + uint32_t type; + /** @brief TODO */ + uint32_t flags; + /** @brief TODO */ + uint32_t pad; + /** @brief TODO */ + //NOLINTNEXTLINE + union + { + /** @brief TODO */ + struct kvm_irq_routing_irqchip irqchip; + /** @brief TODO */ + struct kvm_irq_routing_msi msi; + /** @brief TODO */ + struct kvm_irq_routing_s390_adapter adapter; + /** @brief TODO */ + uint32_t pad[KVM_PAD]; + } /** @brief TODO */ u; + }; + /** TODO: REMOVE ABOVE STRUCTURE: The above structures are part of other branches as of now, + * they will be available to include here once respective branches are merged with master. */ + /** * @struct kvm_irq_routing * @@ -44,8 +144,12 @@ extern "C" */ struct kvm_irq_routing { - /** @brief replace me with contents from KVM API */ - int32_t dummy; + /** @brief TODO */ + uint32_t nr; + /** @brief TODO */ + uint32_t flags; + /** @brief TODO */ + struct kvm_irq_routing_entry entries[KVM_ENTRY]; }; #pragma pack(pop) diff --git a/shim/include/kvm_irq_routing.hpp b/shim/include/kvm_irq_routing.hpp new file mode 100644 index 000000000..608da01b9 --- /dev/null +++ b/shim/include/kvm_irq_routing.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 KVM_IRQ_ROUTING_HPP +#define KVM_IRQ_ROUTING_HPP + +#include + +#pragma pack(push, 1) + +namespace shim +{ + /// @brief defines the size of the padding field + /// @struct kvm_irq_routing + /// + /// + /// @brief see /include/uapi/linux/kvm.h in Linux for more details. + /// + + struct kvm_irq_routing final + { + + /** @brief TODO */ + bsl::uint32 nr; + /** @brief TODO */ + bsl::uint32 flags; + /** @brief TODO */ + // TODO: Below structure to be uncommented when all other branches of IOCTL are merged with master. + //struct kvm_irq_routing_entry entries[KVM_ENTRY]; + }; +} + +#pragma pack(pop) + +#endif \ No newline at end of file diff --git a/shim/integration/CMakeLists.txt b/shim/integration/CMakeLists.txt index 9bcad1da4..6c9f6fe46 100644 --- a/shim/integration/CMakeLists.txt +++ b/shim/integration/CMakeLists.txt @@ -55,3 +55,4 @@ microv_add_shim_integration(kvm_get_irqchip HEADERS) microv_add_shim_integration(kvm_set_irqchip HEADERS) microv_add_shim_integration(kvm_get_lapic HEADERS) microv_add_shim_integration(kvm_set_lapic HEADERS) +microv_add_shim_integration(kvm_irq_routing HEADERS) diff --git a/shim/integration/kvm_irq_routing.cpp b/shim/integration/kvm_irq_routing.cpp new file mode 100644 index 000000000..dccf73397 --- /dev/null +++ b/shim/integration/kvm_irq_routing.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 irqrouting{mut_vcpu.send(shim::KVM_SET_GSI_ROUTING)}; + integration::verify(irqrouting.is_pos()); + integration::verify(irqrouting >= 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 54e3edff8..b3e64b994 100644 --- a/shim/linux/include/platform_interface/shim_platform_interface.hpp +++ b/shim/linux/include/platform_interface/shim_platform_interface.hpp @@ -31,7 +31,11 @@ #include #include #include +<<<<<<< HEAD #include +======= +#include +>>>>>>> KVM_SET_GSI_ROUTING: Add scaffolding and initial integration tests #include #include #include @@ -215,8 +219,9 @@ namespace shim /// @brief defines KVM's KVM_GET_SUPPORTED_CPUID IOCTL constexpr bsl::safe_umx KVM_GET_SUPPORTED_CPUID{static_cast(_IOWR_LIST( SHIMIO.get(), 0x05, struct kvm_cpuid2, struct kvm_cpuid_entry2[CPUID2_MAX_ENTRIES.get()]))}; - // /// @brief defines KVM's KVM_SET_GSI_ROUTING IOCTL - // constexpr bsl::safe_umx KVM_SET_GSI_ROUTING{static_cast(_IOW(SHIMIO.get(), 0x6a, struct kvm_irq_routing))}; + /// @brief defines KVM's KVM_SET_GSI_ROUTING IOCTL + constexpr bsl::safe_umx KVM_SET_GSI_ROUTING{ + static_cast(_IOW(SHIMIO.get(), 0x6a, struct kvm_irq_routing))}; /// @brief defines KVM's KVM_GET_TSC_KHZ IOCTL constexpr bsl::safe_umx KVM_GET_TSC_KHZ{static_cast(_IO(SHIMIO.get(), 0xa3))}; /// @brief defines KVM's KVM_SET_TSC_KHZ IOCTL diff --git a/shim/linux/src/entry.c b/shim/linux/src/entry.c index d86ed7607..60282af8a 100644 --- a/shim/linux/src/entry.c +++ b/shim/linux/src/entry.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -709,10 +710,24 @@ dispatch_vm_kvm_set_device_attr(struct kvm_device_attr *const ioctl_args) } static long -dispatch_vm_kvm_set_gsi_routing(struct kvm_irq_routing *const ioctl_args) +dispatch_vm_kvm_set_gsi_routing( + struct shim_vm_t *const pmut_vm, + struct kvm_irq_routing *const pmut_ioctl_args) { - (void)ioctl_args; - return -EINVAL; + struct kvm_irq_routing 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_set_gsi_routing(pmut_vm, &mut_args)) { + bferror("handle_vm_kvm_set_gsi_routing failed"); + return -EINVAL; + } + + return 0; } static long @@ -936,7 +951,9 @@ dev_unlocked_ioctl_vm( case KVM_SET_GSI_ROUTING: { return dispatch_vm_kvm_set_gsi_routing( + (struct shim_vm_t *)pmut_mut_vm, (struct kvm_irq_routing *)ioctl_args); + ; } case KVM_SET_IDENTITY_MAP_ADDR: { diff --git a/shim/src/handle_vm_kvm_set_gsi_routing.c b/shim/src/handle_vm_kvm_set_gsi_routing.c index 636e839be..7bbab8177 100644 --- a/shim/src/handle_vm_kvm_set_gsi_routing.c +++ b/shim/src/handle_vm_kvm_set_gsi_routing.c @@ -24,20 +24,33 @@ * SOFTWARE. */ +#include +#include #include #include +#include +#include /** * * @brief Handles the execution of kvm_set_gsi_routing. * * + * @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_set_gsi_routing(struct kvm_irq_routing *const pmut_ioctl_args) NOEXCEPT +handle_vm_kvm_set_gsi_routing( + struct shim_vm_t *const pmut_vm, struct kvm_irq_routing *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_set_gsi_routing.cpp b/shim/tests/src/test_handle_vm_kvm_set_gsi_routing.cpp index 5cd016604..0997261b7 100644 --- a/shim/tests/src/test_handle_vm_kvm_set_gsi_routing.cpp +++ b/shim/tests/src/test_handle_vm_kvm_set_gsi_routing.cpp @@ -23,12 +23,12 @@ /// SOFTWARE. #include "../../include/handle_vm_kvm_set_gsi_routing.h" +#include "shim_vm_t.h" +#include #include -#include #include - namespace shim { /// @@ -43,12 +43,32 @@ namespace shim [[nodiscard]] constexpr auto tests() noexcept -> bsl::exit_code { + init_tests(); bsl::ut_scenario{"description"} = []() noexcept { bsl::ut_given{} = [&]() noexcept { kvm_irq_routing mut_args{}; + shim_vm_t mut_vm{}; bsl::ut_when{} = [&]() noexcept { bsl::ut_then{} = [&]() noexcept { - bsl::ut_check(SHIM_SUCCESS == handle_vm_kvm_set_gsi_routing(&mut_args)); + bsl::ut_check( + SHIM_SUCCESS == handle_vm_kvm_set_gsi_routing(&mut_vm, &mut_args)); + }; + }; + }; + }; + + bsl::ut_scenario{"hypervisor not detected"} = []() noexcept { + bsl::ut_given{} = [&]() noexcept { + kvm_irq_routing 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_set_gsi_routing(&mut_vm, &mut_args)); + }; + bsl::ut_cleanup{} = [&]() noexcept { + g_mut_hypervisor_detected = true; }; }; };