rename kvm references to pvm

The term KVM is missleading because we are not using linux kernel
virtualization. PVM stands for "Pound Virtual Machine" which is more
accurate.

Signed-off-by: Ronald Caesar <github43132@proton.me>
This commit is contained in:
Ronald Caesar 2025-09-30 18:13:48 -04:00
parent 70a1abc62f
commit 9d7b05d6ae
No known key found for this signature in database
GPG key ID: 04307C401999C596
14 changed files with 100 additions and 119 deletions

View file

@ -99,7 +99,7 @@ add_subdirectory(3rd_Party)
add_subdirectory(src/common)
add_subdirectory(src/frontend)
add_subdirectory(src/host)
add_subdirectory(src/kvm)
add_subdirectory(src/pvm)
add_subdirectory(src/targets/switch1/hardware)
#--------------------------------
@ -113,7 +113,7 @@ endif()
include(TestBigEndian)
TEST_BIG_ENDIAN(WORDS_BIGENDIAN)
list(APPEND POUND_PROJECT_TARGETS common frontend host kvm)
list(APPEND POUND_PROJECT_TARGETS common frontend host pvm)
foreach(TARGET ${POUND_PROJECT_TARGETS})
# Apply Endianness definitions to all our targets.
if(WORDS_BIGENDIAN)
@ -153,7 +153,7 @@ target_link_libraries(Pound PRIVATE
common
frontend
host
kvm
pvm
OpenGL::GL
SDL3::SDL3

View file

@ -1,7 +1,7 @@
#include "panels.h"
#include <imgui.h>
#include <math.h>
#include "kvm/kvm.h"
#include "pvm/pvm.h"
#include "common/passert.h"
int8_t gui::panel::render_performance_panel(gui::panel::performance_panel_t* panel, performance_data_t* data,
@ -94,7 +94,7 @@ int8_t gui::panel::render_cpu_panel(bool* show_cpu_result_popup)
if (::ImGui::Button("Run CPU Test", ImVec2(120, 0)))
{
pound::kvm::cpuTest();
pound::pvm::cpuTest();
*show_cpu_result_popup = true;
}
if (true == *show_cpu_result_popup)

View file

@ -1,15 +0,0 @@
add_library(kvm STATIC)
target_sources(kvm PRIVATE
mmu.cpp
mmio.cpp
kvm.cpp
guest.cpp
)
target_link_libraries(kvm PRIVATE common host)
target_include_directories(kvm PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/..
)

15
src/pvm/CMakeLists.txt Normal file
View file

@ -0,0 +1,15 @@
add_library(pvm STATIC)
target_sources(pvm PRIVATE
mmu.cpp
mmio.cpp
pvm.cpp
guest.cpp
)
target_link_libraries(pvm PRIVATE common host)
target_include_directories(pvm PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/..
)

View file

@ -1,7 +1,7 @@
#include "guest.h"
#include "common/passert.h"
namespace pound::kvm::memory
namespace pound::pvm::memory
{
guest_memory_t* guest_memory_create(pound::host::memory::arena_t* arena)
{
@ -32,4 +32,4 @@ guest_memory_t* guest_memory_create(pound::host::memory::arena_t* arena)
#pragma GCC diagnostic pop
return memory;
}
} // namespace pound::kvm::memory
} // namespace pound::pvm::memory

View file

@ -1,5 +1,5 @@
#ifndef POUND_KVM_GUEST_H
#define POUND_KVM_GUEST_H
#ifndef POUND_pvm_GUEST_H
#define POUND_pvm_GUEST_H
#include <cassert>
#include <stdint.h>
@ -9,7 +9,7 @@
#include "host/memory/arena.h"
namespace pound::kvm::memory
namespace pound::pvm::memory
{
/*
@ -35,7 +35,7 @@ namespace pound::kvm::memory
* backing memory arena is valid. Typically, this means it is created once
- * during virtual machine initialization and lives for the entire duration of
* the emulation session. Its lifetime is tied to the lifetime of the parent
* KVM instance.
* pvm instance.
*
* --- Invariants ---
* Both fields of this struct are declared `const`. This establishes the
@ -455,5 +455,5 @@ inline guest_mem_access_result_t guest_mem_writeq(guest_memory_t* memory, uint64
memcpy(hva, &val, sizeof(uint64_t));
return GUEST_MEM_ACCESS_OK;
}
} // namespace pound::kvm::memory
#endif // POUND_KVM_GUEST_H
} // namespace pound::pvm::memory
#endif // POUND_pvm_GUEST_H

View file

@ -2,7 +2,7 @@
#include "common/passert.h"
#include <algorithm>
namespace pound::kvm::memory
namespace pound::pvm::memory
{
/*
* This function implements a strict weak ordering comparison on two
@ -67,10 +67,10 @@ bool mmio_compare_addresses(const mmio_range_t& a, const mmio_range_t& b)
return a.gpa_base < b.gpa_base;
}
int8_t mmio_db_dispatch_write(mmio_db_t* db, kvm_t* kvm, uint64_t gpa, uint8_t* data, size_t len)
int8_t mmio_db_dispatch_write(mmio_db_t* db, pvm_t* pvm, uint64_t gpa, uint8_t* data, size_t len)
{
PVM_ASSERT(nullptr != db);
PVM_ASSERT(nullptr != kvm);
PVM_ASSERT(nullptr != pvm);
PVM_ASSERT(nullptr != data);
PVM_ASSERT(len > 0);
@ -95,7 +95,7 @@ int8_t mmio_db_dispatch_write(mmio_db_t* db, kvm_t* kvm, uint64_t gpa, uint8_t*
return EACCESS_DENIED;
}
db->handlers[(size_t)i].write(kvm, gpa, data, len);
db->handlers[(size_t)i].write(pvm, gpa, data, len);
return MMIO_SUCCESS;
}
@ -103,10 +103,10 @@ int8_t mmio_db_dispatch_write(mmio_db_t* db, kvm_t* kvm, uint64_t gpa, uint8_t*
return ENOT_HANDLED;
}
int8_t mmio_db_dispatch_read(mmio_db_t* db, kvm_t* kvm, uint64_t gpa, uint8_t* data, size_t len)
int8_t mmio_db_dispatch_read(mmio_db_t* db, pvm_t* pvm, uint64_t gpa, uint8_t* data, size_t len)
{
PVM_ASSERT(nullptr != db);
PVM_ASSERT(nullptr != kvm);
PVM_ASSERT(nullptr != pvm);
PVM_ASSERT(nullptr != data);
PVM_ASSERT(len > 0);
@ -131,11 +131,11 @@ int8_t mmio_db_dispatch_read(mmio_db_t* db, kvm_t* kvm, uint64_t gpa, uint8_t* d
return EACCESS_DENIED;
}
db->handlers[(size_t)i].read(kvm, gpa, data, len);
db->handlers[(size_t)i].read(pvm, gpa, data, len);
return MMIO_SUCCESS;
}
/* The gpa is not in any mmio region. */
return ENOT_HANDLED;
}
} // namespace pound::kvm::memory
} // namespace pound::pvm::memory

