[PATCH] [ARM] PSCI: improve inline assembly code for smc #0 service call.

136 views
Skip to first unread message

Jean-Christophe DUBOIS

unread,
Apr 10, 2014, 4:55:49 PM4/10/14
to xvisor...@googlegroups.com, Jean-Christophe DUBOIS
Signed-off-by: Jean-Christophe DUBOIS <j...@tribudubois.net>
---
arch/arm/board/common/objects.mk | 1 -
arch/arm/board/common/smp_psci.c | 159 +++++++++++++++++++++++------------
arch/arm/board/common/smp_psci_asm.S | 28 ------
core/include/vmm_compiler.h | 1 +
4 files changed, 107 insertions(+), 82 deletions(-)
delete mode 100644 arch/arm/board/common/smp_psci_asm.S

diff --git a/arch/arm/board/common/objects.mk b/arch/arm/board/common/objects.mk
index c4c8dda..278d362 100644
--- a/arch/arm/board/common/objects.mk
+++ b/arch/arm/board/common/objects.mk
@@ -29,4 +29,3 @@ board-common-objs-$(CONFIG_ARM_SMP_IPI)+=smp_ipi.o
board-common-objs-$(CONFIG_ARM_SMP_SPIN_TABLE)+=smp_spin_table.o
board-common-objs-$(CONFIG_ARM_SCU)+=smp_scu.o
board-common-objs-$(CONFIG_ARM_SMP_PSCI)+=smp_psci.o
-board-common-objs-$(CONFIG_ARM_SMP_PSCI)+=smp_psci_asm.o
diff --git a/arch/arm/board/common/smp_psci.c b/arch/arm/board/common/smp_psci.c
index 12968e9..f0a12c5 100644
--- a/arch/arm/board/common/smp_psci.c
+++ b/arch/arm/board/common/smp_psci.c
@@ -28,6 +28,7 @@
*/

#include <vmm_error.h>
+#include <vmm_compiler.h>
#include <vmm_host_aspace.h>
#include <smp_ops.h>
#include <vmm_stdio.h>
@@ -48,7 +49,7 @@ static u32 psci_function_id[PSCI_FN_MAX];
#define PSCI_RET_EINVAL -2
#define PSCI_RET_EPERM -3

-static int psci_to_xvisor_errno(int errno)
+static int psci_to_xvisor_errno(long errno)
{
switch (errno) {
case PSCI_RET_SUCCESS:
@@ -64,34 +65,63 @@ static int psci_to_xvisor_errno(int errno)
};
}

-extern int psci_smc(u32 function_id, u32 arg0, u32 arg1, u32 arg2);
-
-static int invoke_psci_fn(u32 function_id, u32 arg0, u32 arg1, u32 arg2)
+static int __noinline invoke_psci_fn_smc(unsigned long func,
+ unsigned long arg0,
+ unsigned long arg1,
+ unsigned long arg2)
{
- return psci_to_xvisor_errno(psci_smc(function_id, arg0, arg1, arg2));
+ long ret;
+
+#ifdef CONFIG_ARM64
+ asm volatile(
+ "mov x0, %1\n\t"
+ "mov x1, %2\n\t"
+ "mov x2, %3\n\t"
+ "mov x3, %4\n\t"
+ "smc #0 \n\t"
+ "mov %0, x0\n\t"
+ : "=r" (ret)
+ : "r" (func), "r" (arg0), "r" (arg1), "r" (arg2)
+ : "x0", "x1", "x2", "x3", "cc", "memory");
+#else
+ asm volatile(
+ ".arch_extension sec\n\t"
+ "mov r0, %1\n\t"
+ "mov r1, %2\n\t"
+ "mov r2, %3\n\t"
+ "mov r3, %4\n\t"
+ "smc #0 \n\t"
+ "mov %0, r0\n\t"
+ : "=r" (ret)
+ : "r" (func), "r" (arg0), "r" (arg1), "r" (arg2)
+ : "r0", "r1", "r2", "r3", "cc", "memory");
+#endif
+
+ return psci_to_xvisor_errno(ret);
}

