mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
ANDROID: gunyah: Sync with latest "firmware: qcom_scm: Register Gunyah platform ops"
The QCOM platform hooks are not enabled in gki_defconfig, but backport to align to Gunyah v13 patches posted to kernel.org: https://lore.kernel.org/all/20230509204801.2824351-15-quic_eberman@quicinc.com/ Bug: 279506910 Change-Id: Idce927cfa89cfea137b96024dd3c5a2bf297da82 Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
This commit is contained in:
committed by
Carlos Llamas
parent
15a4929f8e
commit
b3f59a9b33
@@ -538,6 +538,7 @@ CONFIG_DMABUF_HEAPS_PAGE_POOL=y
|
||||
CONFIG_UIO=y
|
||||
CONFIG_VIRT_DRIVERS=y
|
||||
CONFIG_GUNYAH=y
|
||||
# CONFIG_GUNYAH_QCOM_PLATFORM is not set
|
||||
CONFIG_GUNYAH_VCPU=y
|
||||
CONFIG_GUNYAH_IRQFD=y
|
||||
CONFIG_GUNYAH_IOEVENTFD=y
|
||||
|
||||
@@ -6,6 +6,7 @@ config GUNYAH
|
||||
depends on MAILBOX
|
||||
select GUNYAH_PLATFORM_HOOKS
|
||||
select AUXILIARY_BUS
|
||||
imply GUNYAH_QCOM_PLATFORM if ARCH_QCOM
|
||||
help
|
||||
The Gunyah drivers are the helper interfaces that run in a guest VM
|
||||
such as basic inter-VM IPC and signaling mechanisms, and higher level
|
||||
@@ -17,6 +18,18 @@ config GUNYAH
|
||||
config GUNYAH_PLATFORM_HOOKS
|
||||
tristate
|
||||
|
||||
config GUNYAH_QCOM_PLATFORM
|
||||
tristate "Support for Gunyah on Qualcomm platforms"
|
||||
depends on GUNYAH
|
||||
select GUNYAH_PLATFORM_HOOKS
|
||||
select QCOM_SCM
|
||||
help
|
||||
Enable support for interacting with Gunyah on Qualcomm
|
||||
platforms. Interaction with Qualcomm firmware requires
|
||||
extra platform-specific support.
|
||||
|
||||
Say Y/M here to use Gunyah on Qualcomm platforms.
|
||||
|
||||
config GUNYAH_VCPU
|
||||
tristate "Runnable Gunyah vCPUs"
|
||||
depends on GUNYAH
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_GUNYAH_PLATFORM_HOOKS) += gunyah_platform_hooks.o
|
||||
obj-$(CONFIG_GUNYAH_QCOM_PLATFORM) += gunyah_qcom.o
|
||||
|
||||
gunyah_rsc_mgr-y += rsc_mgr.o rsc_mgr_rpc.o vm_mgr.o vm_mgr_mm.o
|
||||
obj-$(CONFIG_GUNYAH) += gunyah_rsc_mgr.o
|
||||
|
||||
147
drivers/virt/gunyah/gunyah_qcom.c
Normal file
147
drivers/virt/gunyah/gunyah_qcom.c
Normal file
@@ -0,0 +1,147 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/arm-smccc.h>
|
||||
#include <linux/gunyah_rsc_mgr.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/qcom_scm.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uuid.h>
|
||||
|
||||
#define QCOM_SCM_RM_MANAGED_VMID 0x3A
|
||||
#define QCOM_SCM_MAX_MANAGED_VMID 0x3F
|
||||
|
||||
static int qcom_scm_gh_rm_pre_mem_share(struct gh_rm *rm, struct gh_rm_mem_parcel *mem_parcel)
|
||||
{
|
||||
struct qcom_scm_vmperm *new_perms;
|
||||
u64 src, src_cpy;
|
||||
int ret = 0, i, n;
|
||||
u16 vmid;
|
||||
|
||||
new_perms = kcalloc(mem_parcel->n_acl_entries, sizeof(*new_perms), GFP_KERNEL);
|
||||
if (!new_perms)
|
||||
return -ENOMEM;
|
||||
|
||||
for (n = 0; n < mem_parcel->n_acl_entries; n++) {
|
||||
vmid = le16_to_cpu(mem_parcel->acl_entries[n].vmid);
|
||||
if (vmid <= QCOM_SCM_MAX_MANAGED_VMID)
|
||||
new_perms[n].vmid = vmid;
|
||||
else
|
||||
new_perms[n].vmid = QCOM_SCM_RM_MANAGED_VMID;
|
||||
if (mem_parcel->acl_entries[n].perms & GH_RM_ACL_X)
|
||||
new_perms[n].perm |= QCOM_SCM_PERM_EXEC;
|
||||
if (mem_parcel->acl_entries[n].perms & GH_RM_ACL_W)
|
||||
new_perms[n].perm |= QCOM_SCM_PERM_WRITE;
|
||||
if (mem_parcel->acl_entries[n].perms & GH_RM_ACL_R)
|
||||
new_perms[n].perm |= QCOM_SCM_PERM_READ;
|
||||
}
|
||||
|
||||
src = (1ull << QCOM_SCM_VMID_HLOS);
|
||||
|
||||
for (i = 0; i < mem_parcel->n_mem_entries; i++) {
|
||||
src_cpy = src;
|
||||
ret = qcom_scm_assign_mem(le64_to_cpu(mem_parcel->mem_entries[i].ipa_base),
|
||||
le64_to_cpu(mem_parcel->mem_entries[i].size),
|
||||
&src_cpy, new_perms, mem_parcel->n_acl_entries);
|
||||
if (ret) {
|
||||
src = 0;
|
||||
for (n = 0; n < mem_parcel->n_acl_entries; n++) {
|
||||
vmid = le16_to_cpu(mem_parcel->acl_entries[n].vmid);
|
||||
if (vmid <= QCOM_SCM_MAX_MANAGED_VMID)
|
||||
src |= (1ull << vmid);
|
||||
else
|
||||
src |= (1ull << QCOM_SCM_RM_MANAGED_VMID);
|
||||
}
|
||||
|
||||
new_perms[0].vmid = QCOM_SCM_VMID_HLOS;
|
||||
|
||||
for (i--; i >= 0; i--) {
|
||||
src_cpy = src;
|
||||
WARN_ON_ONCE(qcom_scm_assign_mem(
|
||||
le64_to_cpu(mem_parcel->mem_entries[i].ipa_base),
|
||||
le64_to_cpu(mem_parcel->mem_entries[i].size),
|
||||
&src_cpy, new_perms, 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
kfree(new_perms);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcom_scm_gh_rm_post_mem_reclaim(struct gh_rm *rm, struct gh_rm_mem_parcel *mem_parcel)
|
||||
{
|
||||
struct qcom_scm_vmperm new_perms;
|
||||
u64 src = 0, src_cpy;
|
||||
int ret = 0, i, n;
|
||||
u16 vmid;
|
||||
|
||||
new_perms.vmid = QCOM_SCM_VMID_HLOS;
|
||||
new_perms.perm = QCOM_SCM_PERM_EXEC | QCOM_SCM_PERM_WRITE | QCOM_SCM_PERM_READ;
|
||||
|
||||
for (n = 0; n < mem_parcel->n_acl_entries; n++) {
|
||||
vmid = le16_to_cpu(mem_parcel->acl_entries[n].vmid);
|
||||
if (vmid <= QCOM_SCM_MAX_MANAGED_VMID)
|
||||
src |= (1ull << vmid);
|
||||
else
|
||||
src |= (1ull << QCOM_SCM_RM_MANAGED_VMID);
|
||||
}
|
||||
|
||||
for (i = 0; i < mem_parcel->n_mem_entries; i++) {
|
||||
src_cpy = src;
|
||||
ret = qcom_scm_assign_mem(le64_to_cpu(mem_parcel->mem_entries[i].ipa_base),
|
||||
le64_to_cpu(mem_parcel->mem_entries[i].size),
|
||||
&src_cpy, &new_perms, 1);
|
||||
WARN_ON_ONCE(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct gh_rm_platform_ops qcom_scm_gh_rm_platform_ops = {
|
||||
.pre_mem_share = qcom_scm_gh_rm_pre_mem_share,
|
||||
.post_mem_reclaim = qcom_scm_gh_rm_post_mem_reclaim,
|
||||
};
|
||||
|
||||
/* {19bd54bd-0b37-571b-946f-609b54539de6} */
|
||||
static const uuid_t QCOM_EXT_UUID =
|
||||
UUID_INIT(0x19bd54bd, 0x0b37, 0x571b, 0x94, 0x6f, 0x60, 0x9b, 0x54, 0x53, 0x9d, 0xe6);
|
||||
|
||||
#define GH_QCOM_EXT_CALL_UUID_ID ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
|
||||
ARM_SMCCC_OWNER_VENDOR_HYP, 0x3f01)
|
||||
|
||||
static bool gh_has_qcom_extensions(void)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
uuid_t uuid;
|
||||
|
||||
arm_smccc_1_1_smc(GH_QCOM_EXT_CALL_UUID_ID, &res);
|
||||
|
||||
((u32 *)&uuid.b[0])[0] = lower_32_bits(res.a0);
|
||||
((u32 *)&uuid.b[0])[1] = lower_32_bits(res.a1);
|
||||
((u32 *)&uuid.b[0])[2] = lower_32_bits(res.a2);
|
||||
((u32 *)&uuid.b[0])[3] = lower_32_bits(res.a3);
|
||||
|
||||
return uuid_equal(&uuid, &QCOM_EXT_UUID);
|
||||
}
|
||||
|
||||
static int __init qcom_gh_platform_hooks_register(void)
|
||||
{
|
||||
if (!gh_has_qcom_extensions())
|
||||
return -ENODEV;
|
||||
|
||||
return gh_rm_register_platform_ops(&qcom_scm_gh_rm_platform_ops);
|
||||
}
|
||||
|
||||
static void __exit qcom_gh_platform_hooks_unregister(void)
|
||||
{
|
||||
gh_rm_unregister_platform_ops(&qcom_scm_gh_rm_platform_ops);
|
||||
}
|
||||
|
||||
module_init(qcom_gh_platform_hooks_register);
|
||||
module_exit(qcom_gh_platform_hooks_unregister);
|
||||
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Platform Hooks for Gunyah");
|
||||
MODULE_LICENSE("GPL");
|
||||
Reference in New Issue
Block a user