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

Commit 388cc6e1 authored by Paul Mackerras's avatar Paul Mackerras Committed by Alexander Graf
Browse files

KVM: PPC: Book3S HV: Support POWER6 compatibility mode on POWER7



This enables us to use the Processor Compatibility Register (PCR) on
POWER7 to put the processor into architecture 2.05 compatibility mode
when running a guest.  In this mode the new instructions and registers
that were introduced on POWER7 are disabled in user mode.  This
includes all the VSX facilities plus several other instructions such
as ldbrx, stdbrx, popcntw, popcntd, etc.

To select this mode, we have a new register accessible through the
set/get_one_reg interface, called KVM_REG_PPC_ARCH_COMPAT.  Setting
this to zero gives the full set of capabilities of the processor.
Setting it to one of the "logical" PVR values defined in PAPR puts
the vcpu into the compatibility mode for the corresponding
architecture level.  The supported values are:

0x0f000002	Architecture 2.05 (POWER6)
0x0f000003	Architecture 2.06 (POWER7)
0x0f100003	Architecture 2.06+ (POWER7+)

Since the PCR is per-core, the architecture compatibility level and
the corresponding PCR value are stored in the struct kvmppc_vcore, and
are therefore shared between all vcpus in a virtual core.

Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
[agraf: squash in fix to add missing break statements and documentation]
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent 4b8473c9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1837,6 +1837,7 @@ registers, find a list below:
  PPC   | KVM_REG_PPC_VRSAVE	| 32
  PPC   | KVM_REG_PPC_LPCR	| 64
  PPC   | KVM_REG_PPC_PPR	| 64
  PPC   | KVM_REG_PPC_ARCH_COMPAT 32
  PPC   | KVM_REG_PPC_TM_GPR0	| 64
          ...
  PPC   | KVM_REG_PPC_TM_GPR31	| 64
+2 −0
Original line number Diff line number Diff line
@@ -291,6 +291,8 @@ struct kvmppc_vcore {
	struct kvm_vcpu *runner;
	u64 tb_offset;		/* guest timebase - host timebase */
	ulong lpcr;
	u32 arch_compat;
	ulong pcr;
};

#define VCORE_ENTRY_COUNT(vc)	((vc)->entry_exit_count & 0xff)
+11 −0
Original line number Diff line number Diff line
@@ -314,6 +314,10 @@
#define   LPID_RSVD	0x3ff		/* Reserved LPID for partn switching */
#define	SPRN_HMER	0x150	/* Hardware m? error recovery */
#define	SPRN_HMEER	0x151	/* Hardware m? enable error recovery */
#define SPRN_PCR	0x152	/* Processor compatibility register */
#define   PCR_VEC_DIS	(1ul << (63-0))	/* Vec. disable (bit NA since POWER8) */
#define   PCR_VSX_DIS	(1ul << (63-1))	/* VSX disable (bit NA since POWER8) */
#define   PCR_ARCH_205	0x2		/* Architecture 2.05 */
#define	SPRN_HEIR	0x153	/* Hypervisor Emulated Instruction Register */
#define SPRN_TLBINDEXR	0x154	/* P7 TLB control register */
#define SPRN_TLBVPNR	0x155	/* P7 TLB control register */
@@ -1106,6 +1110,13 @@
#define PVR_BE		0x0070
#define PVR_PA6T	0x0090

/* "Logical" PVR values defined in PAPR, representing architecture levels */
#define PVR_ARCH_204	0x0f000001
#define PVR_ARCH_205	0x0f000002
#define PVR_ARCH_206	0x0f000003
#define PVR_ARCH_206p	0x0f100003
#define PVR_ARCH_207	0x0f000004

/* Macros for setting and retrieving special purpose registers */
#ifndef __ASSEMBLY__
#define mfmsr()		({unsigned long rval; \
+3 −0
Original line number Diff line number Diff line
@@ -536,6 +536,9 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_LPCR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
#define KVM_REG_PPC_PPR		(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6)

/* Architecture compatibility level */
#define KVM_REG_PPC_ARCH_COMPAT	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb7)

/* Transactional Memory checkpointed state:
 * This is all GPRs, all VSX regs and a subset of SPRs
 */
+1 −0
Original line number Diff line number Diff line
@@ -526,6 +526,7 @@ int main(void)
	DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads));
	DEFINE(VCORE_TB_OFFSET, offsetof(struct kvmppc_vcore, tb_offset));
	DEFINE(VCORE_LPCR, offsetof(struct kvmppc_vcore, lpcr));
	DEFINE(VCORE_PCR, offsetof(struct kvmppc_vcore, pcr));
	DEFINE(VCPU_SVCPU, offsetof(struct kvmppc_vcpu_book3s, shadow_vcpu) -
			   offsetof(struct kvmppc_vcpu_book3s, vcpu));
	DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige));
Loading