soc: qcom: hvc: add hypervisor call support
Add API support for calling into the hypervisor. This will allow various drivers to avail hypervisor services. Change-Id: I0a0e8f8fe13a550ad20c5421b712e207933c82f3 Signed-off-by: Pratik Patel <pratikp@codeaurora.org> [pdaly@codeaurora.org Resolve minor conflicts] Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
This commit is contained in:
parent
240d67c2b0
commit
ebce13ea36
4 changed files with 170 additions and 0 deletions
|
@ -179,6 +179,15 @@ config QCOM_SMEM
|
|||
The driver provides an interface to items in a heap shared among all
|
||||
processors in a Qualcomm platform.
|
||||
|
||||
config MSM_HVC
|
||||
bool "MSM Hypervisor Call Support"
|
||||
help
|
||||
This enables the Hypervisor Call module. It provides apis to call
|
||||
into the hypervisor thereby allowing access to services exposed by
|
||||
the hypervisor. It is primarily intended to be used for Silicon
|
||||
Partner/Manufacturer function identifier subrange but supports other
|
||||
service call subranges as well.
|
||||
|
||||
config MSM_IPC_ROUTER_SMD_XPRT
|
||||
depends on MSM_SMD
|
||||
depends on IPC_ROUTER
|
||||
|
|
|
@ -13,6 +13,7 @@ obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_debug.o smp2p_sleepstate.o
|
|||
obj-$(CONFIG_MSM_SMP2P_TEST) += smp2p_loopback.o smp2p_test.o smp2p_spinlock_test.o
|
||||
obj-$(CONFIG_MSM_QMI_INTERFACE) += qmi_interface.o
|
||||
obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o
|
||||
obj-$(CONFIG_MSM_HVC) += hvc.o
|
||||
ifdef CONFIG_DEBUG_FS
|
||||
obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd-debug.o
|
||||
endif
|
||||
|
|
102
drivers/soc/qcom/hvc.c
Normal file
102
drivers/soc/qcom/hvc.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/compiler.h>
|
||||
|
||||
#include <soc/qcom/hvc.h>
|
||||
|
||||
#define HVC_RET_SUCCESS 0
|
||||
#define HVC_RET_ERROR -1
|
||||
#define HVC_RET_EFUNCNOSUPPORT -2
|
||||
#define HVC_RET_EINVALARCH -3
|
||||
#define HVC_RET_EMEMMAP -4
|
||||
#define HVC_RET_EMEMUNMAP -5
|
||||
#define HVC_RET_EMEMPERM -6
|
||||
|
||||
static int hvc_to_linux_errno(int errno)
|
||||
{
|
||||
switch (errno) {
|
||||
case HVC_RET_SUCCESS:
|
||||
return 0;
|
||||
case HVC_RET_ERROR:
|
||||
return -EIO;
|
||||
case HVC_RET_EFUNCNOSUPPORT:
|
||||
return -EOPNOTSUPP;
|
||||
case HVC_RET_EINVALARCH:
|
||||
case HVC_RET_EMEMMAP:
|
||||
case HVC_RET_EMEMUNMAP:
|
||||
return -EINVAL;
|
||||
case HVC_RET_EMEMPERM:
|
||||
return -EPERM;
|
||||
};
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
static int __hvc(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5,
|
||||
u64 x6, u64 x7, u64 *ret1, u64 *ret2, u64 *ret3)
|
||||
{
|
||||
register u64 r0 asm("x0") = x0;
|
||||
register u64 r1 asm("x1") = x1;
|
||||
register u64 r2 asm("x2") = x2;
|
||||
register u64 r3 asm("x3") = x3;
|
||||
register u64 r4 asm("x4") = x4;
|
||||
register u64 r5 asm("x5") = x5;
|
||||
register u64 r6 asm("x6") = x6;
|
||||
register u64 r7 asm("x7") = x7;
|
||||
|
||||
asm volatile(
|
||||
__asmeq("%0", "x0")
|
||||
__asmeq("%1", "x1")
|
||||
__asmeq("%2", "x2")
|
||||
__asmeq("%3", "x3")
|
||||
__asmeq("%4", "x4")
|
||||
__asmeq("%5", "x5")
|
||||
__asmeq("%6", "x6")
|
||||
__asmeq("%7", "x7")
|
||||
"hvc #0\n"
|
||||
: "+r" (r0), "+r" (r1), "+r" (r2), "+r" (r3)
|
||||
: "r" (r4), "r" (r5), "r" (r6), "r" (r7));
|
||||
|
||||
*ret1 = r1;
|
||||
*ret2 = r2;
|
||||
*ret3 = r3;
|
||||
|
||||
return r0;
|
||||
}
|
||||
#else
|
||||
static int __hvc(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5,
|
||||
u64 x6, u64 *ret1, u64 *ret2, u64 *ret3)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int hvc(u64 func_id, struct hvc_desc *desc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!desc)
|
||||
return -EINVAL;
|
||||
|
||||
ret = __hvc(func_id, desc->arg[0], desc->arg[1], desc->arg[2],
|
||||
desc->arg[3], desc->arg[4], desc->arg[5], 0,
|
||||
&desc->ret[0], &desc->ret[1], &desc->ret[2]);
|
||||
|
||||
return hvc_to_linux_errno(ret);
|
||||
}
|
||||
EXPORT_SYMBOL(hvc);
|
58
include/soc/qcom/hvc.h
Normal file
58
include/soc/qcom/hvc.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MSM_HVC_H
|
||||
#define __MSM_HVC_H
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
#define HVC_FN_ARM_BASE 0xC0000000
|
||||
#define HVC_FN_CPU_BASE 0xC1000000
|
||||
#define HVC_FN_SIP_BASE 0xC2000000
|
||||
#define HVC_FN_OEM_BASE 0xC3000000
|
||||
#define HVC_FN_APP_BASE 0xF0000000
|
||||
#define HVC_FN_OS_BASE 0xF2000000
|
||||
#else
|
||||
#define HVC_FN_ARM_BASE 0x80000000
|
||||
#define HVC_FN_CPU_BASE 0x81000000
|
||||
#define HVC_FN_SIP_BASE 0x82000000
|
||||
#define HVC_FN_OEM_BASE 0x83000000
|
||||
#define HVC_FN_APP_BASE 0xB0000000
|
||||
#define HVC_FN_OS_BASE 0xB2000000
|
||||
#endif
|
||||
|
||||
#define HVC_FN_ARM(n) (HVC_FN_ARM_BASE + (n))
|
||||
#define HVC_FN_CPU(n) (HVC_FN_CPU_BASE + (n))
|
||||
#define HVC_FN_SIP(n) (HVC_FN_SIP_BASE + (n))
|
||||
#define HVC_FN_OEM(n) (HVC_FN_OEM_BASE + (n))
|
||||
#define HVC_FN_APP(n) (HVC_FN_APP_BASE + (n))
|
||||
#define HVC_FN_OS(n) (HVC_FN_OS_BASE + (n))
|
||||
|
||||
#define HVC_MAX_ARGS 6
|
||||
#define HVC_MAX_RETS 3
|
||||
#define HVC_MAX_EXTRA_ARGS 4
|
||||
|
||||
struct hvc_desc {
|
||||
u64 arg[HVC_MAX_ARGS];
|
||||
u64 ret[HVC_MAX_RETS];
|
||||
};
|
||||
|
||||
struct hvc_extra_args {
|
||||
u64 arg[HVC_MAX_EXTRA_ARGS];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MSM_HVC
|
||||
extern int hvc(u64 func_id, struct hvc_desc *desc);
|
||||
#else
|
||||
static inline int hvc(u64 func_id, struct hvc_desc *desc) { return 0; }
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Add table
Reference in a new issue