mirror of
https://github.com/Bareflank/hypervisor
synced 2026-08-17 06:23:04 -04:00
272 lines
11 KiB
C++
272 lines
11 KiB
C++
/// @copyright
|
|
/// Copyright (C) 2020 Assured Information Security, Inc.
|
|
///
|
|
/// @copyright
|
|
/// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
/// of this software and associated documentation files (the "Software"), to deal
|
|
/// in the Software without restriction, including without limitation the rights
|
|
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
/// copies of the Software, and to permit persons to whom the Software is
|
|
/// furnished to do so, subject to the following conditions:
|
|
///
|
|
/// @copyright
|
|
/// The above copyright notice and this permission notice shall be included in
|
|
/// all copies or substantial portions of the Software.
|
|
///
|
|
/// @copyright
|
|
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
/// LIABILITY, WHETHER IN AN ACTION 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 <bf_constants.hpp>
|
|
#include <bf_syscall_t.hpp>
|
|
#include <gs_t.hpp>
|
|
#include <intrinsic_t.hpp>
|
|
#include <tls_t.hpp>
|
|
|
|
#include <bsl/discard.hpp>
|
|
#include <bsl/errc_type.hpp>
|
|
#include <bsl/safe_integral.hpp>
|
|
#include <bsl/unlikely_assert.hpp>
|
|
|
|
namespace example
|
|
{
|
|
/// @class example::vp_t
|
|
///
|
|
/// <!-- description -->
|
|
/// @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:
|
|
/// <!-- description -->
|
|
/// @brief Initializes this vp_t
|
|
///
|
|
/// <!-- inputs/outputs -->
|
|
/// @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 const &gs,
|
|
tls_t const &tls,
|
|
syscall::bf_syscall_t const &sys,
|
|
intrinsic_t const &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;
|
|
}
|
|
|
|
/// <!-- description -->
|
|
/// @brief Release the vp_t.
|
|
///
|
|
/// <!-- inputs/outputs -->
|
|
/// @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 const &gs,
|
|
tls_t const &tls,
|
|
syscall::bf_syscall_t const &sys,
|
|
intrinsic_t const &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();
|
|
}
|
|
|
|
/// <!-- description -->
|
|
/// @brief Allocates a vp_t and returns it's ID
|
|
///
|
|
/// <!-- inputs/outputs -->
|
|
/// @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 const &gs,
|
|
tls_t const &tls,
|
|
syscall::bf_syscall_t const &sys,
|
|
intrinsic_t const &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
|