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

Commit d30f6e48 authored by Scott Wood's avatar Scott Wood Committed by Avi Kivity
Browse files

KVM: PPC: booke: category E.HV (GS-mode) support



Chips such as e500mc that implement category E.HV in Power ISA 2.06
provide hardware virtualization features, including a new MSR mode for
guest state.  The guest OS can perform many operations without trapping
into the hypervisor, including transitions to and from guest userspace.

Since we can use SRR1[GS] to reliably tell whether an exception came from
guest state, instead of messing around with IVPR, we use DO_KVM similarly
to book3s.

Current issues include:
 - Machine checks from guest state are not routed to the host handler.
 - The guest can cause a host oops by executing an emulated instruction
   in a page that lacks read permission.  Existing e500/4xx support has
   the same problem.

Includes work by Ashish Kalra <Ashish.Kalra@freescale.com>,
Varun Sethi <Varun.Sethi@freescale.com>, and
Liu Yu <yu.liu@freescale.com>.

Signed-off-by: default avatarScott Wood <scottwood@freescale.com>
[agraf: remove pt_regs usage]
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent cfac5784
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@


#define PPC_DBELL_MSG_BRDCAST	(0x04000000)
#define PPC_DBELL_MSG_BRDCAST	(0x04000000)
#define PPC_DBELL_TYPE(x)	(((x) & 0xf) << (63-36))
#define PPC_DBELL_TYPE(x)	(((x) & 0xf) << (63-36))
#define PPC_DBELL_LPID(x)	((x) << (63 - 49))
enum ppc_dbell {
enum ppc_dbell {
	PPC_DBELL = 0,		/* doorbell */
	PPC_DBELL = 0,		/* doorbell */
	PPC_DBELL_CRIT = 1,	/* critical doorbell */
	PPC_DBELL_CRIT = 1,	/* critical doorbell */
+8 −0
Original line number Original line Diff line number Diff line
@@ -48,6 +48,14 @@
#define BOOKE_INTERRUPT_SPE_FP_DATA 33
#define BOOKE_INTERRUPT_SPE_FP_DATA 33
#define BOOKE_INTERRUPT_SPE_FP_ROUND 34
#define BOOKE_INTERRUPT_SPE_FP_ROUND 34
#define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35
#define BOOKE_INTERRUPT_PERFORMANCE_MONITOR 35
#define BOOKE_INTERRUPT_DOORBELL 36
#define BOOKE_INTERRUPT_DOORBELL_CRITICAL 37

/* booke_hv */
#define BOOKE_INTERRUPT_GUEST_DBELL 38
#define BOOKE_INTERRUPT_GUEST_DBELL_CRIT 39
#define BOOKE_INTERRUPT_HV_SYSCALL 40
#define BOOKE_INTERRUPT_HV_PRIV 41


/* book3s */
/* book3s */


+49 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2010-2011 Freescale Semiconductor, Inc.
 *
 * 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.
 */

#ifndef ASM_KVM_BOOKE_HV_ASM_H
#define ASM_KVM_BOOKE_HV_ASM_H

#ifdef __ASSEMBLY__

/*
 * All exceptions from guest state must go through KVM
 * (except for those which are delivered directly to the guest) --
 * there are no exceptions for which we fall through directly to
 * the normal host handler.
 *
 * Expected inputs (normal exceptions):
 *   SCRATCH0 = saved r10
 *   r10 = thread struct
 *   r11 = appropriate SRR1 variant (currently used as scratch)
 *   r13 = saved CR
 *   *(r10 + THREAD_NORMSAVE(0)) = saved r11
 *   *(r10 + THREAD_NORMSAVE(2)) = saved r13
 *
 * Expected inputs (crit/mcheck/debug exceptions):
 *   appropriate SCRATCH = saved r8
 *   r8 = exception level stack frame
 *   r9 = *(r8 + _CCR) = saved CR
 *   r11 = appropriate SRR1 variant (currently used as scratch)
 *   *(r8 + GPR9) = saved r9
 *   *(r8 + GPR10) = saved r10 (r10 not yet clobbered)
 *   *(r8 + GPR11) = saved r11
 */
.macro DO_KVM intno srr1
#ifdef CONFIG_KVM_BOOKE_HV
BEGIN_FTR_SECTION
	mtocrf	0x80, r11	/* check MSR[GS] without clobbering reg */
	bf	3, kvmppc_resume_\intno\()_\srr1
	b	kvmppc_handler_\intno\()_\srr1
kvmppc_resume_\intno\()_\srr1:
END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
#endif
.endm

#endif /*__ASSEMBLY__ */
#endif /* ASM_KVM_BOOKE_HV_ASM_H */
+18 −1
Original line number Original line Diff line number Diff line
@@ -106,6 +106,8 @@ struct kvm_vcpu_stat {
	u32 dec_exits;
	u32 dec_exits;
	u32 ext_intr_exits;
	u32 ext_intr_exits;
	u32 halt_wakeup;
	u32 halt_wakeup;
	u32 dbell_exits;
	u32 gdbell_exits;
#ifdef CONFIG_PPC_BOOK3S
#ifdef CONFIG_PPC_BOOK3S
	u32 pf_storage;
	u32 pf_storage;
	u32 pf_instruc;
	u32 pf_instruc;
@@ -140,6 +142,7 @@ enum kvm_exit_types {
	EMULATED_TLBSX_EXITS,
	EMULATED_TLBSX_EXITS,
	EMULATED_TLBWE_EXITS,
	EMULATED_TLBWE_EXITS,
	EMULATED_RFI_EXITS,
	EMULATED_RFI_EXITS,
	EMULATED_RFCI_EXITS,
	DEC_EXITS,
	DEC_EXITS,
	EXT_INTR_EXITS,
	EXT_INTR_EXITS,
	HALT_WAKEUP,
	HALT_WAKEUP,
@@ -147,6 +150,8 @@ enum kvm_exit_types {
	FP_UNAVAIL,
	FP_UNAVAIL,
	DEBUG_EXITS,
	DEBUG_EXITS,
	TIMEINGUEST,
	TIMEINGUEST,
	DBELL_EXITS,
	GDBELL_EXITS,
	__NUMBER_OF_KVM_EXIT_TYPES
	__NUMBER_OF_KVM_EXIT_TYPES
};
};


@@ -217,10 +222,10 @@ struct kvm_arch_memory_slot {
};
};


struct kvm_arch {
struct kvm_arch {
	unsigned int lpid;
#ifdef CONFIG_KVM_BOOK3S_64_HV
#ifdef CONFIG_KVM_BOOK3S_64_HV
	unsigned long hpt_virt;
	unsigned long hpt_virt;
	struct revmap_entry *revmap;
	struct revmap_entry *revmap;
	unsigned int lpid;
	unsigned int host_lpid;
	unsigned int host_lpid;
	unsigned long host_lpcr;
	unsigned long host_lpcr;
	unsigned long sdr1;
	unsigned long sdr1;
@@ -345,6 +350,17 @@ struct kvm_vcpu_arch {
	u64 vsr[64];
	u64 vsr[64];
#endif
#endif


#ifdef CONFIG_KVM_BOOKE_HV
	u32 host_mas4;
	u32 host_mas6;
	u32 shadow_epcr;
	u32 epcr;
	u32 shadow_msrp;
	u32 eplc;
	u32 epsc;
	u32 oldpir;
#endif

#ifdef CONFIG_PPC_BOOK3S
#ifdef CONFIG_PPC_BOOK3S
	/* For Gekko paired singles */
	/* For Gekko paired singles */
	u32 qpr[32];
	u32 qpr[32];
@@ -428,6 +444,7 @@ struct kvm_vcpu_arch {
	ulong queued_esr;
	ulong queued_esr;
	u32 tlbcfg[4];
	u32 tlbcfg[4];
	u32 mmucfg;
	u32 mmucfg;
	u32 epr;
#endif
#endif
	gpa_t paddr_accessed;
	gpa_t paddr_accessed;


+3 −0
Original line number Original line Diff line number Diff line
@@ -139,6 +139,9 @@ extern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
extern void kvmppc_core_commit_memory_region(struct kvm *kvm,
extern void kvmppc_core_commit_memory_region(struct kvm *kvm,
				struct kvm_userspace_memory_region *mem);
				struct kvm_userspace_memory_region *mem);


extern int kvmppc_bookehv_init(void);
extern void kvmppc_bookehv_exit(void);

/*
/*
 * Cuts out inst bits with ordering according to spec.
 * Cuts out inst bits with ordering according to spec.
 * That means the leftmost bit is zero. All given bits are included.
 * That means the leftmost bit is zero. All given bits are included.
Loading