Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa024c2f authored by Marc Zyngier's avatar Marc Zyngier Committed by Christoffer Dall
Browse files

KVM: ARM: Power State Coordination Interface implementation



Implement the PSCI specification (ARM DEN 0022A) to control
virtual CPUs being "powered" on or off.

PSCI/KVM is detected using the KVM_CAP_ARM_PSCI capability.

A virtual CPU can now be initialized in a "powered off" state,
using the KVM_ARM_VCPU_POWER_OFF feature flag.

The guest can use either SMC or HVC to execute a PSCI function.

Reviewed-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Signed-off-by: default avatarChristoffer Dall <c.dall@virtualopensystems.com>
parent 45e96ea6
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -2185,6 +2185,10 @@ return ENOEXEC for that vcpu.
Note that because some registers reflect machine topology, all vcpus
Note that because some registers reflect machine topology, all vcpus
should be created before this ioctl is invoked.
should be created before this ioctl is invoked.


Possible features:
	- KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state.
	  Depends on KVM_CAP_ARM_PSCI.



4.78 KVM_GET_REG_LIST
4.78 KVM_GET_REG_LIST


+10 −0
Original line number Original line Diff line number Diff line
@@ -32,6 +32,11 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu);
void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);


static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu)
{
	return 1;
}

static inline u32 *vcpu_pc(struct kvm_vcpu *vcpu)
static inline u32 *vcpu_pc(struct kvm_vcpu *vcpu)
{
{
	return (u32 *)&vcpu->arch.regs.usr_regs.ARM_pc;
	return (u32 *)&vcpu->arch.regs.usr_regs.ARM_pc;
@@ -42,6 +47,11 @@ static inline u32 *vcpu_cpsr(struct kvm_vcpu *vcpu)
	return (u32 *)&vcpu->arch.regs.usr_regs.ARM_cpsr;
	return (u32 *)&vcpu->arch.regs.usr_regs.ARM_cpsr;
}
}


static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
{
	*vcpu_cpsr(vcpu) |= PSR_T_BIT;
}

static inline bool mode_has_spsr(struct kvm_vcpu *vcpu)
static inline bool mode_has_spsr(struct kvm_vcpu *vcpu)
{
{
	unsigned long cpsr_mode = vcpu->arch.regs.usr_regs.ARM_cpsr & MODE_MASK;
	unsigned long cpsr_mode = vcpu->arch.regs.usr_regs.ARM_cpsr & MODE_MASK;
+4 −1
Original line number Original line Diff line number Diff line
@@ -30,7 +30,7 @@
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
#define KVM_HAVE_ONE_REG
#define KVM_HAVE_ONE_REG


#define KVM_VCPU_MAX_FEATURES 0
#define KVM_VCPU_MAX_FEATURES 1


/* We don't currently support large pages. */
/* We don't currently support large pages. */
#define KVM_HPAGE_GFN_SHIFT(x)	0
#define KVM_HPAGE_GFN_SHIFT(x)	0
@@ -100,6 +100,9 @@ struct kvm_vcpu_arch {
	int last_pcpu;
	int last_pcpu;
	cpumask_t require_dcache_flush;
	cpumask_t require_dcache_flush;


	/* Don't run the guest on this vcpu */
	bool pause;

	/* IO related fields */
	/* IO related fields */
	struct kvm_decode mmio_decode;
	struct kvm_decode mmio_decode;


+23 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2012 - ARM Ltd
 * Author: Marc Zyngier <marc.zyngier@arm.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __ARM_KVM_PSCI_H__
#define __ARM_KVM_PSCI_H__

bool kvm_psci_call(struct kvm_vcpu *vcpu);

#endif /* __ARM_KVM_PSCI_H__ */
+16 −0
Original line number Original line Diff line number Diff line
@@ -65,6 +65,8 @@ struct kvm_regs {
#define KVM_ARM_TARGET_CORTEX_A15	0
#define KVM_ARM_TARGET_CORTEX_A15	0
#define KVM_ARM_NUM_TARGETS		1
#define KVM_ARM_NUM_TARGETS		1


#define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */

struct kvm_vcpu_init {
struct kvm_vcpu_init {
	__u32 target;
	__u32 target;
	__u32 features[7];
	__u32 features[7];
@@ -145,4 +147,18 @@ struct kvm_arch_memory_slot {
/* Highest supported SPI, from VGIC_NR_IRQS */
/* Highest supported SPI, from VGIC_NR_IRQS */
#define KVM_ARM_IRQ_GIC_MAX		127
#define KVM_ARM_IRQ_GIC_MAX		127


/* PSCI interface */
#define KVM_PSCI_FN_BASE		0x95c1ba5e
#define KVM_PSCI_FN(n)			(KVM_PSCI_FN_BASE + (n))

#define KVM_PSCI_FN_CPU_SUSPEND		KVM_PSCI_FN(0)
#define KVM_PSCI_FN_CPU_OFF		KVM_PSCI_FN(1)
#define KVM_PSCI_FN_CPU_ON		KVM_PSCI_FN(2)
#define KVM_PSCI_FN_MIGRATE		KVM_PSCI_FN(3)

#define KVM_PSCI_RET_SUCCESS		0
#define KVM_PSCI_RET_NI			((unsigned long)-1)
#define KVM_PSCI_RET_INVAL		((unsigned long)-2)
#define KVM_PSCI_RET_DENIED		((unsigned long)-3)

#endif /* __ARM_KVM_H__ */
#endif /* __ARM_KVM_H__ */
Loading