1 // © 2022 Qualcomm Innovation Center, Inc. All rights reserved.
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #include <hyptypes.h>
6 
7 #include <smccc_platform.h>
8 #include <thread.h>
9 
10 #include <events/smccc.h>
11 
12 #include "smccc_hypercall.h"
13 
14 bool
smccc_handle_hypercall_wrapper(smccc_function_id_t smc_id,bool is_hvc)15 smccc_handle_hypercall_wrapper(smccc_function_id_t smc_id, bool is_hvc)
16 {
17 	bool handled;
18 
19 	smccc_function_t smc_func  = smccc_function_id_get_function(&smc_id);
20 	smccc_owner_id_t smc_owner = smccc_function_id_get_owner_id(&smc_id);
21 
22 	if (smc_owner != SMCCC_OWNER_ID_VENDOR_HYP) {
23 		handled = false;
24 		goto out;
25 	}
26 
27 	bool is_smc64 = smccc_function_id_get_is_smc64(&smc_id);
28 	bool is_fast  = smccc_function_id_get_is_fast(&smc_id);
29 
30 	thread_t   *current = thread_get_self();
31 	register_t *args    = &current->vcpu_regs_gpr.x[0];
32 
33 	smccc_vendor_hyp_function_id_t smc_type =
34 		smccc_vendor_hyp_function_id_cast((uint16_t)(smc_func));
35 
36 	switch (smccc_vendor_hyp_function_id_get_call_class(&smc_type)) {
37 	case SMCCC_VENDOR_HYP_FUNCTION_CLASS_PLATFORM_CALL:
38 		handled = smccc_handle_smc_platform_call(args, is_hvc);
39 		break;
40 	case SMCCC_VENDOR_HYP_FUNCTION_CLASS_HYPERCALL:
41 		if (is_fast && is_smc64) {
42 			uint32_t hyp_num =
43 				smccc_vendor_hyp_function_id_get_function(
44 					&smc_type);
45 			smccc_hypercall_table_wrapper(hyp_num, args);
46 		} else {
47 			args[0] = (register_t)SMCCC_UNKNOWN_FUNCTION64;
48 		}
49 		handled = true;
50 		break;
51 	case SMCCC_VENDOR_HYP_FUNCTION_CLASS_SERVICE:
52 		if (is_fast && !is_smc64) {
53 			uint16_t func =
54 				smccc_vendor_hyp_function_id_get_function(
55 					&smc_type);
56 			switch ((smccc_vendor_hyp_function_t)func) {
57 			case SMCCC_VENDOR_HYP_FUNCTION_CALL_UID:
58 				args[0] = SMCCC_GUNYAH_UID0;
59 				args[1] = SMCCC_GUNYAH_UID1;
60 				args[2] = SMCCC_GUNYAH_UID2;
61 				args[3] = SMCCC_GUNYAH_UID3;
62 				break;
63 			case SMCCC_VENDOR_HYP_FUNCTION_REVISION:
64 				args[0] = (register_t)hyp_api_info_raw(
65 					hyp_api_info_default());
66 				break;
67 			case SMCCC_VENDOR_HYP_FUNCTION_CALL_COUNT:
68 				// Deprecated
69 			default:
70 				args[0] = (register_t)SMCCC_UNKNOWN_FUNCTION64;
71 				break;
72 			}
73 		} else {
74 			args[0] = (register_t)SMCCC_UNKNOWN_FUNCTION64;
75 		}
76 		handled = true;
77 		break;
78 	default:
79 		args[0] = (register_t)SMCCC_UNKNOWN_FUNCTION64;
80 		handled = true;
81 		break;
82 	}
83 
84 out:
85 	return handled;
86 }
87