This patch became larger than usual ones, but I haven't found a way to
make it smaller. That's due to the fact it replaces the old, racy CPU
onlining/offlining/reset logic with the one derived from x86.
Along this comes a simplification of the smp interface we only have to
cater those few SoCs without proper PSCI support: it is no longer
required to add stubs for PSCI-based platforms. Consequently, those for
TK1 and Allwinner A20 are removed.
Now obsolete PSCI fragments will be purged in a separate patch.
hypervisor/arch/arm/Makefile | 2 -
hypervisor/arch/arm/control.c | 177 +++++-------------------------
hypervisor/arch/arm/include/asm/cell.h | 4 -
hypervisor/arch/arm/include/asm/control.h | 4 +-
hypervisor/arch/arm/include/asm/smp.h | 13 ---
hypervisor/arch/arm/irqchip.c | 2 +-
hypervisor/arch/arm/psci.c | 67 +++++------
hypervisor/arch/arm/setup.c | 5 +-
hypervisor/arch/arm/smp-sun7i.c | 24 ----
hypervisor/arch/arm/smp-tegra124.c | 24 ----
hypervisor/arch/arm/smp-vexpress.c | 51 +++------
hypervisor/arch/arm/smp.c | 17 +--
12 files changed, 76 insertions(+), 314 deletions(-)
delete mode 100644 hypervisor/arch/arm/smp-sun7i.c
delete mode 100644 hypervisor/arch/arm/smp-tegra124.c
diff --git a/hypervisor/arch/arm/Makefile b/hypervisor/arch/arm/Makefile
index 6a156a3..5e68b1a 100644
--- a/hypervisor/arch/arm/Makefile
+++ b/hypervisor/arch/arm/Makefile
@@ -27,5 +27,3 @@ obj-$(CONFIG_SERIAL_AMBA_PL011) += dbg-write-pl011.o
obj-$(CONFIG_SERIAL_8250_DW) += uart-8250-dw.o
obj-$(CONFIG_SERIAL_TEGRA) += uart-tegra.o
obj-$(CONFIG_MACH_VEXPRESS) += smp-vexpress.o
-obj-$(CONFIG_MACH_SUN7I) += smp-sun7i.o
-obj-$(CONFIG_MACH_TEGRA124) += smp-tegra124.o
diff --git a/hypervisor/arch/arm/control.c b/hypervisor/arch/arm/control.c
index 8bccdfa..5d49116 100644
--- a/hypervisor/arch/arm/control.c
+++ b/hypervisor/arch/arm/control.c
@@ -20,108 +20,10 @@
#include <asm/irqchip.h>
#include <asm/platform.h>
#include <asm/processor.h>
+#include <asm/smp.h>
#include <asm/sysregs.h>
#include <asm/traps.h>
-static void arch_reset_el1(struct registers *regs)
-{
- u32 sctlr;
-
- /* Wipe all banked and usr regs */
- memset(regs, 0, sizeof(struct registers));
-
- arm_write_banked_reg(SP_usr, 0);
- arm_write_banked_reg(SP_svc, 0);
- arm_write_banked_reg(SP_abt, 0);
- arm_write_banked_reg(SP_und, 0);
- arm_write_banked_reg(SP_irq, 0);
- arm_write_banked_reg(SP_fiq, 0);
- arm_write_banked_reg(LR_svc, 0);
- arm_write_banked_reg(LR_abt, 0);
- arm_write_banked_reg(LR_und, 0);
- arm_write_banked_reg(LR_irq, 0);
- arm_write_banked_reg(LR_fiq, 0);
- arm_write_banked_reg(R8_fiq, 0);
- arm_write_banked_reg(R9_fiq, 0);
- arm_write_banked_reg(R10_fiq, 0);
- arm_write_banked_reg(R11_fiq, 0);
- arm_write_banked_reg(R12_fiq, 0);
- arm_write_banked_reg(SPSR_svc, 0);
- arm_write_banked_reg(SPSR_abt, 0);
- arm_write_banked_reg(SPSR_und, 0);
- arm_write_banked_reg(SPSR_irq, 0);
- arm_write_banked_reg(SPSR_fiq, 0);
-
- /* Wipe the system registers */
- arm_read_sysreg(SCTLR_EL1, sctlr);
- sctlr = sctlr & ~SCTLR_MASK;
- arm_write_sysreg(SCTLR_EL1, sctlr);
- arm_write_sysreg(CPACR_EL1, 0);
- arm_write_sysreg(CONTEXTIDR_EL1, 0);
- arm_write_sysreg(PAR_EL1, 0);
- arm_write_sysreg(TTBR0_EL1, 0);
- arm_write_sysreg(TTBR1_EL1, 0);
- arm_write_sysreg(CSSELR_EL1, 0);
-
- arm_write_sysreg(CNTKCTL_EL1, 0);
- arm_write_sysreg(CNTP_CTL_EL0, 0);
- arm_write_sysreg(CNTP_CVAL_EL0, 0);
- arm_write_sysreg(CNTV_CTL_EL0, 0);
- arm_write_sysreg(CNTV_CVAL_EL0, 0);
-
- /* AArch32 specific */
- arm_write_sysreg(TTBCR, 0);
- arm_write_sysreg(DACR, 0);
- arm_write_sysreg(VBAR, 0);
- arm_write_sysreg(DFSR, 0);
- arm_write_sysreg(DFAR, 0);
- arm_write_sysreg(IFSR, 0);
- arm_write_sysreg(IFAR, 0);
- arm_write_sysreg(ADFSR, 0);
- arm_write_sysreg(AIFSR, 0);
- arm_write_sysreg(MAIR0, 0);
- arm_write_sysreg(MAIR1, 0);
- arm_write_sysreg(AMAIR0, 0);
- arm_write_sysreg(AMAIR1, 0);
- arm_write_sysreg(TPIDRURW, 0);
- arm_write_sysreg(TPIDRURO, 0);
- arm_write_sysreg(TPIDRPRW, 0);
-}
-
-void arch_reset_self(struct per_cpu *cpu_data)
-{
- unsigned long reset_address;
- struct cell *cell = cpu_data->cell;
- struct registers *regs = guest_regs(cpu_data);
-
- arm_paging_vcpu_init(&cell->
arch.mm);
-
- /*
- * We come from the IRQ handler, but we won't return there, so the IPI
- * is deactivated here.
- */
- irqchip_eoi_irq(SGI_CPU_OFF, true);
-
- irqchip_cpu_reset(cpu_data);
-
- /* Wait for the driver to call cpu_up */
- if (cell == &root_cell)
- reset_address = arch_smp_spin(cpu_data, root_cell.arch.smp);
- else
- reset_address = arch_smp_spin(cpu_data, cell->arch.smp);
-
- /* Set the new MPIDR */
- arm_write_sysreg(VMPIDR_EL2, cpu_data->virt_id | MPIDR_MP_BIT);
-
- /* Restore an empty context */
- arch_reset_el1(regs);
-
- arm_write_banked_reg(ELR_hyp, reset_address);
- arm_write_banked_reg(SPSR_hyp, RESET_PSR);
-
- vmreturn(regs);
-}
-
static void cpu_reset(void)
{
struct per_cpu *cpu_data = this_cpu_data();
@@ -202,17 +104,6 @@ static void cpu_reset(void)
irqchip_cpu_reset(cpu_data);
}
-static void arch_suspend_self(struct per_cpu *cpu_data)
-{
- psci_suspend(cpu_data);
-
- if (cpu_data->flush_vcpu_caches) {
- arm_paging_vcpu_flush_tlbs();
- dsb(nsh);
- cpu_data->flush_vcpu_caches = false;
- }
-}
-
static void enter_cpu_off(struct per_cpu *cpu_data)
{
cpu_data->park = false;
@@ -308,49 +199,48 @@ void arm_cpu_kick(unsigned int cpu_id)
void arch_suspend_cpu(unsigned int cpu_id)
{
- struct sgi sgi;
+ struct per_cpu *target_data = per_cpu(cpu_id);
+ bool target_suspended;
- if (psci_cpu_stopped(cpu_id))
- return;
+ spin_lock(&target_data->control_lock);
- sgi.routing_mode = 0;
- sgi.aff1 = 0;
- sgi.aff2 = 0;
- sgi.aff3 = 0;
- sgi.targets = 1 << cpu_id;
-
sgi.id = SGI_CPU_OFF;
+ target_data->suspend_cpu = true;
+ target_suspended = target_data->cpu_suspended;
- irqchip_send_sgi(&sgi);
+ spin_unlock(&target_data->control_lock);
- psci_wait_cpu_stopped(cpu_id);
+ if (!target_suspended) {
+ arm_cpu_kick(cpu_id);
+
+ while (!target_data->cpu_suspended)
+ cpu_relax();
+ }
}
void arch_resume_cpu(unsigned int cpu_id)
{
- /*
- * Simply get out of the spin loop by returning to handle_sgi
- * If the CPU is being reset, it already has left the PSCI idle loop.
- */
- if (psci_cpu_stopped(cpu_id))
- psci_resume(cpu_id);
+ struct per_cpu *target_data = per_cpu(cpu_id);
+
+ /* take lock to avoid theoretical race with a pending suspension */
+ spin_lock(&target_data->control_lock);
+
+ target_data->suspend_cpu = false;
+
+ spin_unlock(&target_data->control_lock);
}
void arch_reset_cpu(unsigned int cpu_id)
{
- unsigned long cpu_data = (unsigned long)per_cpu(cpu_id);
+ per_cpu(cpu_id)->reset = true;
- if (psci_cpu_on(cpu_id, (unsigned long)arch_reset_self, cpu_data))
- printk("ERROR: unable to reset CPU%d (was running)\n", cpu_id);
+ arch_resume_cpu(cpu_id);
}
void arch_park_cpu(unsigned int cpu_id)
{
- /*
- * Reset always follows park_cpu, so we just need to make sure that the
- * CPU is suspended
- */
- if (psci_wait_cpu_stopped(cpu_id) != 0)
- printk("ERROR: CPU%d is supposed to be stopped\n", cpu_id);
+ per_cpu(cpu_id)->park = true;
+
+ arch_resume_cpu(cpu_id);
}
static void check_events(struct per_cpu *cpu_data)
@@ -417,9 +307,6 @@ void arch_handle_sgi(struct per_cpu *cpu_data, u32 irqn)
case SGI_INJECT:
irqchip_inject_pending(cpu_data);
break;
- case SGI_CPU_OFF:
- arch_suspend_self(cpu_data);
- break;
case SGI_EVENT:
check_events(cpu_data);
break;
@@ -488,7 +375,6 @@ int arch_cell_create(struct cell *cell)
return err;
}
- register_smp_ops(cell);
smp_cell_init(cell);
return 0;
@@ -504,7 +390,6 @@ void arch_cell_destroy(struct cell *cell)
/* Re-assign the physical IDs for the root cell */
percpu->virt_id = percpu->cpu_id;
- arch_reset_cpu(cpu);
percpu->cpu_on_entry = PSCI_INVALID_ADDRESS;
}
@@ -544,15 +429,7 @@ void __attribute__((noreturn)) arch_panic_stop(void)
__builtin_unreachable();
}
-void arch_panic_park(void)
-{
- /* Won't return to panic_park */
- if (phys_processor_id() == panic_cpu)
- panic_in_progress = 0;
-
- psci_cpu_off(this_cpu_data());
- __builtin_unreachable();
-}
+void arch_panic_park(void) __attribute__((alias("arm_cpu_park")));
void arch_shutdown(void)
{
diff --git a/hypervisor/arch/arm/include/asm/cell.h b/hypervisor/arch/arm/include/asm/cell.h
index 305a2e8..5413d30 100644
--- a/hypervisor/arch/arm/include/asm/cell.h
+++ b/hypervisor/arch/arm/include/asm/cell.h
@@ -13,9 +13,6 @@
#ifndef _JAILHOUSE_ASM_CELL_H
#define _JAILHOUSE_ASM_CELL_H
-#include <jailhouse/types.h>
-#include <asm/smp.h>
-
#ifndef __ASSEMBLY__
#include <jailhouse/paging.h>
@@ -23,7 +20,6 @@
/** ARM-specific cell states. */
struct arch_cell {
struct paging_structures mm;
- struct smp_ops *smp;
u32 irq_bitmap[1024/32];
diff --git a/hypervisor/arch/arm/include/asm/control.h b/hypervisor/arch/arm/include/asm/control.h
index d9346c7..794d7bf 100644
--- a/hypervisor/arch/arm/include/asm/control.h
+++ b/hypervisor/arch/arm/include/asm/control.h
@@ -15,7 +15,6 @@
#define SGI_INJECT 0
#define SGI_EVENT 1
-#define SGI_CPU_OFF 2
#define CACHES_CLEAN 0
#define CACHES_CLEAN_INVALIDATE 1
@@ -35,8 +34,9 @@ void arch_handle_trap(struct per_cpu *cpu_data, struct registers *guest_regs);
struct registers* arch_handle_exit(struct per_cpu *cpu_data,
struct registers *regs);
bool arch_handle_phys_irq(struct per_cpu *cpu_data, u32 irqn);
-void arch_reset_self(struct per_cpu *cpu_data);
+
void arch_shutdown_self(struct per_cpu *cpu_data);
+
unsigned int arm_cpu_by_mpidr(struct cell *cell, unsigned long mpidr);
void __attribute__((noreturn)) vmreturn(struct registers *guest_regs);
diff --git a/hypervisor/arch/arm/include/asm/smp.h b/hypervisor/arch/arm/include/asm/smp.h
index 173908a..42d4394 100644
--- a/hypervisor/arch/arm/include/asm/smp.h
+++ b/hypervisor/arch/arm/include/asm/smp.h
@@ -15,26 +15,13 @@
#ifndef JAILHOUSE_ASM_SMP_H_
#define JAILHOUSE_ASM_SMP_H_
-#ifndef __ASSEMBLY__
-
-struct mmio_access;
-struct per_cpu;
struct cell;
-struct smp_ops {
- /* Returns an address */
- unsigned long (*cpu_spin)(struct per_cpu *cpu_data);
-};
-
extern const unsigned int smp_mmio_regions;
-unsigned long arch_smp_spin(struct per_cpu *cpu_data, struct smp_ops *ops);
-void register_smp_ops(struct cell *cell);
-
int smp_init(void);
void smp_cell_init(struct cell *cell);
void smp_cell_exit(struct cell *cell);
-#endif /* !__ASSEMBLY__ */
#endif /* !JAILHOUSE_ASM_SMP_H_ */
diff --git a/hypervisor/arch/arm/irqchip.c b/hypervisor/arch/arm/irqchip.c
index 5f72cdb..fd9ae6f 100644
--- a/hypervisor/arch/arm/irqchip.c
+++ b/hypervisor/arch/arm/irqchip.c
@@ -169,7 +169,7 @@ int irqchip_cell_init(struct cell *cell)
* Permit direct access to all SGIs and PPIs except for those used by
* the hypervisor.
*/
- cell->arch.irq_bitmap[0] = ~((1 << SGI_INJECT) | (1 << SGI_CPU_OFF) |
+ cell->arch.irq_bitmap[0] = ~((1 << SGI_INJECT) | (1 << SGI_EVENT) |
(1 << MAINTENANCE_IRQ));
err = irqchip.cell_init(cell);
diff --git a/hypervisor/arch/arm/psci.c b/hypervisor/arch/arm/psci.c
index e0a6703..fc7c3f8 100644
--- a/hypervisor/arch/arm/psci.c
+++ b/hypervisor/arch/arm/psci.c
@@ -2,9 +2,11 @@
* Jailhouse, a Linux-based partitioning hypervisor
*
* Copyright (c) ARM Limited, 2014
+ * Copyright (c) Siemens AG, 2016
*
* Authors:
* Jean-Philippe Brucker <
jean-phili...@arm.com>
+ * Jan Kiszka <
jan.k...@siemens.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
@@ -78,19 +80,37 @@ int psci_wait_cpu_stopped(unsigned int cpu_id)
static long psci_emulate_cpu_on(struct per_cpu *cpu_data,
struct trap_context *ctx)
{
+ struct per_cpu *target_data;
+ bool kick_cpu = false;
unsigned int cpu;
- struct psci_mbox *mbox;
+ long result;
cpu = arm_cpu_by_mpidr(cpu_data->cell, ctx->regs[1]);
if (cpu == -1)
/* Virtual id not in set */
return PSCI_DENIED;
- mbox = &(per_cpu(cpu)->guest_mbox);
- mbox->entry = ctx->regs[2];
- mbox->context = ctx->regs[3];
+ target_data = per_cpu(cpu);
- return psci_resume(cpu);
+ spin_lock(&target_data->control_lock);
+
+ if (target_data->wait_for_poweron) {
+ target_data->cpu_on_entry = ctx->regs[2];
+ target_data->cpu_on_context = ctx->regs[3];
+ target_data->reset = true;
+ kick_cpu = true;
+
+ result = PSCI_SUCCESS;
+ } else {
+ result = PSCI_ALREADY_ON;
+ }
+
+ spin_unlock(&target_data->control_lock);
+
+ if (kick_cpu)
+ arm_cpu_kick(cpu);
+
+ return result;
}
static long psci_emulate_affinity_info(struct per_cpu *cpu_data,
@@ -102,33 +122,8 @@ static long psci_emulate_affinity_info(struct per_cpu *cpu_data,
/* Virtual id not in set */
return PSCI_DENIED;
- return psci_cpu_stopped(cpu) ? PSCI_CPU_IS_OFF : PSCI_CPU_IS_ON;
-}
-
-/* Returns the secondary address set by the guest */
-unsigned long psci_emulate_spin(struct per_cpu *cpu_data)
-{
- struct psci_mbox *mbox = &(cpu_data->guest_mbox);
-
- mbox->entry = 0;
-
- /* Wait for emulate_cpu_on or a trapped mmio to the mbox */
- while (mbox->entry == 0)
- psci_suspend(cpu_data);
-
- return mbox->entry;
-}
-
-int psci_cell_init(struct cell *cell)
-{
- unsigned int cpu;
-
- for_each_cpu(cpu, cell->cpu_set) {
- per_cpu(cpu)->guest_mbox.entry = 0;
- per_cpu(cpu)->guest_mbox.context = 0;
- }
-
- return 0;
+ return per_cpu(cpu)->wait_for_poweron ?
+ PSCI_CPU_IS_OFF : PSCI_CPU_IS_ON;
}
long psci_dispatch(struct trap_context *ctx)
@@ -143,13 +138,7 @@ long psci_dispatch(struct trap_context *ctx)
case PSCI_CPU_OFF:
case PSCI_CPU_OFF_V0_1_UBOOT:
- /*
- * The reset function will take care of calling
- * psci_emulate_spin
- */
- arch_reset_self(cpu_data);
-
- /* Not reached */
+ arm_cpu_park();
return 0;
case PSCI_CPU_ON_32:
diff --git a/hypervisor/arch/arm/setup.c b/hypervisor/arch/arm/setup.c
index 2e2bee2..1ac54d0 100644
--- a/hypervisor/arch/arm/setup.c
+++ b/hypervisor/arch/arm/setup.c
@@ -14,6 +14,7 @@
#include <asm/irqchip.h>
#include <asm/percpu.h>
#include <asm/setup.h>
+#include <asm/smp.h>
#include <asm/sysregs.h>
#include <jailhouse/control.h>
#include <jailhouse/paging.h>
@@ -76,7 +77,6 @@ int arch_cpu_init(struct per_cpu *cpu_data)
unsigned long hcr = HCR_VM_BIT | HCR_IMO_BIT | HCR_FMO_BIT
| HCR_TSC_BIT | HCR_TAC_BIT | HCR_TSW_BIT;
- cpu_data->psci_mbox.entry = 0;
cpu_data->virt_id = cpu_data->cpu_id;
cpu_data->mpidr = phys_processor_id();
@@ -121,9 +121,6 @@ int arch_init_late(void)
if (err)
return err;
- /* Platform-specific SMP operations */
- register_smp_ops(&root_cell);
-
err = smp_init();
if (err)
return err;
diff --git a/hypervisor/arch/arm/smp-sun7i.c b/hypervisor/arch/arm/smp-sun7i.c
deleted file mode 100644
index 6b03d5c..0000000
--- a/hypervisor/arch/arm/smp-sun7i.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Jailhouse, a Linux-based partitioning hypervisor
- *
- * Copyright (c) Siemens AG, 2014
- *
- * Authors:
- * Jan Kiszka <
jan.k...@siemens.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- */
-
-#include <jailhouse/cell.h>
-#include <asm/psci.h>
-#include <asm/smp.h>
-
-static struct smp_ops sun7i_smp_ops = {
- .cpu_spin = psci_emulate_spin,
-};
-
-void register_smp_ops(struct cell *cell)
-{
- cell->arch.smp = &sun7i_smp_ops;
-}
diff --git a/hypervisor/arch/arm/smp-tegra124.c b/hypervisor/arch/arm/smp-tegra124.c
deleted file mode 100644
index 63555da..0000000
--- a/hypervisor/arch/arm/smp-tegra124.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Jailhouse, a Linux-based partitioning hypervisor
- *
- * Copyright (c) Siemens AG, 2014, 2015
- *
- * Authors:
- * Jan Kiszka <
jan.k...@siemens.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- */
-
-#include <jailhouse/cell.h>
-#include <asm/psci.h>
-#include <asm/smp.h>
-
-static struct smp_ops tegra124_smp_ops = {
- .cpu_spin = psci_emulate_spin,
-};
-
-void register_smp_ops(struct cell *cell)
-{
- cell->arch.smp = &tegra124_smp_ops;
-}
diff --git a/hypervisor/arch/arm/smp-vexpress.c b/hypervisor/arch/arm/smp-vexpress.c
index 1750a41..4c11f44 100644
--- a/hypervisor/arch/arm/smp-vexpress.c
+++ b/hypervisor/arch/arm/smp-vexpress.c
@@ -27,7 +27,7 @@ static unsigned long root_entry;
static enum mmio_result smp_mmio(void *arg, struct mmio_access *mmio)
{
- struct per_cpu *cpu_data = this_cpu_data();
+ struct per_cpu *target_data, *cpu_data = this_cpu_data();
unsigned int cpu;
if (mmio->address != VEXPRESS_FLAGSSET || !mmio->is_write)
@@ -35,45 +35,24 @@ static enum mmio_result smp_mmio(void *arg, struct mmio_access *mmio)
return MMIO_HANDLED;
for_each_cpu_except(cpu, cpu_data->cell->cpu_set, cpu_data->cpu_id) {
- per_cpu(cpu)->guest_mbox.entry = mmio->value;
- psci_try_resume(cpu);
- }
+ target_data = per_cpu(cpu);
- return MMIO_HANDLED;
-}
+ arch_suspend_cpu(cpu);
-static unsigned long smp_spin(struct per_cpu *cpu_data)
-{
- /*
- * This is super-dodgy: we assume nothing wrote to the flag register
- * since the kernel called smp_prepare_cpus, at initialisation.
- */
- return root_entry;
-}
+ spin_lock(&target_data->control_lock);
-static struct smp_ops vexpress_smp_ops = {
- .cpu_spin = smp_spin,
-};
+ if (target_data->wait_for_poweron) {
+ target_data->cpu_on_entry = mmio->value;
+ target_data->cpu_on_context = 0;
+ target_data->reset = true;
+ }
-/*
- * Store the guest's secondaries into our PSCI, and wake them up when we catch
- * an access to the mbox from the primary.
- */
-static struct smp_ops vexpress_guest_smp_ops = {
- .cpu_spin = psci_emulate_spin,
-};
+ spin_unlock(&target_data->control_lock);
-void register_smp_ops(struct cell *cell)
-{
- /*
- * mach-vexpress only writes the SYS_FLAGS once at boot, so the root
- * cell cannot rely on this write to guess where the secondary CPUs
- * should return.
- */
- if (cell == &root_cell)
- cell->arch.smp = &vexpress_smp_ops;
- else
- cell->arch.smp = &vexpress_guest_smp_ops;
+ arch_resume_cpu(cpu);
+ }
+
+ return MMIO_HANDLED;
}
int smp_init(void)
@@ -104,5 +83,7 @@ void smp_cell_exit(struct cell *cell)
for_each_cpu(cpu, cell->cpu_set) {
per_cpu(cpu)->cpu_on_entry = root_entry;
per_cpu(cpu)->cpu_on_context = 0;
+ arch_suspend_cpu(cpu);
+ arch_reset_cpu(cpu);
}
}
diff --git a/hypervisor/arch/arm/smp.c b/hypervisor/arch/arm/smp.c
index 1b43168..f84ea94 100644
--- a/hypervisor/arch/arm/smp.c
+++ b/hypervisor/arch/arm/smp.c
@@ -12,28 +12,13 @@
* the COPYING file in the top-level directory.
*/
-#include <asm/percpu.h>
#include <asm/smp.h>
const unsigned int __attribute__((weak)) smp_mmio_regions;
-unsigned long arch_smp_spin(struct per_cpu *cpu_data, struct smp_ops *ops)
-{
- /*
- * Hotplugging CPU0 is not currently supported. It is always assumed to
- * be the primary CPU. This is consistent with the linux behavior on
- * most platforms.
- * The guest image always starts at virtual address 0.
- */
- if (cpu_data->virt_id == 0)
- return 0;
-
- return ops->cpu_spin(cpu_data);
-}
-
int __attribute__((weak)) smp_init(void)
{
- return psci_cell_init(&root_cell);
+ return 0;
}
void __attribute__((weak)) smp_cell_init(struct cell *cell)
--
2.1.4