int psci_cpu_suspend(unsigned long power_state, unsigned long entry_point)
{
- return invoke_psci_fn(psci_function_id[PSCI_FN_CPU_SUSPEND],
- power_state, entry_point, 0);
+ return invoke_psci_fn_smc(psci_function_id[PSCI_FN_CPU_SUSPEND],
+ power_state, entry_point, 0);
}

int psci_cpu_off(unsigned long power_state)
{
- return invoke_psci_fn(psci_function_id[PSCI_FN_CPU_OFF], power_state, 0,
- 0);
+ return invoke_psci_fn_smc(psci_function_id[PSCI_FN_CPU_OFF],
+ power_state, 0, 0);
}

int psci_cpu_on(unsigned long cpuid, unsigned long entry_point)
{
- return invoke_psci_fn(psci_function_id[PSCI_FN_CPU_ON], cpuid,
- entry_point, 0);
+ return invoke_psci_fn_smc(psci_function_id[PSCI_FN_CPU_ON],
+ cpuid, entry_point, 0);
}

int psci_migrate(unsigned long cpuid)
{
- return invoke_psci_fn(psci_function_id[PSCI_FN_MIGRATE], cpuid, 0, 0);
+ return invoke_psci_fn_smc(psci_function_id[PSCI_FN_MIGRATE],
+ cpuid, 0, 0);
}

