mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/arm: Initial support for PSCI-0.2
This patch adds SMC calls to suport a subset of PSCI-0.2 functions (PSCI_VERSION, CPU_ON, SYSTEM_OFF, SYSTEM_RESET). By default, the psci_init() will use PSCI-0.2. Otherwise, it will use PSCI-0.1 if PSCI-0.2 fails or un-supported. To add support for PSCI_VERSION, this patch replaces the "bool_t psci_available" variable with "int psci_ver", which contains the PSCI_VERSION as described in the PSCI-0.2 spec. Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
b095ec3d88
commit
4d3d72c014
4 files changed
+76
-12
No files matched your search
@@ -54,7 +54,7 @@ static void __init smp_spin_table_init(int cpu, struct dt_device_node *dn)
|
|||||||
|
|
||||||
static int __init smp_psci_init(int cpu)
|
static int __init smp_psci_init(int cpu)
|
||||||
{
|
{
|
||||||
if ( !psci_available )
|
if ( !psci_ver )
|
||||||
{
|
{
|
||||||
printk("CPU%d asks for PSCI, but DTB has no PSCI node\n", cpu);
|
printk("CPU%d asks for PSCI, but DTB has no PSCI node\n", cpu);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ int __init platform_specific_mapping(struct domain *d)
|
|||||||
#ifdef CONFIG_ARM_32
|
#ifdef CONFIG_ARM_32
|
||||||
int __init platform_cpu_up(int cpu)
|
int __init platform_cpu_up(int cpu)
|
||||||
{
|
{
|
||||||
if ( psci_available )
|
if ( psci_ver )
|
||||||
return call_psci_cpu_on(cpu);
|
return call_psci_cpu_on(cpu);
|
||||||
|
|
||||||
if ( platform && platform->cpu_up )
|
if ( platform && platform->cpu_up )
|
||||||
|
|||||||
+71
-9
@@ -23,7 +23,7 @@
|
|||||||
#include <xen/smp.h>
|
#include <xen/smp.h>
|
||||||
#include <asm/psci.h>
|
#include <asm/psci.h>
|
||||||
|
|
||||||
bool_t psci_available;
|
uint32_t psci_ver;
|
||||||
|
|
||||||
#ifdef CONFIG_ARM_32
|
#ifdef CONFIG_ARM_32
|
||||||
#define REG_PREFIX "r"
|
#define REG_PREFIX "r"
|
||||||
@@ -58,16 +58,23 @@ int call_psci_cpu_on(int cpu)
|
|||||||
cpu_logical_map(cpu), __pa(init_secondary), 0);
|
cpu_logical_map(cpu), __pa(init_secondary), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init psci_init(void)
|
void call_psci_system_off(void)
|
||||||
|
{
|
||||||
|
if ( psci_ver > XEN_PSCI_V_0_1 )
|
||||||
|
__invoke_psci_fn_smc(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void call_psci_system_reset(void)
|
||||||
|
{
|
||||||
|
if ( psci_ver > XEN_PSCI_V_0_1 )
|
||||||
|
__invoke_psci_fn_smc(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __init psci_is_smc_method(const struct dt_device_node *psci)
|
||||||
{
|
{
|
||||||
const struct dt_device_node *psci;
|
|
||||||
int ret;
|
int ret;
|
||||||
const char *prop_str;
|
const char *prop_str;
|
||||||
|
|
||||||
psci = dt_find_compatible_node(NULL, NULL, "arm,psci");
|
|
||||||
if ( !psci )
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
ret = dt_property_read_string(psci, "method", &prop_str);
|
ret = dt_property_read_string(psci, "method", &prop_str);
|
||||||
if ( ret )
|
if ( ret )
|
||||||
{
|
{
|
||||||
@@ -85,19 +92,74 @@ int __init psci_init(void)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __init psci_init_0_1(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
const struct dt_device_node *psci;
|
||||||
|
|
||||||
|
psci = dt_find_compatible_node(NULL, NULL, "arm,psci");
|
||||||
|
if ( !psci )
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
ret = psci_is_smc_method(psci);
|
||||||
|
if ( ret )
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if ( !dt_property_read_u32(psci, "cpu_on", &psci_cpu_on_nr) )
|
if ( !dt_property_read_u32(psci, "cpu_on", &psci_cpu_on_nr) )
|
||||||
{
|
{
|
||||||
printk("/psci node is missing the \"cpu_on\" property\n");
|
printk("/psci node is missing the \"cpu_on\" property\n");
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
psci_available = 1;
|
psci_ver = XEN_PSCI_V_0_1;
|
||||||
|
|
||||||
printk(XENLOG_INFO "Using PSCI for SMP bringup\n");
|
printk(XENLOG_INFO "Using PSCI-0.1 for SMP bringup\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __init psci_init_0_2(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
const struct dt_device_node *psci;
|
||||||
|
|
||||||
|
psci = dt_find_compatible_node(NULL, NULL, "arm,psci-0.2");
|
||||||
|
if ( !psci )
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
ret = psci_is_smc_method(psci);
|
||||||
|
if ( ret )
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
psci_ver = __invoke_psci_fn_smc(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
|
||||||
|
|
||||||
|
if ( psci_ver != XEN_PSCI_V_0_2 )
|
||||||
|
{
|
||||||
|
printk("Error: PSCI version %#x is not supported.\n", psci_ver);
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
psci_cpu_on_nr = PSCI_0_2_FN_CPU_ON;
|
||||||
|
|
||||||
|
printk(XENLOG_INFO "Using PSCI-0.2 for SMP bringup\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __init psci_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = psci_init_0_2();
|
||||||
|
if ( ret )
|
||||||
|
ret = psci_init_0_1();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local variables:
|
* Local variables:
|
||||||
* mode: C
|
* mode: C
|
||||||
|
|||||||
@@ -13,10 +13,12 @@
|
|||||||
#define PSCI_DISABLED -8
|
#define PSCI_DISABLED -8
|
||||||
|
|
||||||
/* availability of PSCI on the host for SMP bringup */
|
/* availability of PSCI on the host for SMP bringup */
|
||||||
extern bool_t psci_available;
|
extern uint32_t psci_ver;
|
||||||
|
|
||||||
int psci_init(void);
|
int psci_init(void);
|
||||||
int call_psci_cpu_on(int cpu);
|
int call_psci_cpu_on(int cpu);
|
||||||
|
void call_psci_system_off(void);
|
||||||
|
void call_psci_system_reset(void);
|
||||||
|
|
||||||
/* functions to handle guest PSCI requests */
|
/* functions to handle guest PSCI requests */
|
||||||
int32_t do_psci_cpu_on(uint32_t vcpuid, register_t entry_point);
|
int32_t do_psci_cpu_on(uint32_t vcpuid, register_t entry_point);
|
||||||
|
|||||||