View file

@ -3,9 +3,9 @@
#include <cstdint>
#include <vector>
#include "host/memory/arena_stl.h"
#include "kvm.h"
#include "pvm.h"
namespace pound::kvm::memory
namespace pound::pvm::memory
{
/*
* MMIO_REGIONS - The maximum number of distinct MMIO regions supported.
@ -27,7 +27,7 @@ namespace pound::kvm::memory
/*
* typedef mmio - Function pointer type for an MMIO access handler.
* @kvm: A pointer to the KVM instance.
* @pvm: A pointer to the pvm instance.
* @gpa: The guest physical address of the access.
* @data: A pointer to the data buffer. For reads, this buffer
* should be filled by the handler. For writes, this buffer
@ -41,7 +41,7 @@ namespace pound::kvm::memory
*
* Returns: MMIO_SUCCESS on success, negative errno code on failure.
*/
typedef int8_t (*mmio)(kvm_t* kvm, uint64_t gpa, uint8_t* data, size_t len);
typedef int8_t (*mmio)(pvm_t* pvm, uint64_t gpa, uint8_t* data, size_t len);
/*
* mmio_handler_t - A pair of handlers for an MMIO region.
@ -120,7 +120,7 @@ int8_t mmio_db_register(mmio_db_t* db, const mmio_range_t range, const mmio_hand
/*
* mmio_db_dispatch_write - Dispatches a guest physical write to a registered MMIO handler.
* @db: A pointer to the MMIO database to be queried.
* @kvm: A pointer to the KVM instance.
* @pvm: A pointer to the pvm instance.
* @gpa: The guest physical address of the memory write.
* @data: A pointer to the buffer containing the data written by the guest.
* @len: The size of the write access in bytes.
@ -170,12 +170,12 @@ int8_t mmio_db_register(mmio_db_t* db, const mmio_range_t range, const mmio_hand
* ENOT_HANDLED if the @gpa does not map to any MMIO region.
* EACCESS_DENIED if the MMIO region has no write function pointer.
*/
int8_t mmio_db_dispatch_write(mmio_db_t* db, kvm_t* kvm, uint64_t gpa, uint8_t* data, size_t len);
int8_t mmio_db_dispatch_write(mmio_db_t* db, pvm_t* pvm, uint64_t gpa, uint8_t* data, size_t len);
/*
* mmio_db_dispatch_read - Dispatches a guest physical read to a registered MMIO handler.
* @db: A pointer to the MMIO database to be queried.
* @kvm: A pointer to the KVM instance.
* @pvm: A pointer to the pvm instance.
* @gpa: The guest physical address of the memory write.
* @data: A pointer to the buffer containing the data written by the guest.
* @len: The size of the write access in bytes.
@ -187,5 +187,5 @@ int8_t mmio_db_dispatch_write(mmio_db_t* db, kvm_t* kvm, uint64_t gpa, uint8_t*
* ENOT_HANDLED if the @gpa does not map to any MMIO region.
* EACCESS_DENIED if the MMIO region has no write function pointer.
*/
int8_t mmio_db_dispatch_read(mmio_db_t* db, kvm_t* kvm, uint64_t gpa, uint8_t* data, size_t len);
} // namespace pound::kvm::memory
int8_t mmio_db_dispatch_read(mmio_db_t* db, pvm_t* pvm, uint64_t gpa, uint8_t* data, size_t len);
} // namespace pound::pvm::memory

