ANDROID: KVM: arm64: Allow 16 host_smc handlers

Allow pKVM modules to register up to 16 host_smc handlers. The SMC will
be considered has handled on the first one returning True. Unhandled SMC
will be forwarded.

Bug: 357781595
Bug: 382397533
Change-Id: I58717927d7b47b8af5532ec2bfe57e022186e1d3
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
This commit is contained in:
Vincent Donnefort
2025-01-14 19:14:22 +00:00
parent 0a901ecd7f
commit a3040de297
4 changed files with 29 additions and 16 deletions
+5 -2
View File
@@ -93,8 +93,11 @@ enum pkvm_psci_notification {
* @host_stage2_get_leaf: Query the host's stage2 page-table entry for
* the page @phys.
* @register_host_smc_handler: @cb is called whenever the host issues an SMC
* pKVM couldn't handle. If @cb returns false, the
* SMC will be forwarded to EL3.
* pKVM couldn't handle.
* Up-to 16 handlers can be registered. The handler
* order depends on the registration order. If no
* handler return True, the SMC is forwarded to
* EL3.
* @register_default_trap_handler:
* @cb is called whenever EL2 traps EL1 and pKVM
* has not handled it. If @cb returns false, the
@@ -18,6 +18,7 @@ int __pkvm_register_hcall(unsigned long hfn_hyp_va);
int handle_host_dynamic_hcall(struct user_pt_regs *regs, int id);
void __pkvm_close_module_registration(void);
bool module_handle_host_perm_fault(struct user_pt_regs *regs, u64 esr, u64 addr);
bool module_handle_host_smc(struct user_pt_regs *regs);
#else
static inline int __pkvm_init_module(void *module_init) { return -EOPNOTSUPP; }
static inline int
@@ -29,4 +30,5 @@ handle_host_dynamic_hcall(struct kvm_cpu_context *host_ctxt, int id)
}
static inline void __pkvm_close_module_registration(void) { }
bool module_handle_host_perm_fault(struct user_pt_regs *regs, u64 esr, u64 addr) { return false; }
bool module_handle_host_smc(struct user_pt_regs *regs) { return false; }
#endif
+2 -13
View File
@@ -63,21 +63,10 @@ static inline void hyp_reqs_smccc_encode(unsigned long ret, struct kvm_cpu_conte
void __kvm_hyp_host_forward_smc(struct kvm_cpu_context *host_ctxt);
static bool (*default_host_smc_handler)(struct user_pt_regs *regs);
static bool (*default_trap_handler)(struct user_pt_regs *regs);
static bool (*unmask_serror)(void);
static void (*mask_serror)(void);
int __pkvm_register_host_smc_handler(bool (*cb)(struct user_pt_regs *))
{
/*
* Paired with smp_load_acquire(&default_host_smc_handler) in
* handle_host_smc(). Ensure memory stores happening during a pKVM module
* init are observed before executing the callback.
*/
return cmpxchg_release(&default_host_smc_handler, NULL, cb) ? -EBUSY : 0;
}
int __pkvm_register_default_trap_handler(bool (*cb)(struct user_pt_regs *))
{
return cmpxchg(&default_trap_handler, NULL, cb) ? -EBUSY : 0;
@@ -1856,8 +1845,8 @@ static void handle_host_smc(struct kvm_cpu_context *host_ctxt)
handled = kvm_host_ffa_handler(host_ctxt, func_id);
if (!handled)
handled = kvm_host_scmi_handler(host_ctxt);
if (!handled && smp_load_acquire(&default_host_smc_handler))
handled = default_host_smc_handler(&host_ctxt->regs);
if (!handled)
handled = module_handle_host_smc(&host_ctxt->regs);
if (!handled) {
__hyp_exit();
__kvm_hyp_host_forward_smc(host_ctxt);
+20 -1
View File
@@ -132,6 +132,7 @@ static int __hyp_smp_processor_id(void)
enum mod_handler_type {
HOST_FAULT_HANDLER = 0,
HOST_SMC_HANDLER,
NUM_MOD_HANDLER_TYPES,
};
@@ -173,6 +174,11 @@ __register_host_perm_fault_handler(int (*cb)(struct user_pt_regs *regs, u64 esr,
return mod_handler_register(HOST_FAULT_HANDLER, cb);
}
static int __register_host_smc_handler(bool (*cb)(struct user_pt_regs *))
{
return mod_handler_register(HOST_SMC_HANDLER, cb);
}
bool module_handle_host_perm_fault(struct user_pt_regs *regs, u64 esr, u64 addr)
{
int (*cb)(struct user_pt_regs *regs, u64 esr, u64 addr);
@@ -186,6 +192,19 @@ bool module_handle_host_perm_fault(struct user_pt_regs *regs, u64 esr, u64 addr)
return false;
}
bool module_handle_host_smc(struct user_pt_regs *regs)
{
bool (*cb)(struct user_pt_regs *regs);
int i;
for_each_mod_handler(HOST_SMC_HANDLER, cb, i) {
if (cb(regs))
return true;
}
return false;
}
const struct pkvm_module_ops module_ops = {
.create_private_mapping = __pkvm_create_private_mapping,
.alloc_module_va = __pkvm_alloc_module_va,
@@ -206,7 +225,7 @@ const struct pkvm_module_ops module_ops = {
.host_stage2_get_leaf = host_stage2_get_leaf,
.host_stage2_enable_lazy_pte = host_stage2_enable_lazy_pte,
.host_stage2_disable_lazy_pte = host_stage2_disable_lazy_pte,
.register_host_smc_handler = __pkvm_register_host_smc_handler,
.register_host_smc_handler = __register_host_smc_handler,
.register_default_trap_handler = __pkvm_register_default_trap_handler,
.register_illegal_abt_notifier = __pkvm_register_illegal_abt_notifier,
.register_psci_notifier = __pkvm_register_psci_notifier,