static struct vmm_devtree_nodeid psci_matches[] = {
@@ -102,50 +132,72 @@ static struct vmm_devtree_nodeid psci_matches[] = {
static int __init psci_smp_init(struct vmm_devtree_node *node,
unsigned int cpu)
{
+ int rc;
+ const char *method;
static struct vmm_devtree_node *psci = NULL;

+ if (psci) {
+ return VMM_OK;
+ }
+
+ /* look for node with PSCI compatible string */
+ psci = vmm_devtree_find_matching(NULL, psci_matches);
if (!psci) {
- /* look for the /psci node */
- psci = vmm_devtree_find_matching(NULL, psci_matches);
- if (!psci) {
- vmm_printf("%s: Failed to find psci node\n", __func__);
- return VMM_ENOTAVAIL;
- }
-
- /* it should have a "compatible" attibute containing "arm,psci" */
- /* it should have a "method" attibute equal to "smc" */
-
- /* retrieve the "cpu_on" attribute */
- if (vmm_devtree_read_u32
- (psci, "cpu_on",
- &psci_function_id[PSCI_FN_CPU_ON]) != VMM_OK) {
- vmm_printf("%s: Can't find PSCI 'on' method\n",
- __func__);
- }
-
- /* retrieve the "cpu_suspend" attribute */
- if (vmm_devtree_read_u32
- (psci, "cpu_suspend",
- &psci_function_id[PSCI_FN_CPU_SUSPEND]) != VMM_OK) {
- vmm_printf("%s: Can't find PSCI 'suspend' method\n",
- __func__);
- }
-
- /* retrieve the "cpu_off" attribute */
- if (vmm_devtree_read_u32
- (psci, "cpu_off",
- &psci_function_id[PSCI_FN_CPU_OFF]) != VMM_OK) {
- vmm_printf("%s: Can't find PSCI 'off' method\n",
- __func__);
- }
-
- /* retrieve the "migrate" attribute */
- if (vmm_devtree_read_u32
- (psci, "migrate",
- &psci_function_id[PSCI_FN_MIGRATE]) != VMM_OK) {
- vmm_printf("%s: Can't find PSCI 'migrate' method\n",
- __func__);
- }
+ vmm_printf("%s: Failed to find psci node\n", __func__);
+ return VMM_ENOTAVAIL;
+ }
+
+ /* it should have a "method" attibute equal to "smc" */
+ rc = vmm_devtree_read_string(psci, "method", &method);
+ if (rc) {
+ vmm_printf("%s: Can't find 'method' attribute\n",
+ __func__);
+ return rc;
+ }
+#if 0
+ /* For some reason, this does not work for now. */
+ /* To be investigated. */
+ if (strcmp(method, "smc")) {
+ vmm_printf("%s: 'method' is not 'smc'\n",
+ __func__);
+ return VMM_EINVALID;
+ }
+#endif
+
+ /* retrieve the "cpu_on" attribute */
+ rc = vmm_devtree_read_u32(psci, "cpu_on",
+ &psci_function_id[PSCI_FN_CPU_ON]);
+ if (rc) {
+ vmm_printf("%s: Can't find 'cpu_on' attribute\n",
+ __func__);
+ return rc;
+ }
+
+ /* retrieve the "cpu_suspend" attribute */
+ rc = vmm_devtree_read_u32(psci, "cpu_suspend",
+ &psci_function_id[PSCI_FN_CPU_SUSPEND]);
+ if (rc) {
+ vmm_printf("%s: Can't find 'cpu_suspend' attribute\n",
+ __func__);
+ return rc;
+ }
+
+ /* retrieve the "cpu_off" attribute */
+ rc = vmm_devtree_read_u32(psci, "cpu_off",
+ &psci_function_id[PSCI_FN_CPU_OFF]);
+ if (rc) {
+ vmm_printf("%s: Can't find 'cpu_off' attribute\n",
+ __func__);
+ return rc;
+ }
+
+ /* retrieve the "migrate" attribute */
+ rc = vmm_devtree_read_u32(psci, "migrate",
+ &psci_function_id[PSCI_FN_MIGRATE]);
+ if (rc) {
+ vmm_printf("%s: Can't find 'migrate' attribute\n",
+ __func__);
+ return rc;
}

return VMM_OK;
@@ -153,6 +205,7 @@ static int __init psci_smp_init(struct vmm_devtree_node *node,

static int __init psci_smp_prepare(unsigned int cpu)
{
+ /* Nothing to do here. */
return VMM_OK;
}

diff --git a/arch/arm/board/common/smp_psci_asm.S b/arch/arm/board/common/smp_psci_asm.S
deleted file mode 100644
index c8668b9..0000000
--- a/arch/arm/board/common/smp_psci_asm.S
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Copyright (c) 2014 Jean-Christophe Dubois.
- * 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 as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * @file smp_psci.c
- * @author Jean-Christophe Dubois (j...@tribudubois.net)
- * @brief PSCI asm support function
- *
- */
-
- .globl psci_smc
-psci_smc:
- smc #0
- bx lr
diff --git a/core/include/vmm_compiler.h b/core/include/vmm_compiler.h
index 45c683d..87aefa5 100644
--- a/core/include/vmm_compiler.h
+++ b/core/include/vmm_compiler.h
@@ -28,6 +28,7 @@
#define tostring(s) #s
#define barrier() __asm__ __volatile__("": : :"memory")

+#define __noinline __attribute__((noinline))
#define __always_inline __attribute__((always_inline))
#define __unused __attribute__((unused))
#define __used __attribute__((used))
--
1.8.3.2

Anup Patel

unread,
Apr 11, 2014, 12:25:31 AM4/11/14
to Xvisor Devel, Jean-Christophe DUBOIS
Oops, I send-out a patch for __noinline without seeing that this patch
already has change for adding __noinline. My bad :( :( :(

> #define __always_inline __attribute__((always_inline))
> #define __unused __attribute__((unused))
> #define __used __attribute__((used))
> --
> 1.8.3.2
>
> --
> You received this message because you are subscribed to the Google Groups "Xvisor Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to xvisor-devel...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Applied your patch on xvisor-next tree.

Thanks,
Anup
Reply all
Reply to author
Forward
0 new messages