View file

@ -1,9 +1,9 @@
#include "mmu.h"
#include "kvm.h"
#include "pvm.h"
#include "common/passert.h"
#include <limits.h>
namespace pound::kvm::memory
namespace pound::pvm::memory
{
#define GRANULE_4KB (1ULL << 12)
#define GRANULE_16KB (1ULL << 14)
@ -43,7 +43,7 @@ static inline uint8_t msvc_ctzll(unsigned long long val)
/* Define the size of a page table entry (descriptor) */
#define PAGE_TABLE_ENTRY_SHIFT 3 /* log2(8 bytes) */
int mmu_gva_to_gpa(pound::kvm::kvm_vcpu_t* vcpu, guest_memory_t* memory, uint64_t gva, uint64_t* out_gpa)
int mmu_gva_to_gpa(pound::pvm::pvm_vcpu_t* vcpu, guest_memory_t* memory, uint64_t gva, uint64_t* out_gpa)
{
const uint8_t SCTLR_EL1_M_BIT = (1 << 0);
if (0 == (vcpu->sctlr_el1 & SCTLR_EL1_M_BIT))
@ -394,4 +394,4 @@ int mmu_gva_to_gpa(pound::kvm::kvm_vcpu_t* vcpu, guest_memory_t* memory, uint64_
}
return -1;
}
} // namespace pound::kvm::memory
} // namespace pound::pvm::memory

View file

@ -1,9 +1,9 @@
#pragma once
#include "guest.h"
#include "kvm.h"
#include "pvm.h"
namespace pound::kvm::memory
namespace pound::pvm::memory
{
/*
* mmu_gva_to_gpa() - Translate a Guest Virtual Address to a Guest Physical Address.
@ -36,5 +36,5 @@ namespace pound::kvm::memory
* Return: 0 on successful translation. A negative error code on a translation
* fault (e.g., for a page fault, permission error, or alignment fault).
*/
int mmu_gva_to_gpa(pound::kvm::kvm_vcpu_t* vcpu, guest_memory_t* memory, uint64_t gva, uint64_t* out_gpa);
} // namespace pound::kvm::memory
int mmu_gva_to_gpa(pound::pvm::pvm_vcpu_t* vcpu, guest_memory_t* memory, uint64_t gva, uint64_t* out_gpa);
} // namespace pound::pvm::memory

View file

