diff options
Diffstat (limited to 'arch/powerpc/include/asm')
-rw-r--r-- | arch/powerpc/include/asm/asm-compat.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm.h | 10 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_asm.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_book3s.h | 157 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_book3s_32.h | 42 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_book3s_64.h | 28 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_book3s_asm.h (renamed from arch/powerpc/include/asm/kvm_book3s_64_asm.h) | 25 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_booke.h | 96 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_fpu.h | 85 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 38 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 97 | ||||
-rw-r--r-- | arch/powerpc/include/asm/mmu_context.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/paca.h | 10 | ||||
-rw-r--r-- | arch/powerpc/include/asm/processor.h | 3 | ||||
-rw-r--r-- | arch/powerpc/include/asm/reg.h | 10 |
15 files changed, 490 insertions, 117 deletions
diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h index a9b91ed3d4b..2048a6aeea9 100644 --- a/arch/powerpc/include/asm/asm-compat.h +++ b/arch/powerpc/include/asm/asm-compat.h @@ -21,6 +21,7 @@ /* operations for longs and pointers */ #define PPC_LL stringify_in_c(ld) #define PPC_STL stringify_in_c(std) +#define PPC_STLU stringify_in_c(stdu) #define PPC_LCMPI stringify_in_c(cmpdi) #define PPC_LONG stringify_in_c(.llong) #define PPC_LONG_ALIGN stringify_in_c(.balign 8) @@ -44,6 +45,7 @@ /* operations for longs and pointers */ #define PPC_LL stringify_in_c(lwz) #define PPC_STL stringify_in_c(stw) +#define PPC_STLU stringify_in_c(stwu) #define PPC_LCMPI stringify_in_c(cmpwi) #define PPC_LONG stringify_in_c(.long) #define PPC_LONG_ALIGN stringify_in_c(.balign 4) diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h index 81f3b0b5601..6c5547d82bb 100644 --- a/arch/powerpc/include/asm/kvm.h +++ b/arch/powerpc/include/asm/kvm.h @@ -77,4 +77,14 @@ struct kvm_debug_exit_arch { struct kvm_guest_debug_arch { }; +#define KVM_REG_MASK 0x001f +#define KVM_REG_EXT_MASK 0xffe0 +#define KVM_REG_GPR 0x0000 +#define KVM_REG_FPR 0x0020 +#define KVM_REG_QPR 0x0040 +#define KVM_REG_FQPR 0x0060 + +#define KVM_INTERRUPT_SET -1U +#define KVM_INTERRUPT_UNSET -2U + #endif /* __LINUX_KVM_POWERPC_H */ diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index aadf2dd6f84..c5ea4cda34b 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h @@ -88,6 +88,8 @@ #define BOOK3S_HFLAG_DCBZ32 0x1 #define BOOK3S_HFLAG_SLB 0x2 +#define BOOK3S_HFLAG_PAIRED_SINGLE 0x4 +#define BOOK3S_HFLAG_NATIVE_PS 0x8 #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index db7db0a9696..6f74d93725a 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h @@ -22,46 +22,47 @@ #include <linux/types.h> #include <linux/kvm_host.h> -#include <asm/kvm_book3s_64_asm.h> +#include <asm/kvm_book3s_asm.h> struct kvmppc_slb { u64 esid; u64 vsid; u64 orige; u64 origv; - bool valid; - bool Ks; - bool Kp; - bool nx; - bool large; /* PTEs are 16MB */ - bool tb; /* 1TB segment */ - bool class; + bool valid : 1; + bool Ks : 1; + bool Kp : 1; + bool nx : 1; + bool large : 1; /* PTEs are 16MB */ + bool tb : 1; /* 1TB segment */ + bool class : 1; }; struct kvmppc_sr { u32 raw; u32 vsid; - bool Ks; - bool Kp; - bool nx; + bool Ks : 1; + bool Kp : 1; + bool nx : 1; + bool valid : 1; }; struct kvmppc_bat { u64 raw; u32 bepi; u32 bepi_mask; - bool vs; - bool vp; u32 brpn; u8 wimg; u8 pp; + bool vs : 1; + bool vp : 1; }; struct kvmppc_sid_map { u64 guest_vsid; u64 guest_esid; u64 host_vsid; - bool valid; + bool valid : 1; }; #define SID_MAP_BITS 9 @@ -70,7 +71,7 @@ struct kvmppc_sid_map { struct kvmppc_vcpu_book3s { struct kvm_vcpu vcpu; - struct kvmppc_book3s_shadow_vcpu shadow_vcpu; + struct kvmppc_book3s_shadow_vcpu *shadow_vcpu; struct kvmppc_sid_map sid_map[SID_MAP_NUM]; struct kvmppc_slb slb[64]; struct { @@ -82,9 +83,10 @@ struct kvmppc_vcpu_book3s { struct kvmppc_bat ibat[8]; struct kvmppc_bat dbat[8]; u64 hid[6]; + u64 gqr[8]; int slb_nr; + u32 dsisr; u64 sdr1; - u64 dsisr; u64 hior; u64 msr_mask; u64 vsid_first; @@ -98,15 +100,15 @@ struct kvmppc_vcpu_book3s { #define CONTEXT_GUEST 1 #define CONTEXT_GUEST_END 2 -#define VSID_REAL 0xfffffffffff00000 -#define VSID_REAL_DR 0xffffffffffe00000 -#define VSID_REAL_IR 0xffffffffffd00000 -#define VSID_BAT 0xffffffffffc00000 -#define VSID_PR 0x8000000000000000 +#define VSID_REAL 0x1fffffffffc00000ULL +#define VSID_BAT 0x1fffffffffb00000ULL +#define VSID_REAL_DR 0x2000000000000000ULL +#define VSID_REAL_IR 0x4000000000000000ULL +#define VSID_PR 0x8000000000000000ULL -extern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, u64 ea, u64 ea_mask); +extern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong ea, ulong ea_mask); extern void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 vp, u64 vp_mask); -extern void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, u64 pa_start, u64 pa_end); +extern void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end); extern void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 new_msr); extern void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu); extern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu); @@ -114,11 +116,13 @@ extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte); extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr); extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu); extern struct kvmppc_pte *kvmppc_mmu_find_pte(struct kvm_vcpu *vcpu, u64 ea, bool data); -extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr, bool data); -extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong eaddr, int size, void *ptr); +extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data); +extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data); extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec); extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, bool upper, u32 val); +extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr); +extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu); extern u32 kvmppc_trampoline_lowmem; extern u32 kvmppc_trampoline_enter; @@ -126,6 +130,8 @@ extern void kvmppc_rmcall(ulong srr0, ulong srr1); extern void kvmppc_load_up_fpu(void); extern void kvmppc_load_up_altivec(void); extern void kvmppc_load_up_vsx(void); +extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst); +extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst); static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu) { @@ -140,7 +146,108 @@ static inline ulong dsisr(void) } extern void kvm_return_point(void); +static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vcpu *vcpu); + +static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) +{ + if ( num < 14 ) { + to_svcpu(vcpu)->gpr[num] = val; + to_book3s(vcpu)->shadow_vcpu->gpr[num] = val; + } else + vcpu->arch.gpr[num] = val; +} + +static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num) +{ + if ( num < 14 ) + return to_svcpu(vcpu)->gpr[num]; + else + return vcpu->arch.gpr[num]; +} + +static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val) +{ + to_svcpu(vcpu)->cr = val; + to_book3s(vcpu)->shadow_vcpu->cr = val; +} + +static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) +{ + return to_svcpu(vcpu)->cr; +} + +static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val) +{ + to_svcpu(vcpu)->xer = val; + to_book3s(vcpu)->shadow_vcpu->xer = val; +} + +static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu) +{ + return to_svcpu(vcpu)->xer; +} + +static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val) +{ + to_svcpu(vcpu)->ctr = val; +} + +static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu) +{ + return to_svcpu(vcpu)->ctr; +} + +static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val) +{ + to_svcpu(vcpu)->lr = val; +} + +static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu) +{ + return to_svcpu(vcpu)->lr; +} + +static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val) +{ + to_svcpu(vcpu)->pc = val; +} + +static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu) +{ + return to_svcpu(vcpu)->pc; +} + +static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu) +{ + ulong pc = kvmppc_get_pc(vcpu); + struct kvmppc_book3s_shadow_vcpu *svcpu = to_svcpu(vcpu); + + /* Load the instruction manually if it failed to do so in the + * exit path */ + if (svcpu->last_inst == KVM_INST_FETCH_FAILED) + kvmppc_ld(vcpu, &pc, sizeof(u32), &svcpu->last_inst, false); + + return svcpu->last_inst; +} + +static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) +{ + return to_svcpu(vcpu)->fault_dar; +} + +/* Magic register values loaded into r3 and r4 before the 'sc' assembly + * instruction for the OSI hypercalls */ +#define OSI_SC_MAGIC_R3 0x113724FA +#define OSI_SC_MAGIC_R4 0x77810F9B #define INS_DCBZ 0x7c0007ec +/* Also add subarch specific defines */ + +#ifdef CONFIG_PPC_BOOK3S_32 +#include <asm/kvm_book3s_32.h> +#else +#include <asm/kvm_book3s_64.h> +#endif + #endif /* __ASM_KVM_BOOK3S_H__ */ diff --git a/arch/powerpc/include/asm/kvm_book3s_32.h b/arch/powerpc/include/asm/kvm_book3s_32.h new file mode 100644 index 00000000000..de604db135f --- /dev/null +++ b/arch/powerpc/include/asm/kvm_book3s_32.h @@ -0,0 +1,42 @@ +/* + * 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, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2010 + * + * Authors: Alexander Graf <agraf@suse.de> + */ + +#ifndef __ASM_KVM_BOOK3S_32_H__ +#define __ASM_KVM_BOOK3S_32_H__ + +static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vcpu *vcpu) +{ + return to_book3s(vcpu)->shadow_vcpu; +} + +#define PTE_SIZE 12 +#define VSID_ALL 0 +#define SR_INVALID 0x00000001 /* VSID 1 should always be unused */ +#define SR_KP 0x20000000 +#define PTE_V 0x80000000 +#define PTE_SEC 0x00000040 +#define PTE_M 0x00000010 +#define PTE_R 0x00000100 +#define PTE_C 0x00000080 + +#define SID_SHIFT 28 +#define ESID_MASK 0xf0000000 +#define VSID_MASK 0x00fffffff0000000ULL + +#endif /* __ASM_KVM_BOOK3S_32_H__ */ diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h new file mode 100644 index 00000000000..4cadd612d57 --- /dev/null +++ b/arch/powerpc/include/asm/kvm_book3s_64.h @@ -0,0 +1,28 @@ +/* + * 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, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2010 + * + * Authors: Alexander Graf <agraf@suse.de> + */ + +#ifndef __ASM_KVM_BOOK3S_64_H__ +#define __ASM_KVM_BOOK3S_64_H__ + +static inline struct kvmppc_book3s_shadow_vcpu *to_svcpu(struct kvm_vcpu *vcpu) +{ + return &get_paca()->shadow_vcpu; +} + +#endif /* __ASM_KVM_BOOK3S_64_H__ */ diff --git a/arch/powerpc/include/asm/kvm_book3s_64_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h index 183461b4840..36fdb3aff30 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64_asm.h +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h @@ -22,7 +22,7 @@ #ifdef __ASSEMBLY__ -#ifdef CONFIG_KVM_BOOK3S_64_HANDLER +#ifdef CONFIG_KVM_BOOK3S_HANDLER #include <asm/kvm_asm.h> @@ -55,7 +55,7 @@ kvmppc_resume_\intno: .macro DO_KVM intno .endm -#endif /* CONFIG_KVM_BOOK3S_64_HANDLER */ +#endif /* CONFIG_KVM_BOOK3S_HANDLER */ #else /*__ASSEMBLY__ */ @@ -63,12 +63,33 @@ struct kvmppc_book3s_shadow_vcpu { ulong gpr[14]; u32 cr; u32 xer; + + u32 fault_dsisr; + u32 last_inst; + ulong ctr; + ulong lr; + ulong pc; + ulong shadow_srr1; + ulong fault_dar; + ulong host_r1; ulong host_r2; ulong handler; ulong scratch0; ulong scratch1; ulong vmhandler; + u8 in_guest; + +#ifdef CONFIG_PPC_BOOK3S_32 + u32 sr[16]; /* Guest SRs */ +#endif +#ifdef CONFIG_PPC_BOOK3S_64 + u8 slb_max; /* highest used guest slb entry */ + struct { + u64 esid; + u64 vsid; + } slb[64]; /* guest SLB */ +#endif }; #endif /*__ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h new file mode 100644 index 00000000000..9c9ba3d59b1 --- /dev/null +++ b/arch/powerpc/include/asm/kvm_booke.h @@ -0,0 +1,96 @@ +/* + * 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, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright SUSE Linux Products GmbH 2010 + * + * Authors: Alexander Graf <agraf@suse.de> + */ + +#ifndef __ASM_KVM_BOOKE_H__ +#define __ASM_KVM_BOOKE_H__ + +#include <linux/types.h> +#include <linux/kvm_host.h> + +static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) +{ + vcpu->arch.gpr[num] = val; +} + +static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num) +{ + return vcpu->arch.gpr[num]; +} + +static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val) +{ + vcpu->arch.cr = val; +} + +static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.cr; +} + +static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val) +{ + vcpu->arch.xer = val; +} + +static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.xer; +} + +static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.last_inst; +} + +static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val) +{ + vcpu->arch.ctr = val; +} + +static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.ctr; +} + +static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val) +{ + vcpu->arch.lr = val; +} + +static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.lr; +} + +static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val) +{ + vcpu->arch.pc = val; +} + +static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.pc; +} + +static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.fault_dear; +} + +#endif /* __ASM_KVM_BOOKE_H__ */ diff --git a/arch/powerpc/include/asm/kvm_fpu.h b/arch/powerpc/include/asm/kvm_fpu.h new file mode 100644 index 00000000000..94f05de9ad0 --- /dev/null +++ b/arch/powerpc/include/asm/kvm_fpu.h @@ -0,0 +1,85 @@ +/* + * 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, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright Novell Inc. 2010 + * + * Authors: Alexander Graf <agraf@suse.de> + */ + +#ifndef __ASM_KVM_FPU_H__ +#define __ASM_KVM_FPU_H__ + +#include <linux/types.h> + +extern void fps_fres(struct thread_struct *t, u32 *dst, u32 *src1); +extern void fps_frsqrte(struct thread_struct *t, u32 *dst, u32 *src1); +extern void fps_fsqrts(struct thread_struct *t, u32 *dst, u32 *src1); + +extern void fps_fadds(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2); +extern void fps_fdivs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2); +extern void fps_fmuls(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2); +extern void fps_fsubs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2); + +extern void fps_fmadds(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2, + u32 *src3); +extern void fps_fmsubs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2, + u32 *src3); +extern void fps_fnmadds(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2, + u32 *src3); +extern void fps_fnmsubs(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2, + u32 *src3); +extern void fps_fsel(struct thread_struct *t, u32 *dst, u32 *src1, u32 *src2, + u32 *src3); + +#define FPD_ONE_IN(name) extern void fpd_ ## name(u64 *fpscr, u32 *cr, \ + u64 *dst, u64 *src1); +#define FPD_TWO_IN(name) extern void fpd_ ## name(u64 *fpscr, u32 *cr, \ + u64 *dst, u64 *src1, u64 *src2); +#define FPD_THREE_IN(name) extern void fpd_ ## name(u64 *fpscr, u32 *cr, \ + u64 *dst, u64 *src1, u64 *src2, u64 *src3); + +extern void fpd_fcmpu(u64 *fpscr, u32 *cr, u64 *src1, u64 *src2); +extern void fpd_fcmpo(u64 *fpscr, u32 *cr, u64 *src1, u64 *src2); + +FPD_ONE_IN(fsqrts) +FPD_ONE_IN(frsqrtes) +FPD_ONE_IN(fres) +FPD_ONE_IN(frsp) +FPD_ONE_IN(fctiw) +FPD_ONE_IN(fctiwz) +FPD_ONE_IN(fsqrt) +FPD_ONE_IN(fre) +FPD_ONE_IN(frsqrte) +FPD_ONE_IN(fneg) +FPD_ONE_IN(fabs) +FPD_TWO_IN(fadds) +FPD_TWO_IN(fsubs) +FPD_TWO_IN(fdivs) +FPD_TWO_IN(fmuls) +FPD_TWO_IN(fcpsgn) +FPD_TWO_IN(fdiv) +FPD_TWO_IN(fadd) +FPD_TWO_IN(fmul) +FPD_TWO_IN(fsub) +FPD_THREE_IN(fmsubs) +FPD_THREE_IN(fmadds) +FPD_THREE_IN(fnmsubs) +FPD_THREE_IN(fnmadds) +FPD_THREE_IN(fsel) +FPD_THREE_IN(fmsub) +FPD_THREE_IN(fmadd) +FPD_THREE_IN(fnmsub) +FPD_THREE_IN(fnmadd) + +#endif diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 5e5bae7e152..0c9ad869dec 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -66,7 +66,7 @@ struct kvm_vcpu_stat { u32 dec_exits; u32 ext_intr_exits; u32 halt_wakeup; -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_BOOK3S u32 pf_storage; u32 pf_instruc; u32 sp_storage; @@ -124,12 +124,12 @@ struct kvm_arch { }; struct kvmppc_pte { - u64 eaddr; + ulong eaddr; u64 vpage; - u64 raddr; - bool may_read; - bool may_write; - bool may_execute; + ulong raddr; + bool may_read : 1; + bool may_write : 1; + bool may_execute : 1; }; struct kvmppc_mmu { @@ -145,7 +145,7 @@ struct kvmppc_mmu { int (*xlate)(struct kvm_vcpu *vcpu, gva_t eaddr, struct kvmppc_pte *pte, bool data); void (*reset_msr)(struct kvm_vcpu *vcpu); void (*tlbie)(struct kvm_vcpu *vcpu, ulong addr, bool large); - int (*esid_to_vsid)(struct kvm_vcpu *vcpu, u64 esid, u64 *vsid); + int (*esid_to_vsid)(struct kvm_vcpu *vcpu, ulong esid, u64 *vsid); u64 (*ea_to_vp)(struct kvm_vcpu *vcpu, gva_t eaddr, bool data); bool (*is_dcbz32)(struct kvm_vcpu *vcpu); }; @@ -160,7 +160,7 @@ struct hpte_cache { struct kvm_vcpu_arch { ulong host_stack; u32 host_pid; -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_BOOK3S ulong host_msr; ulong host_r2; void *host_retip; @@ -175,7 +175,7 @@ struct kvm_vcpu_arch { ulong gpr[32]; u64 fpr[32]; - u32 fpscr; + u64 fpscr; #ifdef CONFIG_ALTIVEC vector128 vr[32]; @@ -186,19 +186,23 @@ struct kvm_vcpu_arch { u64 vsr[32]; #endif +#ifdef CONFIG_PPC_BOOK3S + /* For Gekko paired singles */ + u32 qpr[32]; +#endif + +#ifdef CONFIG_BOOKE ulong pc; ulong ctr; ulong lr; -#ifdef CONFIG_BOOKE ulong xer; u32 cr; #endif ulong msr; -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_BOOK3S ulong shadow_msr; - ulong shadow_srr1; ulong hflags; ulong guest_owned_ext; #endif @@ -253,20 +257,22 @@ struct kvm_vcpu_arch { struct dentry *debugfs_exit_timing; #endif +#ifdef CONFIG_BOOKE u32 last_inst; -#ifdef CONFIG_PPC64 - ulong fault_dsisr; -#endif ulong fault_dear; ulong fault_esr; ulong queued_dear; ulong queued_esr; +#endif gpa_t paddr_accessed; u8 io_gpr; /* GPR used as IO source/target */ u8 mmio_is_bigendian; + u8 mmio_sign_extend; u8 dcr_needed; u8 dcr_is_write; + u8 osi_needed; + u8 osi_enabled; u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */ @@ -275,7 +281,7 @@ struct kvm_vcpu_arch { u64 dec_jiffies; unsigned long pending_exceptions; -#ifdef CONFIG_PPC64 +#ifdef CONFIG_PPC_BOOK3S struct hpte_cache hpte_cache[HPTEG_CACHE_NUM]; int hpte_cache_offset; #endif diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index e2642829e43..18d139ec2d2 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h @@ -30,6 +30,8 @@ #include <linux/kvm_host.h> #ifdef CONFIG_PPC_BOOK3S #include <asm/kvm_book3s.h> +#else +#include <asm/kvm_booke.h> #endif enum emulation_result { @@ -37,6 +39,7 @@ enum emulation_result { EMULATE_DO_MMIO, /* kvm_run filled with MMIO request */ EMULATE_DO_DCR, /* kvm_run filled with DCR request */ EMULATE_FAIL, /* can't emulate this instruction */ + EMULATE_AGAIN, /* something went wrong. go again */ }; extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); @@ -48,8 +51,11 @@ extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu); extern int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, unsigned int rt, unsigned int bytes, int is_bigendian); +extern int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu, + unsigned int rt, unsigned int bytes, + int is_bigendian); extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, - u32 val, unsigned int bytes, int is_bigendian); + u64 val, unsigned int bytes, int is_bigendian); extern int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu); @@ -63,6 +69,7 @@ extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr, extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode); extern void kvmppc_mmu_switch_pid(struct kvm_vcpu *vcpu, u32 pid); extern void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu); +extern int kvmppc_mmu_init(struct kvm_vcpu *vcpu); extern int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); extern int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr); extern gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index, @@ -88,6 +95,8 @@ extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu); extern void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu); extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq); +extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu, + struct kvm_interrupt *irq); extern int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, unsigned int op, int *advance); @@ -99,81 +108,37 @@ extern void kvmppc_booke_exit(void); extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu); -#ifdef CONFIG_PPC_BOOK3S - -/* We assume we're always acting on the current vcpu */ - -static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) -{ - if ( num < 14 ) { - get_paca()->shadow_vcpu.gpr[num] = val; - to_book3s(vcpu)->shadow_vcpu.gpr[num] = val; - } else - vcpu->arch.gpr[num] = val; -} - -static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num) -{ - if ( num < 14 ) - return get_paca()->shadow_vcpu.gpr[num]; - else - return vcpu->arch.gpr[num]; -} - -static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val) -{ - get_paca()->shadow_vcpu.cr = val; - to_book3s(vcpu)->shadow_vcpu.cr = val; -} - -static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) -{ - return get_paca()->shadow_vcpu.cr; -} - -static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val) -{ - get_paca()->shadow_vcpu.xer = val; - to_book3s(vcpu)->shadow_vcpu.xer = val; -} - -static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu) +/* + * Cuts out inst bits with ordering according to spec. + * That means the leftmost bit is zero. All given bits are included. + */ +static inline u32 kvmppc_get_field(u64 inst, int msb, int lsb) { - return get_paca()->shadow_vcpu.xer; -} + u32 r; + u32 mask; -#else + BUG_ON(msb > lsb); -static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) -{ - vcpu->arch.gpr[num] = val; -} + mask = (1 << (lsb - msb + 1)) - 1; + r = (inst >> (63 - lsb)) & mask; -static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num) -{ - return vcpu->arch.gpr[num]; + return r; } -static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val) +/* + * Replaces inst bits with ordering according to spec. + */ +static inline u32 kvmppc_set_field(u64 inst, int msb, int lsb, int value) { - vcpu->arch.cr = val; -} + u32 r; + u32 mask; -static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) -{ - return vcpu->arch.cr; -} + BUG_ON(msb > lsb); -static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val) -{ - vcpu->arch.xer = val; -} + mask = ((1 << (lsb - msb + 1)) - 1) << (63 - lsb); + r = (inst & ~mask) | ((value << (63 - lsb)) & mask); -static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu) -{ - return vcpu->arch.xer; + return r; } -#endif - #endif /* __POWERPC_KVM_PPC_H__ */ diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index 26383e0778a..81fb41289d6 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h @@ -27,6 +27,8 @@ extern int __init_new_context(void); extern void __destroy_context(int context_id); static inline void mmu_context_init(void) { } #else +extern unsigned long __init_new_context(void); +extern void __destroy_context(unsigned long context_id); extern void mmu_context_init(void); #endif diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 971dfa4815f..8ce7963ad41 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h @@ -23,7 +23,7 @@ #include <asm/page.h> #include <asm/exception-64e.h> #ifdef CONFIG_KVM_BOOK3S_64_HANDLER -#include <asm/kvm_book3s_64_asm.h> +#include <asm/kvm_book3s_asm.h> #endif register struct paca_struct *local_paca asm("r13"); @@ -137,15 +137,9 @@ struct paca_struct { u64 startpurr; /* PURR/TB value snapshot */ u64 startspurr; /* SPURR value snapshot */ -#ifdef CONFIG_KVM_BOOK3S_64_HANDLER - struct { - u64 esid; - u64 vsid; - } kvm_slb[64]; /* guest SLB */ +#ifdef CONFIG_KVM_BOOK3S_HANDLER /* We use this to store guest state in */ struct kvmppc_book3s_shadow_vcpu shadow_vcpu; - u8 kvm_slb_max; /* highest used guest slb entry */ - u8 kvm_in_guest; /* are we inside the guest? */ #endif }; diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 221ba624046..7492fe8ad6e 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -229,6 +229,9 @@ struct thread_struct { unsigned long spefscr; /* SPE & eFP status */ int used_spe; /* set if process has used spe */ #endif /* CONFIG_SPE */ +#ifdef CONFIG_KVM_BOOK3S_32_HANDLER + void* kvm_shadow_vcpu; /* KVM internal data */ +#endif /* CONFIG_KVM_BOOK3S_32_HANDLER */ }; #define ARCH_MIN_TASKALIGN 16 diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index b68f025924a..d62fdf4e504 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -293,10 +293,12 @@ #define HID1_ABE (1<<10) /* 7450 Address Broadcast Enable */ #define HID1_PS (1<<16) /* 750FX PLL selection */ #define SPRN_HID2 0x3F8 /* Hardware Implementation Register 2 */ +#define SPRN_HID2_GEKKO 0x398 /* Gekko HID2 Register */ #define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */ #define SPRN_IABR2 0x3FA /* 83xx */ #define SPRN_IBCR 0x135 /* 83xx Insn Breakpoint Control Reg */ #define SPRN_HID4 0x3F4 /* 970 HID4 */ +#define SPRN_HID4_GEKKO 0x3F3 /* Gekko HID4 */ #define SPRN_HID5 0x3F6 /* 970 HID5 */ #define SPRN_HID6 0x3F9 /* BE HID 6 */ #define HID6_LB (0x0F<<12) /* Concurrent Large Page Modes */ @@ -465,6 +467,14 @@ #define SPRN_VRSAVE 0x100 /* Vector Register Save Register */ #define SPRN_XER 0x001 /* Fixed Point Exception Register */ +#define SPRN_MMCR0_GEKKO 0x3B8 /* Gekko Monitor Mode Control Register 0 */ +#define SPRN_MMCR1_GEKKO 0x3BC /* Gekko Monitor Mode Control Register 1 */ +#define SPRN_PMC1_GEKKO 0x3B9 /* Gekko Performance Monitor Control 1 */ +#define SPRN_PMC2_GEKKO 0x3BA /* Gekko Performance Monitor Control 2 */ +#define SPRN_PMC3_GEKKO 0x3BD /* Gekko Performance Monitor Control 3 */ +#define SPRN_PMC4_GEKKO 0x3BE /* Gekko Performance Monitor Control 4 */ +#define SPRN_WPAR_GEKKO 0x399 /* Gekko Write Pipe Address Register */ + #define SPRN_SCOMC 0x114 /* SCOM Access Control */ #define SPRN_SCOMD 0x115 /* SCOM Access DATA */ |