From 2fc3bdec40f07036fbce52ac28d64ee3b210915f Mon Sep 17 00:00:00 2001 From: Qi Yadong Date: Fri, 25 May 2018 13:08:04 +0800 Subject: [PATCH] HV: trusty: new hypercall to save/restore context of secure world New field in VM's structure: sworld_snapshot: save cpu_context of secure world. New hypercall: HC_SAVE_RESTORE_SWORLD_CTX In UOS S3 suspend path: trusty kernel driver will call this hypercall to require Hypervisor save context of secure world. In UOS S3 resume path: virtual firmware will call this hypercall to require Hypervisor restore context of secure world. New bit in secure_world_control.flag: ctx_saved: indicate whether cpu_context of secure world is saved. Signed-off-by: Qi Yadong Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/vmcall.c | 7 +++++- hypervisor/arch/x86/trusty.c | 24 ++++++++++++++++++ hypervisor/common/trusty_hypercall.c | 31 ++++++++++++++++++++++++ hypervisor/include/arch/x86/guest/vm.h | 7 ++++++ hypervisor/include/arch/x86/trusty.h | 11 ++++++--- hypervisor/include/common/hypercall.h | 9 +++++++ hypervisor/include/public/acrn_hv_defs.h | 1 + 7 files changed, 85 insertions(+), 5 deletions(-) diff --git a/hypervisor/arch/x86/guest/vmcall.c b/hypervisor/arch/x86/guest/vmcall.c index 3e3a7c77b..deeb79244 100644 --- a/hypervisor/arch/x86/guest/vmcall.c +++ b/hypervisor/arch/x86/guest/vmcall.c @@ -29,7 +29,8 @@ int vmcall_vmexit_handler(struct vcpu *vcpu) } if (!is_vm0(vm) && hypcall_id != HC_WORLD_SWITCH && - hypcall_id != HC_INITIALIZE_TRUSTY) { + hypcall_id != HC_INITIALIZE_TRUSTY && + hypcall_id != HC_SAVE_RESTORE_SWORLD_CTX) { pr_err("hypercall %d is only allowed from VM0!\n", hypcall_id); goto out; } @@ -170,6 +171,10 @@ int vmcall_vmexit_handler(struct vcpu *vcpu) ret = hcall_get_cpu_pm_state(vm, param1, param2); break; + case HC_SAVE_RESTORE_SWORLD_CTX: + ret = hcall_save_restore_sworld_ctx(vcpu); + break; + default: pr_err("op %d: Invalid hypercall\n", hypcall_id); ret = -EPERM; diff --git a/hypervisor/arch/x86/trusty.c b/hypervisor/arch/x86/trusty.c index 3c0c11f06..af7ea7112 100644 --- a/hypervisor/arch/x86/trusty.c +++ b/hypervisor/arch/x86/trusty.c @@ -494,6 +494,30 @@ void trusty_set_dseed(void *dseed, uint8_t dseed_num) dseed, sizeof(struct seed_info) * dseed_num); } +void save_sworld_context(struct vcpu *vcpu) +{ + memcpy_s(&vcpu->vm->sworld_snapshot, + sizeof(struct cpu_context), + &vcpu->arch_vcpu.contexts[SECURE_WORLD], + sizeof(struct cpu_context)); +} + +void restore_sworld_context(struct vcpu *vcpu) +{ + struct secure_world_control *sworld_ctl = + &vcpu->vm->sworld_control; + + create_secure_world_ept(vcpu->vm, + sworld_ctl->sworld_memory.base_gpa_in_uos, + sworld_ctl->sworld_memory.length, + TRUSTY_EPT_REBASE_GPA); + + memcpy_s(&vcpu->arch_vcpu.contexts[SECURE_WORLD], + sizeof(struct cpu_context), + &vcpu->vm->sworld_snapshot, + sizeof(struct cpu_context)); +} + /** * @} */ // End of trusty_apis diff --git a/hypervisor/common/trusty_hypercall.c b/hypervisor/common/trusty_hypercall.c index fe884b77f..5bbaf7860 100644 --- a/hypervisor/common/trusty_hypercall.c +++ b/hypervisor/common/trusty_hypercall.c @@ -71,3 +71,34 @@ int32_t hcall_initialize_trusty(struct vcpu *vcpu, uint64_t param) return 0; } + +int64_t hcall_save_restore_sworld_ctx(struct vcpu *vcpu) +{ + struct vm *vm = vcpu->vm; + + if (!vm->sworld_control.flag.supported) { + dev_dbg(ACRN_DBG_TRUSTY_HYCALL, + "Secure World is not supported!\n"); + return -EPERM; + } + + /* Currently, Secure World is only running on vCPU0 */ + if (!is_vcpu_bsp(vcpu)) { + dev_dbg(ACRN_DBG_TRUSTY_HYCALL, + "This hypercall is only allowed from vcpu0!"); + return -EPERM; + } + + if (vm->sworld_control.flag.active) { + save_sworld_context(vcpu); + vm->sworld_control.flag.ctx_saved = 1UL; + } else { + if (vm->sworld_control.flag.ctx_saved) { + restore_sworld_context(vcpu); + vm->sworld_control.flag.ctx_saved = 0UL; + vm->sworld_control.flag.active = 1UL; + } + } + + return 0; +} diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index df7c83d11..87405ccbb 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -153,6 +153,13 @@ struct vm { unsigned char GUID[16]; struct secure_world_control sworld_control; + /* Secure World's snapshot + * Currently, Secure World is only running on vcpu[0], + * so the snapshot only stores the vcpu0's run_context + * of secure world. + */ + struct cpu_context sworld_snapshot; + uint32_t vcpuid_entry_nr, vcpuid_level, vcpuid_xlevel; struct vcpuid_entry vcpuid_entries[MAX_VM_VCPUID_ENTRIES]; #ifdef CONFIG_PARTITION_MODE diff --git a/hypervisor/include/arch/x86/trusty.h b/hypervisor/include/arch/x86/trusty.h index ce28c3bcd..0c3836783 100644 --- a/hypervisor/include/arch/x86/trusty.h +++ b/hypervisor/include/arch/x86/trusty.h @@ -104,11 +104,13 @@ struct secure_world_memory { struct secure_world_control { /* Flag indicates Secure World's state */ struct { - /* secure world supporting: 0(unsupported), 1(supported) */ + /* sworld supporting: 0(unsupported), 1(supported) */ uint64_t supported : 1; - /* secure world running status: 0(inactive), 1(active) */ + /* sworld running status: 0(inactive), 1(active) */ uint64_t active : 1; - uint64_t reserved : 62; + /* sworld context saving status: 0(unsaved), 1(saved) */ + uint64_t ctx_saved : 1; + uint64_t reserved : 61; } flag; /* Secure world memory structure */ struct secure_world_memory sworld_memory; @@ -126,7 +128,8 @@ struct trusty_startup_param { void switch_world(struct vcpu *vcpu, int next_world); bool initialize_trusty(struct vcpu *vcpu, uint64_t param); void destroy_secure_world(struct vm *vm); - +void save_sworld_context(struct vcpu *vcpu); +void restore_sworld_context(struct vcpu *vcpu); void trusty_set_dseed(void *dseed, uint8_t dseed_num); #endif /* TRUSTY_H_ */ diff --git a/hypervisor/include/common/hypercall.h b/hypervisor/include/common/hypercall.h index 7673c6419..914703137 100644 --- a/hypervisor/include/common/hypercall.h +++ b/hypervisor/include/common/hypercall.h @@ -397,6 +397,15 @@ int32_t hcall_world_switch(struct vcpu *vcpu); */ int32_t hcall_initialize_trusty(struct vcpu *vcpu, uint64_t param); +/** + * @brief Save/Restore Context of Secure World. + * + * @param vcpu Pointer to VCPU data structure + * + * @return 0 on success, non-zero on error. + */ +int64_t hcall_save_restore_sworld_ctx(struct vcpu *vcpu); + /** * @} */ // End of trusty_hypercall diff --git a/hypervisor/include/public/acrn_hv_defs.h b/hypervisor/include/public/acrn_hv_defs.h index b7ad23258..cfeb8341e 100644 --- a/hypervisor/include/public/acrn_hv_defs.h +++ b/hypervisor/include/public/acrn_hv_defs.h @@ -75,6 +75,7 @@ #define HC_ID_TRUSTY_BASE 0x70UL #define HC_INITIALIZE_TRUSTY BASE_HC_ID(HC_ID, HC_ID_TRUSTY_BASE + 0x00UL) #define HC_WORLD_SWITCH BASE_HC_ID(HC_ID, HC_ID_TRUSTY_BASE + 0x01UL) +#define HC_SAVE_RESTORE_SWORLD_CTX BASE_HC_ID(HC_ID, HC_ID_TRUSTY_BASE + 0x02UL) /* Power management */ #define HC_ID_PM_BASE 0x80UL