@ -1,27 +1,27 @@
#include "kvm.h"
#include "pvm.h"
#include "guest.h"
#include "common/passert.h"
#include "host/memory/arena.h"
#define LOG_MODULE "kvm"
#define LOG_MODULE "pvm"
#include "common/logging.h"
namespace pound::kvm
namespace pound::pvm
{
uint8_t kvm_probe(kvm_t* kvm, enum target_type type)
uint8_t pvm_probe(pvm_t* pvm, enum target_type type)
{
if (type != KVM_TARGET_SWITCH1)
if (type != pvm_TARGET_SWITCH1)
{
PVM_ASSERT_MSG(false, "Only Switch 1 is supported");
}
kvm->ops = s1_ops;
pvm->ops = s1_ops;
/* Go to targets/switch1/hardware/probe.cpp */
(void)kvm->ops.init(kvm);
(void)pvm->ops.init(pvm);
return 0;
}
void take_synchronous_exception(kvm_vcpu_t* vcpu, uint8_t exception_class, uint32_t iss, uint64_t faulting_address)
void take_synchronous_exception(pvm_vcpu_t* vcpu, uint8_t exception_class, uint32_t iss, uint64_t faulting_address)
{
PVM_ASSERT(nullptr != vcpu);
/* An EC holds 6 bits.*/
@ -80,4 +80,4 @@ void cpuTest()
//(void)test_guest_ram_access(guest_ram);
#endif
}
} // namespace pound::kvm
} // namespace pound::pvm

View file

@ -7,7 +7,7 @@
#include <cstdlib>
#include <cstring>
namespace pound::kvm
namespace pound::pvm
{
/* AArch64 R0-R31 */
#define GP_REGISTERS 32
@ -28,7 +28,7 @@ namespace pound::kvm
#define PSTATE_EL1H 0b0101
/*
* kvm_vcpu_t - Holds the architectural and selected system-register state for an emulated vCPU.
* pvm_vcpu_t - Holds the architectural and selected system-register state for an emulated vCPU.
* @r: General-purpose registers X0X31 (X31 as SP/ZR as appropriate).
* @pc: Program Counter.
* @cntfreq_el0: Counter Frequency.
@ -130,23 +130,21 @@ typedef struct alignas(CACHE_LINE_SIZE)
uint32_t dczid_el0;
uint32_t pmcr_el0;
uint32_t pstate;
} kvm_vcpu_t;
} pvm_vcpu_t;
/* This is here to break the circular dependency between kvm_t and kvm_ops_t. */
typedef struct kvm_s kvm_t;
/* This is here to break the circular dependency between pvm_t and pvm_ops_t. */
typedef struct pvm_s pvm_t;
/*
* struct kvm_ops_t - A table of machine-specific operations.
* struct pvm_ops_t - A table of machine-specific operations.
* @init: Function pointer to initialize the target machine's state.
* Called once by kvm_probe(). It is responsible for setting up
* Called once by pvm_probe(). It is responsible for setting up
* the guest memory map, loading firmware, and registering all
* MMIO device handlers.
* @mmio_read: Function pointer to handle a guest read from an MMIO region.
* @mmio_write: Function pointer to handle a guest write to an MMIO region.
* @destroy: Function pointer to clean up and deallocate all resources
* associated with the machine instance. Called on VM shutdown.
*
* This structure acts as a "virtual table" in C, allowing the generic KVM
* This structure acts as a "virtual table" in C, allowing the generic pvm
* core to call target-specific code (e.g., for a Switch 1 or Switch 2)
* without needing to know the implementation details. Each supported target
* machine must provide a globally visible instance of this struct.
@ -154,33 +152,27 @@ typedef struct kvm_s kvm_t;
typedef struct
{
/* Initialize the machine state */
int8_t (*init)(kvm_t* kvm);
/* Handles an MMIO read from the guest. */
int8_t (*mmio_read)(kvm_t* kvm, uint64_t gpa, uint8_t* data, size_t len);
/* Handles an MMIO write from the guest. */
int8_t (*mmio_write)(kvm_t* kvm, uint64_t gpa, uint8_t* data, size_t len);
int8_t (*init)(pvm_t* pvm);
/* Clean up on shutdown */
void (*destroy)(kvm_t* kvm);
} kvm_ops_t;
void (*destroy)(pvm_t* pvm);
} pvm_ops_t;
/*
* kvm_s - The main KVM instance structure.
* pvm_s - The main pvm instance structure.
* @vcpu: The state of the emulated virtual CPU core. Contains all guest-
* visible registers.
* @memory: A structure representing the guest's physical RAM.
* @ops: A table of function pointers to the machine-specific implementation
* for this KVM instance. This should only be set by kvm_probe().
* for this pvm instance. This should only be set by pvm_probe().
*
* This structure represents a single virtual machine instance.
*/
struct kvm_s
struct pvm_s
{
pound::kvm::kvm_vcpu_t vcpu;
pound::kvm::memory::guest_memory_t memory;
kvm_ops_t ops;
pound::pvm::pvm_vcpu_t vcpu;
pound::pvm::memory::guest_memory_t memory;
pvm_ops_t ops;
};
/**
@ -191,31 +183,31 @@ struct kvm_s
* (targets/switch1/hardware/probe.cpp) and provides the iplementations
* for initializing and running the emulated Switch 1 hardware.
*/
extern const kvm_ops_t s1_ops;
extern const pvm_ops_t s1_ops;
enum target_type
{
KVM_TARGET_SWITCH1 = 0,
KVM_TARGET_SWITCH2 = 1,
pvm_TARGET_SWITCH1 = 0,
pvm_TARGET_SWITCH2 = 1,
};
/*
* kvm_probe - Probes for and initializes a target machine configuration.
* @kvm: A pointer to the KVM instance to be initialized. This function will
* pvm_probe - Probes for and initializes a target machine configuration.
* @pvm: A pointer to the pvm instance to be initialized. This function will
* populate the fields of this struct.
* @type: The type of target machine to initialize.
*
* This function is the primary factory for creating a virtual machine. It
* looks up the requested machine @type, attaches the corresponding operations
* table (e.g., s1_ops) to the @kvm instance, and calls the machine-specific
* table (e.g., s1_ops) to the @pvm instance, and calls the machine-specific
* init() function.
*
* On successful return, the @kvm struct will be fully configured and ready
* On successful return, the @pvm struct will be fully configured and ready
* for execution.
*
* Return: 0 on success, or a negative errno code on failure.
*/
uint8_t kvm_probe(kvm_t* kvm, enum target_type type);
uint8_t pvm_probe(pvm_t* pvm, enum target_type type);
/*
* take_synchronous_exception() - Emulates the hardware process of taking a synchronous exception to EL1.
@ -232,7 +224,7 @@ uint8_t kvm_probe(kvm_t* kvm, enum target_type type);
* program counter by branching to the appropriate offset in the EL1 vector table.
*
*/
void take_synchronous_exception(kvm_vcpu_t* vcpu, uint8_t exception_class, uint32_t iss, uint64_t faulting_address);
void take_synchronous_exception(pvm_vcpu_t* vcpu, uint8_t exception_class, uint32_t iss, uint64_t faulting_address);
void cpuTest();
} // namespace pound::kvm
} // namespace pound::pvm

