1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2024-11-19 13:27:49 +00:00
a155-U-u1/kernel-5.10/drivers/misc/mediatek/mkp/mkp_hvc.c
2024-03-11 06:53:12 +11:00

326 lines
11 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 MediaTek Inc.
* Author: Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com>
*/
#include "mkp_hvc.h"
#include "debug.h"
DEBUG_SET_LEVEL(DEBUG_LEVEL_ERR);
static void mkp_smccc_hvc(unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3,
unsigned long a4, unsigned long a5,
unsigned long a6, unsigned long a7,
struct arm_smccc_res *res)
{
arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
}
int mkp_set_mapping_ro_hvc_call(uint32_t policy, uint32_t handle)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_SET_MAPPING_RO);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, 0, 0, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_set_mapping_rw_hvc_call(uint32_t policy, uint32_t handle)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_SET_MAPPING_RW);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, 0, 0, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_set_mapping_nx_hvc_call(uint32_t policy, uint32_t handle)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_SET_MAPPING_NX);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, 0, 0, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_set_mapping_x_hvc_call(uint32_t policy, uint32_t handle)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_SET_MAPPING_X);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, 0, 0, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_clear_mapping_hvc_call(uint32_t policy, uint32_t handle)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_CLEAR_MAPPING);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, 0, 0, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_lookup_mapping_entry_hvc_call(uint32_t policy, uint32_t handle,
unsigned long *entry_size, unsigned long *permission)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_LOOKUP_MAPPING_ENTRY);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, 0, 0, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
if (res.a0)
return -1;
*entry_size = res.a1;
*permission = res.a2;
return 0;
}
int mkp_req_new_policy_hvc_call(unsigned long policy_char)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
uint32_t policy = 0;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_NEW_POLICY);
mkp_smccc_hvc(mkp_hvc_fast_call_id, policy_char, 0, 0, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
policy = (uint32_t)res.a0;
if (res.a0 == 0)
return -1;
return (int)policy;
}
int mkp_change_policy_action_hvc_call(uint32_t policy, unsigned long policy_char_action)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
int ret = -1;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_POLICY_ACTION);
mkp_smccc_hvc(mkp_hvc_fast_call_id, policy_char_action, 0, 0, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
ret = (int)res.a0;
/* Success: 0, Fail: other */
return ret;
}
int mkp_req_new_specified_policy_hvc_call(unsigned long policy_char, uint32_t specified_policy)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
uint32_t policy = 0;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_NEW_SPECIFIED_POLICY);
mkp_smccc_hvc(mkp_hvc_fast_call_id, policy_char, specified_policy, 0, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, specified_policy, res.a0, res.a1, res.a2, res.a3);
policy = (uint32_t)res.a0;
if (res.a0 == 0)
return -1;
/* Expect "policy == specified_policy" */
if (policy != specified_policy)
return -1;
return (int)policy;
}
uint32_t mkp_create_handle_hvc_call(uint32_t policy,
unsigned long ipa, unsigned long size)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
uint32_t handle = 0;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_CREATE_HANDLE);
mkp_smccc_hvc(mkp_hvc_fast_call_id, ipa, size, 0, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
handle = (uint32_t)(res.a0);
// if fail return 0
// success return >0
return handle;
}
int mkp_destroy_handle_hvc_call(uint32_t policy, uint32_t handle)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_DESTROY_HANDLE);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, 0, 0, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_configure_sharebuf_hvc_call(uint32_t policy, uint32_t handle, uint32_t type,
unsigned long nr_entries, unsigned long size)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_CONFIGURE_SHAREBUF);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, type, nr_entries, size, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_update_sharebuf_1_argu_hvc_call(uint32_t policy, uint32_t handle, unsigned long index,
unsigned long a1)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_UPDATE_SHAREBUF_1_ARGU);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, index, a1, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_update_sharebuf_2_argu_hvc_call(uint32_t policy, uint32_t handle, unsigned long index,
unsigned long a1, unsigned long a2)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_UPDATE_SHAREBUF_2_ARGU);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, index, a1, a2, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_update_sharebuf_3_argu_hvc_call(uint32_t policy, uint32_t handle, unsigned long index,
unsigned long a1, unsigned long a2, unsigned long a3)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_UPDATE_SHAREBUF_3_ARGU);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, index, a1, a2, a3, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_update_sharebuf_4_argu_hvc_call(uint32_t policy, uint32_t handle, unsigned long index,
unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_UPDATE_SHAREBUF_4_ARGU);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, index, a1, a2, a3, a4, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_update_sharebuf_5_argu_hvc_call(uint32_t policy, uint32_t handle, unsigned long index,
unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_UPDATE_SHAREBUF_5_ARGU);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, index, a1, a2, a3, a4, a5, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
int mkp_update_sharebuf_hvc_call(uint32_t policy, uint32_t handle, unsigned long index,
unsigned long ipa)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(policy, HVC_FUNC_UPDATE_SHAREBUF);
mkp_smccc_hvc(mkp_hvc_fast_call_id, handle, index, ipa, 0, 0, 0, 0, &res);
MKP_DEBUG("%s:%d hvc_id:0x%x, policy:%d res:0x%lx 0x%lx 0x%lx 0x%lx\n", __func__, __LINE__,
mkp_hvc_fast_call_id, policy, res.a0, res.a1, res.a2, res.a3);
return res.a0 ? -1 : 0;
}
/* Pass some essential information to MKP service, return 0 if success. */
int __init mkp_setup_essential_hvc_call(unsigned long phys_offset,
unsigned long fixaddr_top, unsigned long fixaddr_real_start)
{
uint64_t phys_addr;
static int is_executed;
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
int ret = -1;
/* Get subscribe's IPA */
phys_addr = (uint64_t)(vmalloc_to_pfn((void *)&subscribe) << PAGE_SHIFT) +
((uint64_t)&subscribe & ~PAGE_MASK);
if (is_executed == 0) {
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(0, HVC_FUNC_ESS_0);
mkp_smccc_hvc(mkp_hvc_fast_call_id, phys_offset, fixaddr_top,
fixaddr_real_start, phys_addr, 0, 0, 0, &res);
is_executed = 1;
/* Success */
if (res.a0 == 0)
ret = 0;
}
return ret;
}
/* Tell MKP service it should start granting */
int __init mkp_start_granting_hvc_call(void)
{
struct arm_smccc_res res;
int mkp_hvc_fast_call_id;
int ret = -1;
mkp_hvc_fast_call_id = MKP_HVC_CALL_ID(0, HVC_FUNC_ESS_1);
mkp_smccc_hvc(mkp_hvc_fast_call_id, 0, 0, 0, 0, 0, 0, 0, &res);
/* Success */
if (res.a0 == 0)
ret = 0;
return ret;
}