Skip to content

Commit

Permalink
Add support for custom SMC SiP handler
Browse files Browse the repository at this point in the history
Signed-off-by: Ivan Velickovic <[email protected]>
  • Loading branch information
Ivan-Velickovic committed Sep 3, 2024
1 parent fae43de commit 5315476
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 3 deletions.
19 changes: 18 additions & 1 deletion include/libvmm/arch/aarch64/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,24 @@
#include <microkit.h>

/* SMC vCPU fault handler */
bool handle_smc(size_t vcpu_id, uint32_t hsr);
bool smc_handle(size_t vcpu_id, uint32_t hsr);

/*
* A custom handler for SMC SiP calls can be registered.
* By default SiP calls are not handled.
* Note only one handler can be registered at a given time.
* smc_register_sip_handler returns false if a handler already exists.
*/
typedef bool (*smc_sip_handler_t)(size_t vcpu_id, seL4_UserContext *regs, size_t fn_number);
bool smc_register_sip_handler(smc_sip_handler_t handler);

#if defined(CONFIG_ALLOW_SMC_CALLS)
/*
* Handle SMC SiP calls simply by forwarding the arguments to seL4 to perform
* and placing the response registers into the guest's TCB registers.
*/
bool smc_sip_forward(size_t vcpu, seL4_UserContext *regs, size_t fn_number);
#endif

/* Helper functions */
void smc_set_return_value(seL4_UserContext *u, uint64_t val);
Expand Down
2 changes: 1 addition & 1 deletion src/arch/aarch64/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ bool fault_handle_vcpu_exception(size_t vcpu_id)
uint64_t hsr_ec_class = HSR_EXCEPTION_CLASS(hsr);
switch (hsr_ec_class) {
case HSR_SMC_64_EXCEPTION:
return handle_smc(vcpu_id, hsr);
return smc_handle(vcpu_id, hsr);
case HSR_WFx_EXCEPTION:
// If we get a WFI exception, we just do nothing in the VMM.
return true;
Expand Down
79 changes: 78 additions & 1 deletion src/arch/aarch64/smc.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include <libvmm/util/util.h>
#include <libvmm/arch/aarch64/smc.h>
#include <libvmm/arch/aarch64/psci.h>
#include <libvmm/arch/aarch64/fault.h>

// #define DEBUG_SMC

// Values in this file are taken from:
// SMC CALLING CONVENTION
Expand Down Expand Up @@ -90,8 +93,77 @@ static void smc_set_arg(seL4_UserContext *u, size_t arg, size_t val)
}
}

static void dump_smc_request(seL4_ARM_SMCContext *request) {
LOG_VMM("SMC forward dump request:\n");
LOG_VMM(" x0: 0x%lx\n", request->x0);
LOG_VMM(" x1: 0x%lx\n", request->x1);
LOG_VMM(" x2: 0x%lx\n", request->x2);
LOG_VMM(" x3: 0x%lx\n", request->x3);
LOG_VMM(" x4: 0x%lx\n", request->x4);
LOG_VMM(" x5: 0x%lx\n", request->x5);
LOG_VMM(" x6: 0x%lx\n", request->x6);
LOG_VMM(" x7: 0x%lx\n", request->x7);
}

static void dump_smc_response(seL4_ARM_SMCContext *response) {
LOG_VMM("SMC forward dump response:\n");
LOG_VMM(" x0: 0x%lx\n", response->x0);
LOG_VMM(" x1: 0x%lx\n", response->x1);
LOG_VMM(" x2: 0x%lx\n", response->x2);
LOG_VMM(" x3: 0x%lx\n", response->x3);
LOG_VMM(" x4: 0x%lx\n", response->x4);
LOG_VMM(" x5: 0x%lx\n", response->x5);
LOG_VMM(" x6: 0x%lx\n", response->x6);
LOG_VMM(" x7: 0x%lx\n", response->x7);
}

#if defined(CONFIG_ALLOW_SMC_CALLS)
bool smc_sip_forward(size_t vcpu_id, seL4_UserContext *regs, size_t fn_number)
{
seL4_ARM_SMCContext request;
seL4_ARM_SMCContext response;

request.x0 = regs->x0; request.x1 = regs->x1;
request.x2 = regs->x2; request.x3 = regs->x3;
request.x4 = regs->x4; request.x5 = regs->x5;
request.x6 = regs->x6; request.x7 = regs->x7;

#if defined(DEBUG_SMC)
dump_smc_request(&request);
#endif

microkit_arm_smc_call(&request, &response);

#if defined(DEBUG_SMC)
dump_smc_response(&response);
#endif

regs->x0 = response.x0; regs->x1 = response.x1;
regs->x2 = response.x2; regs->x3 = response.x3;
regs->x4 = response.x4; regs->x5 = response.x5;
regs->x6 = response.x6; regs->x7 = response.x7;

bool success = fault_advance_vcpu(vcpu_id, regs);
assert(success);

return success;
}
#endif

static smc_sip_handler_t smc_sip_handler = NULL;

bool smc_register_sip_handler(smc_sip_handler_t handler) {
if (smc_sip_handler) {
LOG_VMM_ERR("SMC SiP handler already registered\n");
return false;
}
smc_sip_handler = handler;

return true;
}

// @ivanv: print out which SMC call as a string we can't handle.
bool handle_smc(size_t vcpu_id, uint32_t hsr)
bool smc_handle(size_t vcpu_id, uint32_t hsr)
{
// @ivanv: An optimisation to be made is to store the TCB registers so we don't
// end up reading them multiple times
Expand All @@ -109,6 +181,11 @@ bool handle_smc(size_t vcpu_id, uint32_t hsr)
}
LOG_VMM_ERR("Unhandled SMC: standard service call %lu\n", fn_number);
break;
case SMC_CALL_SIP_SERVICE:
if (smc_sip_handler) {
return smc_sip_handler(vcpu_id, &regs, fn_number);
}
/* If we don't have a SiP handler registered, drop to the default case. */
default:
LOG_VMM_ERR("Unhandled SMC: unknown value service: 0x%lx, function number: 0x%lx\n", service, fn_number);
break;
Expand Down

0 comments on commit 5315476

Please sign in to comment.