View file

@ -1,41 +1,30 @@
#include "kvm/kvm.h"
#include "pvm/pvm.h"
#define LOG_MODULE "switch1"
#include "common/logging.h"
namespace pound::kvm
namespace pound::pvm
{
static int8_t s1_init(kvm_t* kvm);
static int8_t s1_mmio_read(kvm_t* kvm, uint64_t gpa, uint8_t* data, size_t len);
static int8_t s1_mmio_write(kvm_t* kvm, uint64_t gpa, uint8_t* data, size_t len);
static void s1_destroy(kvm_t* kvm);
static int8_t s1_init(pvm_t* pvm);
static int8_t s1_mmio_read(pvm_t* pvm, uint64_t gpa, uint8_t* data, size_t len);
static int8_t s1_mmio_write(pvm_t* pvm, uint64_t gpa, uint8_t* data, size_t len);
static void s1_destroy(pvm_t* pvm);
const kvm_ops_t s1_ops = {
const pvm_ops_t s1_ops = {
.init = s1_init,
.mmio_read = s1_mmio_read,
.mmio_write = s1_mmio_write,
.destroy = s1_destroy,
};
static int8_t s1_init(kvm_t* kvm)
static int8_t s1_init(pvm_t* pvm)
{
LOG_INFO("Initializing Switch 1 virtual machine");
/* BOOTSTRAPPING CODE GOES HERE */
return 0;
}
static int8_t s1_mmio_read(kvm_t* kvm, uint64_t gpa, uint8_t* data, size_t len)
static void s1_destroy(pvm_t* pvm)
{
/* TODO(GloriousTacoo:kvm) */
return 0;
}
static int8_t s1_mmio_write(kvm_t* kvm, uint64_t gpa, uint8_t* data, size_t len)
{
/* TODO(GloriousTacoo:kvm) */
return 0;
}
static void s1_destroy(kvm_t* kvm)
{
/* TODO(GloriousTacoo:kvm) */
/* TODO(GloriousTacoo:pvm) */
}
}