Commit 53ea2e46 authored by Paolo Bonzini's avatar Paolo Bonzini

Merge tag 'signed-kvm-ppc-next' of git://github.com/agraf/linux-2.6 into kvm-next

Patch queue for ppc - 2014-05-30

In this round we have a few nice gems. PR KVM gains initial POWER8 support
as well as LE host awareness, ihe e500 targets can now properly run u-boot,
LE guests now work with PR KVM including KVM hypercalls and HV KVM guests
can now use huge pages.

On top of this there are some bug fixes.

Conflicts:
	include/uapi/linux/kvm.h
parents ee1a725f d8d164a9
...@@ -1794,6 +1794,11 @@ registers, find a list below: ...@@ -1794,6 +1794,11 @@ registers, find a list below:
PPC | KVM_REG_PPC_MMCR0 | 64 PPC | KVM_REG_PPC_MMCR0 | 64
PPC | KVM_REG_PPC_MMCR1 | 64 PPC | KVM_REG_PPC_MMCR1 | 64
PPC | KVM_REG_PPC_MMCRA | 64 PPC | KVM_REG_PPC_MMCRA | 64
PPC | KVM_REG_PPC_MMCR2 | 64
PPC | KVM_REG_PPC_MMCRS | 64
PPC | KVM_REG_PPC_SIAR | 64
PPC | KVM_REG_PPC_SDAR | 64
PPC | KVM_REG_PPC_SIER | 64
PPC | KVM_REG_PPC_PMC1 | 32 PPC | KVM_REG_PPC_PMC1 | 32
PPC | KVM_REG_PPC_PMC2 | 32 PPC | KVM_REG_PPC_PMC2 | 32
PPC | KVM_REG_PPC_PMC3 | 32 PPC | KVM_REG_PPC_PMC3 | 32
...@@ -1868,6 +1873,7 @@ registers, find a list below: ...@@ -1868,6 +1873,7 @@ registers, find a list below:
PPC | KVM_REG_PPC_PPR | 64 PPC | KVM_REG_PPC_PPR | 64
PPC | KVM_REG_PPC_ARCH_COMPAT 32 PPC | KVM_REG_PPC_ARCH_COMPAT 32
PPC | KVM_REG_PPC_DABRX | 32 PPC | KVM_REG_PPC_DABRX | 32
PPC | KVM_REG_PPC_WORT | 64
PPC | KVM_REG_PPC_TM_GPR0 | 64 PPC | KVM_REG_PPC_TM_GPR0 | 64
... ...
PPC | KVM_REG_PPC_TM_GPR31 | 64 PPC | KVM_REG_PPC_TM_GPR31 | 64
......
...@@ -94,10 +94,24 @@ a bitmap of available features inside the magic page. ...@@ -94,10 +94,24 @@ a bitmap of available features inside the magic page.
The following enhancements to the magic page are currently available: The following enhancements to the magic page are currently available:
KVM_MAGIC_FEAT_SR Maps SR registers r/w in the magic page KVM_MAGIC_FEAT_SR Maps SR registers r/w in the magic page
KVM_MAGIC_FEAT_MAS0_TO_SPRG7 Maps MASn, ESR, PIR and high SPRGs
For enhanced features in the magic page, please check for the existence of the For enhanced features in the magic page, please check for the existence of the
feature before using them! feature before using them!
Magic page flags
================
In addition to features that indicate whether a host is capable of a particular
feature we also have a channel for a guest to tell the guest whether it's capable
of something. This is what we call "flags".
Flags are passed to the host in the low 12 bits of the Effective Address.
The following flags are currently available for a guest to expose:
MAGIC_PAGE_FLAG_NOT_MAPPED_NX Guest handles NX bits correclty wrt magic page
MSR bits MSR bits
======== ========
......
...@@ -81,4 +81,38 @@ static inline unsigned int get_oc(u32 inst) ...@@ -81,4 +81,38 @@ static inline unsigned int get_oc(u32 inst)
{ {
return (inst >> 11) & 0x7fff; return (inst >> 11) & 0x7fff;
} }
#define IS_XFORM(inst) (get_op(inst) == 31)
#define IS_DSFORM(inst) (get_op(inst) >= 56)
/*
* Create a DSISR value from the instruction
*/
static inline unsigned make_dsisr(unsigned instr)
{
unsigned dsisr;
/* bits 6:15 --> 22:31 */
dsisr = (instr & 0x03ff0000) >> 16;
if (IS_XFORM(instr)) {
/* bits 29:30 --> 15:16 */
dsisr |= (instr & 0x00000006) << 14;
/* bit 25 --> 17 */
dsisr |= (instr & 0x00000040) << 8;
/* bits 21:24 --> 18:21 */
dsisr |= (instr & 0x00000780) << 3;
} else {
/* bit 5 --> 17 */
dsisr |= (instr & 0x04000000) >> 12;
/* bits 1: 4 --> 18:21 */
dsisr |= (instr & 0x78000000) >> 17;
/* bits 30:31 --> 12:13 */
if (IS_DSFORM(instr))
dsisr |= (instr & 0x00000003) << 18;
}
return dsisr;
}
#endif /* __ASM_PPC_DISASSEMBLE_H__ */ #endif /* __ASM_PPC_DISASSEMBLE_H__ */
...@@ -102,6 +102,7 @@ ...@@ -102,6 +102,7 @@
#define BOOK3S_INTERRUPT_PERFMON 0xf00 #define BOOK3S_INTERRUPT_PERFMON 0xf00
#define BOOK3S_INTERRUPT_ALTIVEC 0xf20 #define BOOK3S_INTERRUPT_ALTIVEC 0xf20
#define BOOK3S_INTERRUPT_VSX 0xf40 #define BOOK3S_INTERRUPT_VSX 0xf40
#define BOOK3S_INTERRUPT_FAC_UNAVAIL 0xf60
#define BOOK3S_INTERRUPT_H_FAC_UNAVAIL 0xf80 #define BOOK3S_INTERRUPT_H_FAC_UNAVAIL 0xf80
#define BOOK3S_IRQPRIO_SYSTEM_RESET 0 #define BOOK3S_IRQPRIO_SYSTEM_RESET 0
...@@ -114,14 +115,15 @@ ...@@ -114,14 +115,15 @@
#define BOOK3S_IRQPRIO_FP_UNAVAIL 7 #define BOOK3S_IRQPRIO_FP_UNAVAIL 7
#define BOOK3S_IRQPRIO_ALTIVEC 8 #define BOOK3S_IRQPRIO_ALTIVEC 8
#define BOOK3S_IRQPRIO_VSX 9 #define BOOK3S_IRQPRIO_VSX 9
#define BOOK3S_IRQPRIO_SYSCALL 10 #define BOOK3S_IRQPRIO_FAC_UNAVAIL 10
#define BOOK3S_IRQPRIO_MACHINE_CHECK 11 #define BOOK3S_IRQPRIO_SYSCALL 11
#define BOOK3S_IRQPRIO_DEBUG 12 #define BOOK3S_IRQPRIO_MACHINE_CHECK 12
#define BOOK3S_IRQPRIO_EXTERNAL 13 #define BOOK3S_IRQPRIO_DEBUG 13
#define BOOK3S_IRQPRIO_DECREMENTER 14 #define BOOK3S_IRQPRIO_EXTERNAL 14
#define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR 15 #define BOOK3S_IRQPRIO_DECREMENTER 15
#define BOOK3S_IRQPRIO_EXTERNAL_LEVEL 16 #define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR 16
#define BOOK3S_IRQPRIO_MAX 17 #define BOOK3S_IRQPRIO_EXTERNAL_LEVEL 17
#define BOOK3S_IRQPRIO_MAX 18
#define BOOK3S_HFLAG_DCBZ32 0x1 #define BOOK3S_HFLAG_DCBZ32 0x1
#define BOOK3S_HFLAG_SLB 0x2 #define BOOK3S_HFLAG_SLB 0x2
......
...@@ -268,9 +268,10 @@ static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu) ...@@ -268,9 +268,10 @@ static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
return vcpu->arch.pc; return vcpu->arch.pc;
} }
static inline u64 kvmppc_get_msr(struct kvm_vcpu *vcpu);
static inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu) static inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu)
{ {
return (vcpu->arch.shared->msr & MSR_LE) != (MSR_KERNEL & MSR_LE); return (kvmppc_get_msr(vcpu) & MSR_LE) != (MSR_KERNEL & MSR_LE);
} }
static inline u32 kvmppc_get_last_inst_internal(struct kvm_vcpu *vcpu, ulong pc) static inline u32 kvmppc_get_last_inst_internal(struct kvm_vcpu *vcpu, ulong pc)
......
...@@ -77,34 +77,122 @@ static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits) ...@@ -77,34 +77,122 @@ static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits)
return old == 0; return old == 0;
} }
static inline int __hpte_actual_psize(unsigned int lp, int psize)
{
int i, shift;
unsigned int mask;
/* start from 1 ignoring MMU_PAGE_4K */
for (i = 1; i < MMU_PAGE_COUNT; i++) {
/* invalid penc */
if (mmu_psize_defs[psize].penc[i] == -1)
continue;
/*
* encoding bits per actual page size
* PTE LP actual page size
* rrrr rrrz >=8KB
* rrrr rrzz >=16KB
* rrrr rzzz >=32KB
* rrrr zzzz >=64KB
* .......
*/
shift = mmu_psize_defs[i].shift - LP_SHIFT;
if (shift > LP_BITS)
shift = LP_BITS;
mask = (1 << shift) - 1;
if ((lp & mask) == mmu_psize_defs[psize].penc[i])
return i;
}
return -1;
}
static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
unsigned long pte_index) unsigned long pte_index)
{ {
unsigned long rb, va_low; int b_psize, a_psize;
unsigned int penc;
unsigned long rb = 0, va_low, sllp;
unsigned int lp = (r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
if (!(v & HPTE_V_LARGE)) {
/* both base and actual psize is 4k */
b_psize = MMU_PAGE_4K;
a_psize = MMU_PAGE_4K;
} else {
for (b_psize = 0; b_psize < MMU_PAGE_COUNT; b_psize++) {
/* valid entries have a shift value */
if (!mmu_psize_defs[b_psize].shift)
continue;
a_psize = __hpte_actual_psize(lp, b_psize);
if (a_psize != -1)
break;
}
}
/*
* Ignore the top 14 bits of va
* v have top two bits covering segment size, hence move
* by 16 bits, Also clear the lower HPTE_V_AVPN_SHIFT (7) bits.
* AVA field in v also have the lower 23 bits ignored.
* For base page size 4K we need 14 .. 65 bits (so need to
* collect extra 11 bits)
* For others we need 14..14+i
*/
/* This covers 14..54 bits of va*/
rb = (v & ~0x7fUL) << 16; /* AVA field */ rb = (v & ~0x7fUL) << 16; /* AVA field */
/*
* AVA in v had cleared lower 23 bits. We need to derive
* that from pteg index
*/
va_low = pte_index >> 3; va_low = pte_index >> 3;
if (v & HPTE_V_SECONDARY) if (v & HPTE_V_SECONDARY)
va_low = ~va_low; va_low = ~va_low;
/* xor vsid from AVA */ /*
* get the vpn bits from va_low using reverse of hashing.
* In v we have va with 23 bits dropped and then left shifted
* HPTE_V_AVPN_SHIFT (7) bits. Now to find vsid we need
* right shift it with (SID_SHIFT - (23 - 7))
*/
if (!(v & HPTE_V_1TB_SEG)) if (!(v & HPTE_V_1TB_SEG))
va_low ^= v >> 12; va_low ^= v >> (SID_SHIFT - 16);
else else
va_low ^= v >> 24; va_low ^= v >> (SID_SHIFT_1T - 16);
va_low &= 0x7ff; va_low &= 0x7ff;
if (v & HPTE_V_LARGE) {
rb |= 1; /* L field */ switch (b_psize) {
if (cpu_has_feature(CPU_FTR_ARCH_206) && case MMU_PAGE_4K:
(r & 0xff000)) { sllp = ((mmu_psize_defs[a_psize].sllp & SLB_VSID_L) >> 6) |
/* non-16MB large page, must be 64k */ ((mmu_psize_defs[a_psize].sllp & SLB_VSID_LP) >> 4);
/* (masks depend on page size) */ rb |= sllp << 5; /* AP field */
rb |= 0x1000; /* page encoding in LP field */ rb |= (va_low & 0x7ff) << 12; /* remaining 11 bits of AVA */
rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */ break;
rb |= ((va_low << 4) & 0xf0); /* AVAL field (P7 doesn't seem to care) */ default:
} {
} else { int aval_shift;
/* 4kB page */ /*
rb |= (va_low & 0x7ff) << 12; /* remaining 11b of VA */ * remaining 7bits of AVA/LP fields
* Also contain the rr bits of LP
*/
rb |= (va_low & 0x7f) << 16;
/*
* Now clear not needed LP bits based on actual psize
*/
rb &= ~((1ul << mmu_psize_defs[a_psize].shift) - 1);
/*
* AVAL field 58..77 - base_page_shift bits of va
* we have space for 58..64 bits, Missing bits should
* be zero filled. +1 is to take care of L bit shift
*/
aval_shift = 64 - (77 - mmu_psize_defs[b_psize].shift) + 1;
rb |= ((va_low << aval_shift) & 0xfe);
rb |= 1; /* L field */
penc = mmu_psize_defs[b_psize].penc[a_psize];
rb |= penc << 12; /* LP field */
break;
}
} }
rb |= (v >> 54) & 0x300; /* B field */ rb |= (v >> 54) & 0x300; /* B field */
return rb; return rb;
...@@ -112,14 +200,26 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, ...@@ -112,14 +200,26 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
static inline unsigned long hpte_page_size(unsigned long h, unsigned long l) static inline unsigned long hpte_page_size(unsigned long h, unsigned long l)
{ {
int size, a_psize;
/* Look at the 8 bit LP value */
unsigned int lp = (l >> LP_SHIFT) & ((1 << LP_BITS) - 1);
/* only handle 4k, 64k and 16M pages for now */ /* only handle 4k, 64k and 16M pages for now */
if (!(h & HPTE_V_LARGE)) if (!(h & HPTE_V_LARGE))
return 1ul << 12; /* 4k page */ return 1ul << 12;
if ((l & 0xf000) == 0x1000 && cpu_has_feature(CPU_FTR_ARCH_206)) else {
return 1ul << 16; /* 64k page */ for (size = 0; size < MMU_PAGE_COUNT; size++) {
if ((l & 0xff000) == 0) /* valid entries have a shift value */
return 1ul << 24; /* 16M page */ if (!mmu_psize_defs[size].shift)
return 0; /* error */ continue;
a_psize = __hpte_actual_psize(lp, size);
if (a_psize != -1)
return 1ul << mmu_psize_defs[a_psize].shift;
}
}
return 0;
} }
static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize) static inline unsigned long hpte_rpn(unsigned long ptel, unsigned long psize)
......
...@@ -104,6 +104,7 @@ struct kvmppc_host_state { ...@@ -104,6 +104,7 @@ struct kvmppc_host_state {
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
u64 cfar; u64 cfar;
u64 ppr; u64 ppr;
u64 host_fscr;
#endif #endif
}; };
...@@ -133,6 +134,7 @@ struct kvmppc_book3s_shadow_vcpu { ...@@ -133,6 +134,7 @@ struct kvmppc_book3s_shadow_vcpu {
u64 esid; u64 esid;
u64 vsid; u64 vsid;
} slb[64]; /* guest SLB */ } slb[64]; /* guest SLB */
u64 shadow_fscr;
#endif #endif
}; };
......
...@@ -108,9 +108,4 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) ...@@ -108,9 +108,4 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
{ {
return vcpu->arch.fault_dear; return vcpu->arch.fault_dear;
} }
static inline ulong kvmppc_get_msr(struct kvm_vcpu *vcpu)
{
return vcpu->arch.shared->msr;
}
#endif /* __ASM_KVM_BOOKE_H__ */ #endif /* __ASM_KVM_BOOKE_H__ */
...@@ -449,7 +449,9 @@ struct kvm_vcpu_arch { ...@@ -449,7 +449,9 @@ struct kvm_vcpu_arch {
ulong pc; ulong pc;
ulong ctr; ulong ctr;
ulong lr; ulong lr;
#ifdef CONFIG_PPC_BOOK3S
ulong tar; ulong tar;
#endif
ulong xer; ulong xer;
u32 cr; u32 cr;
...@@ -475,6 +477,7 @@ struct kvm_vcpu_arch { ...@@ -475,6 +477,7 @@ struct kvm_vcpu_arch {
ulong ppr; ulong ppr;
ulong pspb; ulong pspb;
ulong fscr; ulong fscr;
ulong shadow_fscr;
ulong ebbhr; ulong ebbhr;
ulong ebbrr; ulong ebbrr;
ulong bescr; ulong bescr;
...@@ -562,6 +565,7 @@ struct kvm_vcpu_arch { ...@@ -562,6 +565,7 @@ struct kvm_vcpu_arch {
#ifdef CONFIG_PPC_BOOK3S #ifdef CONFIG_PPC_BOOK3S
ulong fault_dar; ulong fault_dar;
u32 fault_dsisr; u32 fault_dsisr;
unsigned long intr_msr;
#endif #endif
#ifdef CONFIG_BOOKE #ifdef CONFIG_BOOKE
...@@ -622,8 +626,12 @@ struct kvm_vcpu_arch { ...@@ -622,8 +626,12 @@ struct kvm_vcpu_arch {
wait_queue_head_t cpu_run; wait_queue_head_t cpu_run;
struct kvm_vcpu_arch_shared *shared; struct kvm_vcpu_arch_shared *shared;
#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
bool shared_big_endian;
#endif
unsigned long magic_page_pa; /* phys addr to map the magic page to */ unsigned long magic_page_pa; /* phys addr to map the magic page to */
unsigned long magic_page_ea; /* effect. addr to map the magic page to */ unsigned long magic_page_ea; /* effect. addr to map the magic page to */
bool disable_kernel_nx;
int irq_type; /* one of KVM_IRQ_* */ int irq_type; /* one of KVM_IRQ_* */
int irq_cpu_id; int irq_cpu_id;
...@@ -654,7 +662,6 @@ struct kvm_vcpu_arch { ...@@ -654,7 +662,6 @@ struct kvm_vcpu_arch {
spinlock_t tbacct_lock; spinlock_t tbacct_lock;
u64 busy_stolen; u64 busy_stolen;
u64 busy_preempt; u64 busy_preempt;
unsigned long intr_msr;
#endif #endif
}; };
......
...@@ -448,6 +448,84 @@ static inline void kvmppc_mmu_flush_icache(pfn_t pfn) ...@@ -448,6 +448,84 @@ static inline void kvmppc_mmu_flush_icache(pfn_t pfn)
} }
} }
/*
* Shared struct helpers. The shared struct can be little or big endian,
* depending on the guest endianness. So expose helpers to all of them.
*/
static inline bool kvmppc_shared_big_endian(struct kvm_vcpu *vcpu)
{
#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
/* Only Book3S_64 PR supports bi-endian for now */
return vcpu->arch.shared_big_endian;
#elif defined(CONFIG_PPC_BOOK3S_64) && defined(__LITTLE_ENDIAN__)
/* Book3s_64 HV on little endian is always little endian */
return false;
#else
return true;
#endif
}
#define SHARED_WRAPPER_GET(reg, size) \
static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \
{ \
if (kvmppc_shared_big_endian(vcpu)) \
return be##size##_to_cpu(vcpu->arch.shared->reg); \
else \
return le##size##_to_cpu(vcpu->arch.shared->reg); \
} \
#define SHARED_WRAPPER_SET(reg, size) \
static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val) \
{ \
if (kvmppc_shared_big_endian(vcpu)) \
vcpu->arch.shared->reg = cpu_to_be##size(val); \
else \
vcpu->arch.shared->reg = cpu_to_le##size(val); \
} \
#define SHARED_WRAPPER(reg, size) \
SHARED_WRAPPER_GET(reg, size) \
SHARED_WRAPPER_SET(reg, size) \
SHARED_WRAPPER(critical, 64)
SHARED_WRAPPER(sprg0, 64)
SHARED_WRAPPER(sprg1, 64)
SHARED_WRAPPER(sprg2, 64)
SHARED_WRAPPER(sprg3, 64)
SHARED_WRAPPER(srr0, 64)
SHARED_WRAPPER(srr1, 64)
SHARED_WRAPPER(dar, 64)
SHARED_WRAPPER_GET(msr, 64)
static inline void kvmppc_set_msr_fast(struct kvm_vcpu *vcpu, u64 val)
{
if (kvmppc_shared_big_endian(vcpu))
vcpu->arch.shared->msr = cpu_to_be64(val);
else
vcpu->arch.shared->msr = cpu_to_le64(val);
}
SHARED_WRAPPER(dsisr, 32)
SHARED_WRAPPER(int_pending, 32)
SHARED_WRAPPER(sprg4, 64)
SHARED_WRAPPER(sprg5, 64)
SHARED_WRAPPER(sprg6, 64)
SHARED_WRAPPER(sprg7, 64)
static inline u32 kvmppc_get_sr(struct kvm_vcpu *vcpu, int nr)
{
if (kvmppc_shared_big_endian(vcpu))
return be32_to_cpu(vcpu->arch.shared->sr[nr]);
else
return le32_to_cpu(vcpu->arch.shared->sr[nr]);
}
static inline void kvmppc_set_sr(struct kvm_vcpu *vcpu, int nr, u32 val)
{
if (kvmppc_shared_big_endian(vcpu))
vcpu->arch.shared->sr[nr] = cpu_to_be32(val);
else
vcpu->arch.shared->sr[nr] = cpu_to_le32(val);
}
/* /*
* Please call after prepare_to_enter. This function puts the lazy ee and irq * Please call after prepare_to_enter. This function puts the lazy ee and irq
* disabled tracking state back to normal mode, without actually enabling * disabled tracking state back to normal mode, without actually enabling
...@@ -485,7 +563,7 @@ static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb) ...@@ -485,7 +563,7 @@ static inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
msr_64bit = MSR_SF; msr_64bit = MSR_SF;
#endif #endif
if (!(vcpu->arch.shared->msr & msr_64bit)) if (!(kvmppc_get_msr(vcpu) & msr_64bit))
ea = (uint32_t)ea; ea = (uint32_t)ea;
return ea; return ea;
......
...@@ -670,18 +670,20 @@ ...@@ -670,18 +670,20 @@
#define MMCR0_PROBLEM_DISABLE MMCR0_FCP #define MMCR0_PROBLEM_DISABLE MMCR0_FCP
#define MMCR0_FCM1 0x10000000UL /* freeze counters while MSR mark = 1 */ #define MMCR0_FCM1 0x10000000UL /* freeze counters while MSR mark = 1 */
#define MMCR0_FCM0 0x08000000UL /* freeze counters while MSR mark = 0 */ #define MMCR0_FCM0 0x08000000UL /* freeze counters while MSR mark = 0 */
#define MMCR0_PMXE 0x04000000UL /* performance monitor exception enable */ #define MMCR0_PMXE ASM_CONST(0x04000000) /* perf mon exception enable */
#define MMCR0_FCECE 0x02000000UL /* freeze ctrs on enabled cond or event */ #define MMCR0_FCECE ASM_CONST(0x02000000) /* freeze ctrs on enabled cond or event */
#define MMCR0_TBEE 0x00400000UL /* time base exception enable */ #define MMCR0_TBEE 0x00400000UL /* time base exception enable */
#define MMCR0_BHRBA 0x00200000UL /* BHRB Access allowed in userspace */ #define MMCR0_BHRBA 0x00200000UL /* BHRB Access allowed in userspace */
#define MMCR0_EBE 0x00100000UL /* Event based branch enable */ #define MMCR0_EBE 0x00100000UL /* Event based branch enable */
#define MMCR0_PMCC 0x000c0000UL /* PMC control */ #define MMCR0_PMCC 0x000c0000UL /* PMC control */
#define MMCR0_PMCC_U6 0x00080000UL /* PMC1-6 are R/W by user (PR) */ #define MMCR0_PMCC_U6 0x00080000UL /* PMC1-6 are R/W by user (PR) */
#define MMCR0_PMC1CE 0x00008000UL /* PMC1 count enable*/ #define MMCR0_PMC1CE 0x00008000UL /* PMC1 count enable*/
#define MMCR0_PMCjCE 0x00004000UL /* PMCj count enable*/ #define MMCR0_PMCjCE ASM_CONST(0x00004000) /* PMCj count enable*/
#define MMCR0_TRIGGER 0x00002000UL /* TRIGGER enable */ #define MMCR0_TRIGGER 0x00002000UL /* TRIGGER enable */
#define MMCR0_PMAO_SYNC 0x00000800UL /* PMU interrupt is synchronous */ #define MMCR0_PMAO_SYNC ASM_CONST(0x00000800) /* PMU intr is synchronous */
#define MMCR0_PMAO 0x00000080UL /* performance monitor alert has occurred, set to 0 after handling exception */ #define MMCR0_C56RUN ASM_CONST(0x00000100) /* PMC5/6 count when RUN=0 */
/* performance monitor alert has occurred, set to 0 after handling exception */
#define MMCR0_PMAO ASM_CONST(0x00000080)
#define MMCR0_SHRFC 0x00000040UL /* SHRre freeze conditions between threads */ #define MMCR0_SHRFC 0x00000040UL /* SHRre freeze conditions between threads */
#define MMCR0_FC56 0x00000010UL /* freeze counters 5 and 6 */ #define MMCR0_FC56 0x00000010UL /* freeze counters 5 and 6 */
#define MMCR0_FCTI 0x00000008UL /* freeze counters in tags inactive mode */ #define MMCR0_FCTI 0x00000008UL /* freeze counters in tags inactive mode */
......
...@@ -583,6 +583,7 @@ ...@@ -583,6 +583,7 @@
/* Bit definitions for L1CSR0. */ /* Bit definitions for L1CSR0. */
#define L1CSR0_CPE 0x00010000 /* Data Cache Parity Enable */ #define L1CSR0_CPE 0x00010000 /* Data Cache Parity Enable */
#define L1CSR0_CUL 0x00000400 /* Data Cache Unable to Lock */
#define L1CSR0_CLFC 0x00000100 /* Cache Lock Bits Flash Clear */ #define L1CSR0_CLFC 0x00000100 /* Cache Lock Bits Flash Clear */
#define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */ #define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */
#define L1CSR0_CFI 0x00000002 /* Cache Flash Invalidate */ #define L1CSR0_CFI 0x00000002 /* Cache Flash Invalidate */
......
...@@ -545,7 +545,6 @@ struct kvm_get_htab_header { ...@@ -545,7 +545,6 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_TCSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb1) #define KVM_REG_PPC_TCSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb1)
#define KVM_REG_PPC_PID (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb2) #define KVM_REG_PPC_PID (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb2)
#define KVM_REG_PPC_ACOP (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb3) #define KVM_REG_PPC_ACOP (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb3)
#define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb4)
#define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4) #define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4)
#define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5) #define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
...@@ -555,6 +554,7 @@ struct kvm_get_htab_header { ...@@ -555,6 +554,7 @@ struct kvm_get_htab_header {
#define KVM_REG_PPC_ARCH_COMPAT (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb7) #define KVM_REG_PPC_ARCH_COMPAT (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb7)
#define KVM_REG_PPC_DABRX (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8) #define KVM_REG_PPC_DABRX (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8)
#define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb9)
/* Transactional Memory checkpointed state: /* Transactional Memory checkpointed state:
* This is all GPRs, all VSX regs and a subset of SPRs * This is all GPRs, all VSX regs and a subset of SPRs
......
...@@ -82,10 +82,16 @@ struct kvm_vcpu_arch_shared { ...@@ -82,10 +82,16 @@ struct kvm_vcpu_arch_shared {
#define KVM_FEATURE_MAGIC_PAGE 1 #define KVM_FEATURE_MAGIC_PAGE 1
/* Magic page flags from host to guest */
#define KVM_MAGIC_FEAT_SR (1 << 0) #define KVM_MAGIC_FEAT_SR (1 << 0)
/* MASn, ESR, PIR, and high SPRGs */ /* MASn, ESR, PIR, and high SPRGs */
#define KVM_MAGIC_FEAT_MAS0_TO_SPRG7 (1 << 1) #define KVM_MAGIC_FEAT_MAS0_TO_SPRG7 (1 << 1)
/* Magic page flags from guest to host */
#define MAGIC_PAGE_FLAG_NOT_MAPPED_NX (1 << 0)
#endif /* _UAPI__POWERPC_KVM_PARA_H__ */ #endif /* _UAPI__POWERPC_KVM_PARA_H__ */
...@@ -25,14 +25,13 @@ ...@@ -25,14 +25,13 @@
#include <asm/cputable.h> #include <asm/cputable.h>
#include <asm/emulated_ops.h> #include <asm/emulated_ops.h>
#include <asm/switch_to.h> #include <asm/switch_to.h>
#include <asm/disassemble.h>
struct aligninfo { struct aligninfo {
unsigned char len; unsigned char len;
unsigned char flags; unsigned char flags;
}; };
#define IS_XFORM(inst) (((inst) >> 26) == 31)
#define IS_DSFORM(inst) (((inst) >> 26) >= 56)
#define INVALID { 0, 0 } #define INVALID { 0, 0 }
...@@ -191,37 +190,6 @@ static struct aligninfo aligninfo[128] = { ...@@ -191,37 +190,6 @@ static struct aligninfo aligninfo[128] = {
INVALID, /* 11 1 1111 */ INVALID, /* 11 1 1111 */
}; };
/*
* Create a DSISR value from the instruction
*/
static inline unsigned make_dsisr(unsigned instr)
{
unsigned dsisr;
/* bits 6:15 --> 22:31 */
dsisr = (instr & 0x03ff0000) >> 16;
if (IS_XFORM(instr)) {
/* bits 29:30 --> 15:16 */
dsisr |= (instr & 0x00000006) << 14;
/* bit 25 --> 17 */
dsisr |= (instr & 0x00000040) << 8;
/* bits 21:24 --> 18:21 */
dsisr |= (instr & 0x00000780) << 3;
} else {
/* bit 5 --> 17 */
dsisr |= (instr & 0x04000000) >> 12;
/* bits 1: 4 --> 18:21 */
dsisr |= (instr & 0x78000000) >> 17;
/* bits 30:31 --> 12:13 */
if (IS_DSFORM(instr))
dsisr |= (instr & 0x00000003) << 18;
}
return dsisr;
}
/* /*
* The dcbz (data cache block zero) instruction * The dcbz (data cache block zero) instruction
* gives an alignment fault if used on non-cacheable * gives an alignment fault if used on non-cacheable
......
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
#endif #endif
#if defined(CONFIG_KVM) && defined(CONFIG_PPC_BOOK3S) #if defined(CONFIG_KVM) && defined(CONFIG_PPC_BOOK3S)
#include <asm/kvm_book3s.h> #include <asm/kvm_book3s.h>
#include <asm/kvm_ppc.h>
#endif #endif
#ifdef CONFIG_PPC32 #ifdef CONFIG_PPC32
...@@ -445,7 +446,9 @@ int main(void) ...@@ -445,7 +446,9 @@ int main(void)
DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer)); DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer));
DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr)); DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr));
DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr)); DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
#ifdef CONFIG_PPC_BOOK3S
DEFINE(VCPU_TAR, offsetof(struct kvm_vcpu, arch.tar)); DEFINE(VCPU_TAR, offsetof(struct kvm_vcpu, arch.tar));
#endif
DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr)); DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc)); DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc));
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
...@@ -467,6 +470,9 @@ int main(void) ...@@ -467,6 +470,9 @@ int main(void)
DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared)); DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared));
DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr)); DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr));
DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr)); DEFINE(VCPU_SHADOW_MSR, offsetof(struct kvm_vcpu, arch.shadow_msr));
#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
DEFINE(VCPU_SHAREDBE, offsetof(struct kvm_vcpu, arch.shared_big_endian));
#endif
DEFINE(VCPU_SHARED_MAS0, offsetof(struct kvm_vcpu_arch_shared, mas0)); DEFINE(VCPU_SHARED_MAS0, offsetof(struct kvm_vcpu_arch_shared, mas0));
DEFINE(VCPU_SHARED_MAS1, offsetof(struct kvm_vcpu_arch_shared, mas1)); DEFINE(VCPU_SHARED_MAS1, offsetof(struct kvm_vcpu_arch_shared, mas1));
...@@ -493,7 +499,6 @@ int main(void) ...@@ -493,7 +499,6 @@ int main(void)
DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar)); DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa.pinned_addr)); DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa.pinned_addr));
DEFINE(VCPU_VPA_DIRTY, offsetof(struct kvm_vcpu, arch.vpa.dirty)); DEFINE(VCPU_VPA_DIRTY, offsetof(struct kvm_vcpu, arch.vpa.dirty));
DEFINE(VCPU_INTR_MSR, offsetof(struct kvm_vcpu, arch.intr_msr));
#endif #endif
#ifdef CONFIG_PPC_BOOK3S #ifdef CONFIG_PPC_BOOK3S
DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id)); DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
...@@ -528,11 +533,13 @@ int main(void) ...@@ -528,11 +533,13 @@ int main(void)
DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr)); DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr));
DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr)); DEFINE(VCPU_FAULT_DSISR, offsetof(struct kvm_vcpu, arch.fault_dsisr));
DEFINE(VCPU_FAULT_DAR, offsetof(struct kvm_vcpu, arch.fault_dar)); DEFINE(VCPU_FAULT_DAR, offsetof(struct kvm_vcpu, arch.fault_dar));
DEFINE(VCPU_INTR_MSR, offsetof(struct kvm_vcpu, arch.intr_msr));
DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst));
DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap)); DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap));
DEFINE(VCPU_CFAR, offsetof(struct kvm_vcpu, arch.cfar)); DEFINE(VCPU_CFAR, offsetof(struct kvm_vcpu, arch.cfar));
DEFINE(VCPU_PPR, offsetof(struct kvm_vcpu, arch.ppr)); DEFINE(VCPU_PPR, offsetof(struct kvm_vcpu, arch.ppr));
DEFINE(VCPU_FSCR, offsetof(struct kvm_vcpu, arch.fscr)); DEFINE(VCPU_FSCR, offsetof(struct kvm_vcpu, arch.fscr));
DEFINE(VCPU_SHADOW_FSCR, offsetof(struct kvm_vcpu, arch.shadow_fscr));
DEFINE(VCPU_PSPB, offsetof(struct kvm_vcpu, arch.pspb)); DEFINE(VCPU_PSPB, offsetof(struct kvm_vcpu, arch.pspb));
DEFINE(VCPU_EBBHR, offsetof(struct kvm_vcpu, arch.ebbhr)); DEFINE(VCPU_EBBHR, offsetof(struct kvm_vcpu, arch.ebbhr));
DEFINE(VCPU_EBBRR, offsetof(struct kvm_vcpu, arch.ebbrr)); DEFINE(VCPU_EBBRR, offsetof(struct kvm_vcpu, arch.ebbrr));
...@@ -614,6 +621,7 @@ int main(void) ...@@ -614,6 +621,7 @@ int main(void)
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
SVCPU_FIELD(SVCPU_SLB, slb); SVCPU_FIELD(SVCPU_SLB, slb);
SVCPU_FIELD(SVCPU_SLB_MAX, slb_max); SVCPU_FIELD(SVCPU_SLB_MAX, slb_max);
SVCPU_FIELD(SVCPU_SHADOW_FSCR, shadow_fscr);
#endif #endif
HSTATE_FIELD(HSTATE_HOST_R1, host_r1); HSTATE_FIELD(HSTATE_HOST_R1, host_r1);
...@@ -649,6 +657,7 @@ int main(void) ...@@ -649,6 +657,7 @@ int main(void)
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
HSTATE_FIELD(HSTATE_CFAR, cfar); HSTATE_FIELD(HSTATE_CFAR, cfar);
HSTATE_FIELD(HSTATE_PPR, ppr); HSTATE_FIELD(HSTATE_PPR, ppr);
HSTATE_FIELD(HSTATE_HOST_FSCR, host_fscr);
#endif /* CONFIG_PPC_BOOK3S_64 */ #endif /* CONFIG_PPC_BOOK3S_64 */
#else /* CONFIG_PPC_BOOK3S */ #else /* CONFIG_PPC_BOOK3S */
......
...@@ -47,9 +47,10 @@ static int __init early_init_dt_scan_epapr(unsigned long node, ...@@ -47,9 +47,10 @@ static int __init early_init_dt_scan_epapr(unsigned long node,
return -1; return -1;
for (i = 0; i < (len / 4); i++) { for (i = 0; i < (len / 4); i++) {
patch_instruction(epapr_hypercall_start + i, insts[i]); u32 inst = be32_to_cpu(insts[i]);
patch_instruction(epapr_hypercall_start + i, inst);
#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64) #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
patch_instruction(epapr_ev_idle_start + i, insts[i]); patch_instruction(epapr_ev_idle_start + i, inst);
#endif #endif
} }
......
...@@ -417,7 +417,7 @@ static void kvm_map_magic_page(void *data) ...@@ -417,7 +417,7 @@ static void kvm_map_magic_page(void *data)
ulong out[8]; ulong out[8];
in[0] = KVM_MAGIC_PAGE; in[0] = KVM_MAGIC_PAGE;
in[1] = KVM_MAGIC_PAGE; in[1] = KVM_MAGIC_PAGE | MAGIC_PAGE_FLAG_NOT_MAPPED_NX;
epapr_hypercall(in, out, KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE)); epapr_hypercall(in, out, KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE));
......
...@@ -98,6 +98,9 @@ static inline void free_lppacas(void) { } ...@@ -98,6 +98,9 @@ static inline void free_lppacas(void) { }
/* /*
* 3 persistent SLBs are registered here. The buffer will be zero * 3 persistent SLBs are registered here. The buffer will be zero
* initially, hence will all be invaild until we actually write them. * initially, hence will all be invaild until we actually write them.
*
* If you make the number of persistent SLB entries dynamic, please also
* update PR KVM to flush and restore them accordingly.
*/ */
static struct slb_shadow *slb_shadow; static struct slb_shadow *slb_shadow;
......
...@@ -6,7 +6,6 @@ source "virt/kvm/Kconfig" ...@@ -6,7 +6,6 @@ source "virt/kvm/Kconfig"
menuconfig VIRTUALIZATION menuconfig VIRTUALIZATION
bool "Virtualization" bool "Virtualization"
depends on !CPU_LITTLE_ENDIAN
---help--- ---help---
Say Y here to get to see options for using your Linux host to run Say Y here to get to see options for using your Linux host to run
other operating systems inside virtual machines (guests). other operating systems inside virtual machines (guests).
...@@ -76,6 +75,7 @@ config KVM_BOOK3S_64 ...@@ -76,6 +75,7 @@ config KVM_BOOK3S_64
config KVM_BOOK3S_64_HV config KVM_BOOK3S_64_HV
tristate "KVM support for POWER7 and PPC970 using hypervisor mode in host" tristate "KVM support for POWER7 and PPC970 using hypervisor mode in host"
depends on KVM_BOOK3S_64 depends on KVM_BOOK3S_64
depends on !CPU_LITTLE_ENDIAN
select KVM_BOOK3S_HV_POSSIBLE select KVM_BOOK3S_HV_POSSIBLE
select MMU_NOTIFIER select MMU_NOTIFIER
select CMA select CMA
......
...@@ -85,9 +85,9 @@ static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu, ...@@ -85,9 +85,9 @@ static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu,
if (is_kvmppc_hv_enabled(vcpu->kvm)) if (is_kvmppc_hv_enabled(vcpu->kvm))
return; return;
if (pending_now) if (pending_now)
vcpu->arch.shared->int_pending = 1; kvmppc_set_int_pending(vcpu, 1);
else if (old_pending) else if (old_pending)
vcpu->arch.shared->int_pending = 0; kvmppc_set_int_pending(vcpu, 0);
} }
static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu) static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
...@@ -99,11 +99,11 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu) ...@@ -99,11 +99,11 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
if (is_kvmppc_hv_enabled(vcpu->kvm)) if (is_kvmppc_hv_enabled(vcpu->kvm))
return false; return false;
crit_raw = vcpu->arch.shared->critical; crit_raw = kvmppc_get_critical(vcpu);
crit_r1 = kvmppc_get_gpr(vcpu, 1); crit_r1 = kvmppc_get_gpr(vcpu, 1);
/* Truncate crit indicators in 32 bit mode */ /* Truncate crit indicators in 32 bit mode */
if (!(vcpu->arch.shared->msr & MSR_SF)) { if (!(kvmppc_get_msr(vcpu) & MSR_SF)) {
crit_raw &= 0xffffffff; crit_raw &= 0xffffffff;
crit_r1 &= 0xffffffff; crit_r1 &= 0xffffffff;
} }
...@@ -111,15 +111,15 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu) ...@@ -111,15 +111,15 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu)
/* Critical section when crit == r1 */ /* Critical section when crit == r1 */
crit = (crit_raw == crit_r1); crit = (crit_raw == crit_r1);
/* ... and we're in supervisor mode */ /* ... and we're in supervisor mode */
crit = crit && !(vcpu->arch.shared->msr & MSR_PR); crit = crit && !(kvmppc_get_msr(vcpu) & MSR_PR);
return crit; return crit;
} }
void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags) void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
{ {
vcpu->arch.shared->srr0 = kvmppc_get_pc(vcpu); kvmppc_set_srr0(vcpu, kvmppc_get_pc(vcpu));
vcpu->arch.shared->srr1 = vcpu->arch.shared->msr | flags; kvmppc_set_srr1(vcpu, kvmppc_get_msr(vcpu) | flags);
kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec); kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec);
vcpu->arch.mmu.reset_msr(vcpu); vcpu->arch.mmu.reset_msr(vcpu);
} }
...@@ -145,6 +145,7 @@ static int kvmppc_book3s_vec2irqprio(unsigned int vec) ...@@ -145,6 +145,7 @@ static int kvmppc_book3s_vec2irqprio(unsigned int vec)
case 0xd00: prio = BOOK3S_IRQPRIO_DEBUG; break; case 0xd00: prio = BOOK3S_IRQPRIO_DEBUG; break;
case 0xf20: prio = BOOK3S_IRQPRIO_ALTIVEC; break; case 0xf20: prio = BOOK3S_IRQPRIO_ALTIVEC; break;
case 0xf40: prio = BOOK3S_IRQPRIO_VSX; break; case 0xf40: prio = BOOK3S_IRQPRIO_VSX; break;
case 0xf60: prio = BOOK3S_IRQPRIO_FAC_UNAVAIL; break;
default: prio = BOOK3S_IRQPRIO_MAX; break; default: prio = BOOK3S_IRQPRIO_MAX; break;
} }
...@@ -225,12 +226,12 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) ...@@ -225,12 +226,12 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
switch (priority) { switch (priority) {
case BOOK3S_IRQPRIO_DECREMENTER: case BOOK3S_IRQPRIO_DECREMENTER:
deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit; deliver = (kvmppc_get_msr(vcpu) & MSR_EE) && !crit;
vec = BOOK3S_INTERRUPT_DECREMENTER; vec = BOOK3S_INTERRUPT_DECREMENTER;
break; break;
case BOOK3S_IRQPRIO_EXTERNAL: case BOOK3S_IRQPRIO_EXTERNAL:
case BOOK3S_IRQPRIO_EXTERNAL_LEVEL: case BOOK3S_IRQPRIO_EXTERNAL_LEVEL:
deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit; deliver = (kvmppc_get_msr(vcpu) & MSR_EE) && !crit;
vec = BOOK3S_INTERRUPT_EXTERNAL; vec = BOOK3S_INTERRUPT_EXTERNAL;
break; break;
case BOOK3S_IRQPRIO_SYSTEM_RESET: case BOOK3S_IRQPRIO_SYSTEM_RESET:
...@@ -275,6 +276,9 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) ...@@ -275,6 +276,9 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
case BOOK3S_IRQPRIO_PERFORMANCE_MONITOR: case BOOK3S_IRQPRIO_PERFORMANCE_MONITOR:
vec = BOOK3S_INTERRUPT_PERFMON; vec = BOOK3S_INTERRUPT_PERFMON;
break; break;
case BOOK3S_IRQPRIO_FAC_UNAVAIL:
vec = BOOK3S_INTERRUPT_FAC_UNAVAIL;
break;
default: default:
deliver = 0; deliver = 0;
printk(KERN_ERR "KVM: Unknown interrupt: 0x%x\n", priority); printk(KERN_ERR "KVM: Unknown interrupt: 0x%x\n", priority);
...@@ -343,7 +347,7 @@ pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing, ...@@ -343,7 +347,7 @@ pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing,
{ {
ulong mp_pa = vcpu->arch.magic_page_pa; ulong mp_pa = vcpu->arch.magic_page_pa;
if (!(vcpu->arch.shared->msr & MSR_SF)) if (!(kvmppc_get_msr(vcpu) & MSR_SF))
mp_pa = (uint32_t)mp_pa; mp_pa = (uint32_t)mp_pa;
/* Magic page override */ /* Magic page override */
...@@ -367,7 +371,7 @@ EXPORT_SYMBOL_GPL(kvmppc_gfn_to_pfn); ...@@ -367,7 +371,7 @@ EXPORT_SYMBOL_GPL(kvmppc_gfn_to_pfn);
static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data, static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
bool iswrite, struct kvmppc_pte *pte) bool iswrite, struct kvmppc_pte *pte)
{ {
int relocated = (vcpu->arch.shared->msr & (data ? MSR_DR : MSR_IR)); int relocated = (kvmppc_get_msr(vcpu) & (data ? MSR_DR : MSR_IR));
int r; int r;
if (relocated) { if (relocated) {
...@@ -498,18 +502,18 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) ...@@ -498,18 +502,18 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->ctr = kvmppc_get_ctr(vcpu); regs->ctr = kvmppc_get_ctr(vcpu);
regs->lr = kvmppc_get_lr(vcpu); regs->lr = kvmppc_get_lr(vcpu);
regs->xer = kvmppc_get_xer(vcpu); regs->xer = kvmppc_get_xer(vcpu);
regs->msr = vcpu->arch.shared->msr; regs->msr = kvmppc_get_msr(vcpu);
regs->srr0 = vcpu->arch.shared->srr0; regs->srr0 = kvmppc_get_srr0(vcpu);
regs->srr1 = vcpu->arch.shared->srr1; regs->srr1 = kvmppc_get_srr1(vcpu);
regs->pid = vcpu->arch.pid; regs->pid = vcpu->arch.pid;
regs->sprg0 = vcpu->arch.shared->sprg0; regs->sprg0 = kvmppc_get_sprg0(vcpu);
regs->sprg1 = vcpu->arch.shared->sprg1; regs->sprg1 = kvmppc_get_sprg1(vcpu);
regs->sprg2 = vcpu->arch.shared->sprg2; regs->sprg2 = kvmppc_get_sprg2(vcpu);
regs->sprg3 = vcpu->arch.shared->sprg3; regs->sprg3 = kvmppc_get_sprg3(vcpu);
regs->sprg4 = vcpu->arch.shared->sprg4; regs->sprg4 = kvmppc_get_sprg4(vcpu);
regs->sprg5 = vcpu->arch.shared->sprg5; regs->sprg5 = kvmppc_get_sprg5(vcpu);
regs->sprg6 = vcpu->arch.shared->sprg6; regs->sprg6 = kvmppc_get_sprg6(vcpu);
regs->sprg7 = vcpu->arch.shared->sprg7; regs->sprg7 = kvmppc_get_sprg7(vcpu);
for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
regs->gpr[i] = kvmppc_get_gpr(vcpu, i); regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
...@@ -527,16 +531,16 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) ...@@ -527,16 +531,16 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
kvmppc_set_lr(vcpu, regs->lr); kvmppc_set_lr(vcpu, regs->lr);
kvmppc_set_xer(vcpu, regs->xer); kvmppc_set_xer(vcpu, regs->xer);
kvmppc_set_msr(vcpu, regs->msr); kvmppc_set_msr(vcpu, regs->msr);
vcpu->arch.shared->srr0 = regs->srr0; kvmppc_set_srr0(vcpu, regs->srr0);
vcpu->arch.shared->srr1 = regs->srr1; kvmppc_set_srr1(vcpu, regs->srr1);
vcpu->arch.shared->sprg0 = regs->sprg0; kvmppc_set_sprg0(vcpu, regs->sprg0);
vcpu->arch.shared->sprg1 = regs->sprg1; kvmppc_set_sprg1(vcpu, regs->sprg1);
vcpu->arch.shared->sprg2 = regs->sprg2; kvmppc_set_sprg2(vcpu, regs->sprg2);
vcpu->arch.shared->sprg3 = regs->sprg3; kvmppc_set_sprg3(vcpu, regs->sprg3);
vcpu->arch.shared->sprg4 = regs->sprg4; kvmppc_set_sprg4(vcpu, regs->sprg4);
vcpu->arch.shared->sprg5 = regs->sprg5; kvmppc_set_sprg5(vcpu, regs->sprg5);
vcpu->arch.shared->sprg6 = regs->sprg6; kvmppc_set_sprg6(vcpu, regs->sprg6);
vcpu->arch.shared->sprg7 = regs->sprg7; kvmppc_set_sprg7(vcpu, regs->sprg7);
for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
kvmppc_set_gpr(vcpu, i, regs->gpr[i]); kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
...@@ -570,10 +574,10 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) ...@@ -570,10 +574,10 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
r = 0; r = 0;
switch (reg->id) { switch (reg->id) {
case KVM_REG_PPC_DAR: case KVM_REG_PPC_DAR:
val = get_reg_val(reg->id, vcpu->arch.shared->dar); val = get_reg_val(reg->id, kvmppc_get_dar(vcpu));
break; break;
case KVM_REG_PPC_DSISR: case KVM_REG_PPC_DSISR:
val = get_reg_val(reg->id, vcpu->arch.shared->dsisr); val = get_reg_val(reg->id, kvmppc_get_dsisr(vcpu));
break; break;
case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
i = reg->id - KVM_REG_PPC_FPR0; i = reg->id - KVM_REG_PPC_FPR0;
...@@ -627,6 +631,21 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) ...@@ -627,6 +631,21 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
val = get_reg_val(reg->id, kvmppc_xics_get_icp(vcpu)); val = get_reg_val(reg->id, kvmppc_xics_get_icp(vcpu));
break; break;
#endif /* CONFIG_KVM_XICS */ #endif /* CONFIG_KVM_XICS */
case KVM_REG_PPC_FSCR:
val = get_reg_val(reg->id, vcpu->arch.fscr);
break;
case KVM_REG_PPC_TAR:
val = get_reg_val(reg->id, vcpu->arch.tar);
break;
case KVM_REG_PPC_EBBHR:
val = get_reg_val(reg->id, vcpu->arch.ebbhr);
break;
case KVM_REG_PPC_EBBRR:
val = get_reg_val(reg->id, vcpu->arch.ebbrr);
break;
case KVM_REG_PPC_BESCR:
val = get_reg_val(reg->id, vcpu->arch.bescr);
break;
default: default:
r = -EINVAL; r = -EINVAL;
break; break;
...@@ -660,10 +679,10 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) ...@@ -660,10 +679,10 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
r = 0; r = 0;
switch (reg->id) { switch (reg->id) {
case KVM_REG_PPC_DAR: case KVM_REG_PPC_DAR:
vcpu->arch.shared->dar = set_reg_val(reg->id, val); kvmppc_set_dar(vcpu, set_reg_val(reg->id, val));
break; break;
case KVM_REG_PPC_DSISR: case KVM_REG_PPC_DSISR:
vcpu->arch.shared->dsisr = set_reg_val(reg->id, val); kvmppc_set_dsisr(vcpu, set_reg_val(reg->id, val));
break; break;
case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
i = reg->id - KVM_REG_PPC_FPR0; i = reg->id - KVM_REG_PPC_FPR0;
...@@ -716,6 +735,21 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) ...@@ -716,6 +735,21 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
set_reg_val(reg->id, val)); set_reg_val(reg->id, val));
break; break;
#endif /* CONFIG_KVM_XICS */ #endif /* CONFIG_KVM_XICS */
case KVM_REG_PPC_FSCR:
vcpu->arch.fscr = set_reg_val(reg->id, val);
break;
case KVM_REG_PPC_TAR:
vcpu->arch.tar = set_reg_val(reg->id, val);
break;
case KVM_REG_PPC_EBBHR:
vcpu->arch.ebbhr = set_reg_val(reg->id, val);
break;
case KVM_REG_PPC_EBBRR:
vcpu->arch.ebbrr = set_reg_val(reg->id, val);
break;
case KVM_REG_PPC_BESCR:
vcpu->arch.bescr = set_reg_val(reg->id, val);
break;
default: default:
r = -EINVAL; r = -EINVAL;
break; break;
......
...@@ -91,7 +91,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, ...@@ -91,7 +91,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
static u32 find_sr(struct kvm_vcpu *vcpu, gva_t eaddr) static u32 find_sr(struct kvm_vcpu *vcpu, gva_t eaddr)
{ {
return vcpu->arch.shared->sr[(eaddr >> 28) & 0xf]; return kvmppc_get_sr(vcpu, (eaddr >> 28) & 0xf);
} }
static u64 kvmppc_mmu_book3s_32_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, static u64 kvmppc_mmu_book3s_32_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr,
...@@ -131,7 +131,7 @@ static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvm_vcpu *vcpu, ...@@ -131,7 +131,7 @@ static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvm_vcpu *vcpu,
pteg = (vcpu_book3s->sdr1 & 0xffff0000) | hash; pteg = (vcpu_book3s->sdr1 & 0xffff0000) | hash;
dprintk("MMU: pc=0x%lx eaddr=0x%lx sdr1=0x%llx pteg=0x%x vsid=0x%x\n", dprintk("MMU: pc=0x%lx eaddr=0x%lx sdr1=0x%llx pteg=0x%x vsid=0x%x\n",
kvmppc_get_pc(&vcpu_book3s->vcpu), eaddr, vcpu_book3s->sdr1, pteg, kvmppc_get_pc(vcpu), eaddr, vcpu_book3s->sdr1, pteg,
sr_vsid(sre)); sr_vsid(sre));
r = gfn_to_hva(vcpu->kvm, pteg >> PAGE_SHIFT); r = gfn_to_hva(vcpu->kvm, pteg >> PAGE_SHIFT);
...@@ -160,7 +160,7 @@ static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -160,7 +160,7 @@ static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr,
else else
bat = &vcpu_book3s->ibat[i]; bat = &vcpu_book3s->ibat[i];
if (vcpu->arch.shared->msr & MSR_PR) { if (kvmppc_get_msr(vcpu) & MSR_PR) {
if (!bat->vp) if (!bat->vp)
continue; continue;
} else { } else {
...@@ -208,6 +208,7 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -208,6 +208,7 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
u32 sre; u32 sre;
hva_t ptegp; hva_t ptegp;
u32 pteg[16]; u32 pteg[16];
u32 pte0, pte1;
u32 ptem = 0; u32 ptem = 0;
int i; int i;
int found = 0; int found = 0;
...@@ -233,14 +234,16 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -233,14 +234,16 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
} }
for (i=0; i<16; i+=2) { for (i=0; i<16; i+=2) {
if (ptem == pteg[i]) { pte0 = be32_to_cpu(pteg[i]);
pte1 = be32_to_cpu(pteg[i + 1]);
if (ptem == pte0) {
u8 pp; u8 pp;
pte->raddr = (pteg[i+1] & ~(0xFFFULL)) | (eaddr & 0xFFF); pte->raddr = (pte1 & ~(0xFFFULL)) | (eaddr & 0xFFF);
pp = pteg[i+1] & 3; pp = pte1 & 3;
if ((sr_kp(sre) && (vcpu->arch.shared->msr & MSR_PR)) || if ((sr_kp(sre) && (kvmppc_get_msr(vcpu) & MSR_PR)) ||
(sr_ks(sre) && !(vcpu->arch.shared->msr & MSR_PR))) (sr_ks(sre) && !(kvmppc_get_msr(vcpu) & MSR_PR)))
pp |= 4; pp |= 4;
pte->may_write = false; pte->may_write = false;
...@@ -260,7 +263,7 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -260,7 +263,7 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
} }
dprintk_pte("MMU: Found PTE -> %x %x - %x\n", dprintk_pte("MMU: Found PTE -> %x %x - %x\n",
pteg[i], pteg[i+1], pp); pte0, pte1, pp);
found = 1; found = 1;
break; break;
} }
...@@ -269,8 +272,8 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -269,8 +272,8 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
/* Update PTE C and A bits, so the guest's swapper knows we used the /* Update PTE C and A bits, so the guest's swapper knows we used the
page */ page */
if (found) { if (found) {
u32 pte_r = pteg[i+1]; u32 pte_r = pte1;
char __user *addr = (char __user *) &pteg[i+1]; char __user *addr = (char __user *) (ptegp + (i+1) * sizeof(u32));
/* /*
* Use single-byte writes to update the HPTE, to * Use single-byte writes to update the HPTE, to
...@@ -296,7 +299,8 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -296,7 +299,8 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr,
to_book3s(vcpu)->sdr1, ptegp); to_book3s(vcpu)->sdr1, ptegp);
for (i=0; i<16; i+=2) { for (i=0; i<16; i+=2) {
dprintk_pte(" %02d: 0x%x - 0x%x (0x%x)\n", dprintk_pte(" %02d: 0x%x - 0x%x (0x%x)\n",
i, pteg[i], pteg[i+1], ptem); i, be32_to_cpu(pteg[i]),
be32_to_cpu(pteg[i+1]), ptem);
} }
} }
...@@ -316,7 +320,7 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -316,7 +320,7 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
/* Magic page override */ /* Magic page override */
if (unlikely(mp_ea) && if (unlikely(mp_ea) &&
unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) && unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) &&
!(vcpu->arch.shared->msr & MSR_PR)) { !(kvmppc_get_msr(vcpu) & MSR_PR)) {
pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data); pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data);
pte->raddr = vcpu->arch.magic_page_pa | (pte->raddr & 0xfff); pte->raddr = vcpu->arch.magic_page_pa | (pte->raddr & 0xfff);
pte->raddr &= KVM_PAM; pte->raddr &= KVM_PAM;
...@@ -341,13 +345,13 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -341,13 +345,13 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
static u32 kvmppc_mmu_book3s_32_mfsrin(struct kvm_vcpu *vcpu, u32 srnum) static u32 kvmppc_mmu_book3s_32_mfsrin(struct kvm_vcpu *vcpu, u32 srnum)
{ {
return vcpu->arch.shared->sr[srnum]; return kvmppc_get_sr(vcpu, srnum);
} }
static void kvmppc_mmu_book3s_32_mtsrin(struct kvm_vcpu *vcpu, u32 srnum, static void kvmppc_mmu_book3s_32_mtsrin(struct kvm_vcpu *vcpu, u32 srnum,
ulong value) ulong value)
{ {
vcpu->arch.shared->sr[srnum] = value; kvmppc_set_sr(vcpu, srnum, value);
kvmppc_mmu_map_segment(vcpu, srnum << SID_SHIFT); kvmppc_mmu_map_segment(vcpu, srnum << SID_SHIFT);
} }
...@@ -367,8 +371,9 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, ...@@ -367,8 +371,9 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
ulong ea = esid << SID_SHIFT; ulong ea = esid << SID_SHIFT;
u32 sr; u32 sr;
u64 gvsid = esid; u64 gvsid = esid;
u64 msr = kvmppc_get_msr(vcpu);
if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { if (msr & (MSR_DR|MSR_IR)) {
sr = find_sr(vcpu, ea); sr = find_sr(vcpu, ea);
if (sr_valid(sr)) if (sr_valid(sr))
gvsid = sr_vsid(sr); gvsid = sr_vsid(sr);
...@@ -377,7 +382,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, ...@@ -377,7 +382,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
/* In case we only have one of MSR_IR or MSR_DR set, let's put /* In case we only have one of MSR_IR or MSR_DR set, let's put
that in the real-mode context (and hope RM doesn't access that in the real-mode context (and hope RM doesn't access
high memory) */ high memory) */
switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { switch (msr & (MSR_DR|MSR_IR)) {
case 0: case 0:
*vsid = VSID_REAL | esid; *vsid = VSID_REAL | esid;
break; break;
...@@ -397,7 +402,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, ...@@ -397,7 +402,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
BUG(); BUG();
} }
if (vcpu->arch.shared->msr & MSR_PR) if (msr & MSR_PR)
*vsid |= VSID_PR; *vsid |= VSID_PR;
return 0; return 0;
......
...@@ -92,7 +92,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid) ...@@ -92,7 +92,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
struct kvmppc_sid_map *map; struct kvmppc_sid_map *map;
u16 sid_map_mask; u16 sid_map_mask;
if (vcpu->arch.shared->msr & MSR_PR) if (kvmppc_get_msr(vcpu) & MSR_PR)
gvsid |= VSID_PR; gvsid |= VSID_PR;
sid_map_mask = kvmppc_sid_hash(vcpu, gvsid); sid_map_mask = kvmppc_sid_hash(vcpu, gvsid);
...@@ -279,7 +279,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) ...@@ -279,7 +279,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
u16 sid_map_mask; u16 sid_map_mask;
static int backwards_map = 0; static int backwards_map = 0;
if (vcpu->arch.shared->msr & MSR_PR) if (kvmppc_get_msr(vcpu) & MSR_PR)
gvsid |= VSID_PR; gvsid |= VSID_PR;
/* We might get collisions that trap in preceding order, so let's /* We might get collisions that trap in preceding order, so let's
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
static void kvmppc_mmu_book3s_64_reset_msr(struct kvm_vcpu *vcpu) static void kvmppc_mmu_book3s_64_reset_msr(struct kvm_vcpu *vcpu)
{ {
kvmppc_set_msr(vcpu, MSR_SF); kvmppc_set_msr(vcpu, vcpu->arch.intr_msr);
} }
static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe( static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
...@@ -226,7 +226,7 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -226,7 +226,7 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
/* Magic page override */ /* Magic page override */
if (unlikely(mp_ea) && if (unlikely(mp_ea) &&
unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) && unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) &&
!(vcpu->arch.shared->msr & MSR_PR)) { !(kvmppc_get_msr(vcpu) & MSR_PR)) {
gpte->eaddr = eaddr; gpte->eaddr = eaddr;
gpte->vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, eaddr, data); gpte->vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, eaddr, data);
gpte->raddr = vcpu->arch.magic_page_pa | (gpte->raddr & 0xfff); gpte->raddr = vcpu->arch.magic_page_pa | (gpte->raddr & 0xfff);
...@@ -269,18 +269,21 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -269,18 +269,21 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
goto no_page_found; goto no_page_found;
} }
if ((vcpu->arch.shared->msr & MSR_PR) && slbe->Kp) if ((kvmppc_get_msr(vcpu) & MSR_PR) && slbe->Kp)
key = 4; key = 4;
else if (!(vcpu->arch.shared->msr & MSR_PR) && slbe->Ks) else if (!(kvmppc_get_msr(vcpu) & MSR_PR) && slbe->Ks)
key = 4; key = 4;
for (i=0; i<16; i+=2) { for (i=0; i<16; i+=2) {
u64 pte0 = be64_to_cpu(pteg[i]);
u64 pte1 = be64_to_cpu(pteg[i + 1]);
/* Check all relevant fields of 1st dword */ /* Check all relevant fields of 1st dword */
if ((pteg[i] & v_mask) == v_val) { if ((pte0 & v_mask) == v_val) {
/* If large page bit is set, check pgsize encoding */ /* If large page bit is set, check pgsize encoding */
if (slbe->large && if (slbe->large &&
(vcpu->arch.hflags & BOOK3S_HFLAG_MULTI_PGSIZE)) { (vcpu->arch.hflags & BOOK3S_HFLAG_MULTI_PGSIZE)) {
pgsize = decode_pagesize(slbe, pteg[i+1]); pgsize = decode_pagesize(slbe, pte1);
if (pgsize < 0) if (pgsize < 0)
continue; continue;
} }
...@@ -297,8 +300,8 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -297,8 +300,8 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
goto do_second; goto do_second;
} }
v = pteg[i]; v = be64_to_cpu(pteg[i]);
r = pteg[i+1]; r = be64_to_cpu(pteg[i+1]);
pp = (r & HPTE_R_PP) | key; pp = (r & HPTE_R_PP) | key;
if (r & HPTE_R_PP0) if (r & HPTE_R_PP0)
pp |= 8; pp |= 8;
...@@ -310,6 +313,9 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -310,6 +313,9 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
gpte->raddr = (r & HPTE_R_RPN & ~eaddr_mask) | (eaddr & eaddr_mask); gpte->raddr = (r & HPTE_R_RPN & ~eaddr_mask) | (eaddr & eaddr_mask);
gpte->page_size = pgsize; gpte->page_size = pgsize;
gpte->may_execute = ((r & HPTE_R_N) ? false : true); gpte->may_execute = ((r & HPTE_R_N) ? false : true);
if (unlikely(vcpu->arch.disable_kernel_nx) &&
!(kvmppc_get_msr(vcpu) & MSR_PR))
gpte->may_execute = true;
gpte->may_read = false; gpte->may_read = false;
gpte->may_write = false; gpte->may_write = false;
...@@ -342,14 +348,14 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, ...@@ -342,14 +348,14 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
* non-PAPR platforms such as mac99, and this is * non-PAPR platforms such as mac99, and this is
* what real hardware does. * what real hardware does.
*/ */
char __user *addr = (char __user *) &pteg[i+1]; char __user *addr = (char __user *) (ptegp + (i + 1) * sizeof(u64));
r |= HPTE_R_R; r |= HPTE_R_R;
put_user(r >> 8, addr + 6); put_user(r >> 8, addr + 6);
} }
if (iswrite && gpte->may_write && !(r & HPTE_R_C)) { if (iswrite && gpte->may_write && !(r & HPTE_R_C)) {
/* Set the dirty flag */ /* Set the dirty flag */
/* Use a single byte write */ /* Use a single byte write */
char __user *addr = (char __user *) &pteg[i+1]; char __user *addr = (char __user *) (ptegp + (i + 1) * sizeof(u64));
r |= HPTE_R_C; r |= HPTE_R_C;
put_user(r, addr + 7); put_user(r, addr + 7);
} }
...@@ -479,7 +485,7 @@ static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu) ...@@ -479,7 +485,7 @@ static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu)
vcpu->arch.slb[i].origv = 0; vcpu->arch.slb[i].origv = 0;
} }
if (vcpu->arch.shared->msr & MSR_IR) { if (kvmppc_get_msr(vcpu) & MSR_IR) {
kvmppc_mmu_flush_segments(vcpu); kvmppc_mmu_flush_segments(vcpu);
kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
} }
...@@ -563,7 +569,7 @@ static int segment_contains_magic_page(struct kvm_vcpu *vcpu, ulong esid) ...@@ -563,7 +569,7 @@ static int segment_contains_magic_page(struct kvm_vcpu *vcpu, ulong esid)
{ {
ulong mp_ea = vcpu->arch.magic_page_ea; ulong mp_ea = vcpu->arch.magic_page_ea;
return mp_ea && !(vcpu->arch.shared->msr & MSR_PR) && return mp_ea && !(kvmppc_get_msr(vcpu) & MSR_PR) &&
(mp_ea >> SID_SHIFT) == esid; (mp_ea >> SID_SHIFT) == esid;
} }
#endif #endif
...@@ -576,8 +582,9 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, ...@@ -576,8 +582,9 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
u64 gvsid = esid; u64 gvsid = esid;
ulong mp_ea = vcpu->arch.magic_page_ea; ulong mp_ea = vcpu->arch.magic_page_ea;
int pagesize = MMU_PAGE_64K; int pagesize = MMU_PAGE_64K;
u64 msr = kvmppc_get_msr(vcpu);
if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { if (msr & (MSR_DR|MSR_IR)) {
slb = kvmppc_mmu_book3s_64_find_slbe(vcpu, ea); slb = kvmppc_mmu_book3s_64_find_slbe(vcpu, ea);
if (slb) { if (slb) {
gvsid = slb->vsid; gvsid = slb->vsid;
...@@ -590,7 +597,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, ...@@ -590,7 +597,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
} }
} }
switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { switch (msr & (MSR_DR|MSR_IR)) {
case 0: case 0:
gvsid = VSID_REAL | esid; gvsid = VSID_REAL | esid;
break; break;
...@@ -623,7 +630,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, ...@@ -623,7 +630,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
gvsid |= VSID_64K; gvsid |= VSID_64K;
#endif #endif
if (vcpu->arch.shared->msr & MSR_PR) if (kvmppc_get_msr(vcpu) & MSR_PR)
gvsid |= VSID_PR; gvsid |= VSID_PR;
*vsid = gvsid; *vsid = gvsid;
...@@ -633,7 +640,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, ...@@ -633,7 +640,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid,
/* Catch magic page case */ /* Catch magic page case */
if (unlikely(mp_ea) && if (unlikely(mp_ea) &&
unlikely(esid == (mp_ea >> SID_SHIFT)) && unlikely(esid == (mp_ea >> SID_SHIFT)) &&
!(vcpu->arch.shared->msr & MSR_PR)) { !(kvmppc_get_msr(vcpu) & MSR_PR)) {
*vsid = VSID_REAL | esid; *vsid = VSID_REAL | esid;
return 0; return 0;
} }
......
...@@ -58,7 +58,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid) ...@@ -58,7 +58,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
struct kvmppc_sid_map *map; struct kvmppc_sid_map *map;
u16 sid_map_mask; u16 sid_map_mask;
if (vcpu->arch.shared->msr & MSR_PR) if (kvmppc_get_msr(vcpu) & MSR_PR)
gvsid |= VSID_PR; gvsid |= VSID_PR;
sid_map_mask = kvmppc_sid_hash(vcpu, gvsid); sid_map_mask = kvmppc_sid_hash(vcpu, gvsid);
...@@ -230,7 +230,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) ...@@ -230,7 +230,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
u16 sid_map_mask; u16 sid_map_mask;
static int backwards_map = 0; static int backwards_map = 0;
if (vcpu->arch.shared->msr & MSR_PR) if (kvmppc_get_msr(vcpu) & MSR_PR)
gvsid |= VSID_PR; gvsid |= VSID_PR;
/* We might get collisions that trap in preceding order, so let's /* We might get collisions that trap in preceding order, so let's
...@@ -271,11 +271,8 @@ static int kvmppc_mmu_next_segment(struct kvm_vcpu *vcpu, ulong esid) ...@@ -271,11 +271,8 @@ static int kvmppc_mmu_next_segment(struct kvm_vcpu *vcpu, ulong esid)
int found_inval = -1; int found_inval = -1;
int r; int r;
if (!svcpu->slb_max)
svcpu->slb_max = 1;
/* Are we overwriting? */ /* Are we overwriting? */
for (i = 1; i < svcpu->slb_max; i++) { for (i = 0; i < svcpu->slb_max; i++) {
if (!(svcpu->slb[i].esid & SLB_ESID_V)) if (!(svcpu->slb[i].esid & SLB_ESID_V))
found_inval = i; found_inval = i;
else if ((svcpu->slb[i].esid & ESID_MASK) == esid) { else if ((svcpu->slb[i].esid & ESID_MASK) == esid) {
...@@ -285,7 +282,7 @@ static int kvmppc_mmu_next_segment(struct kvm_vcpu *vcpu, ulong esid) ...@@ -285,7 +282,7 @@ static int kvmppc_mmu_next_segment(struct kvm_vcpu *vcpu, ulong esid)
} }
/* Found a spare entry that was invalidated before */ /* Found a spare entry that was invalidated before */
if (found_inval > 0) { if (found_inval >= 0) {
r = found_inval; r = found_inval;
goto out; goto out;
} }
...@@ -359,7 +356,7 @@ void kvmppc_mmu_flush_segment(struct kvm_vcpu *vcpu, ulong ea, ulong seg_size) ...@@ -359,7 +356,7 @@ void kvmppc_mmu_flush_segment(struct kvm_vcpu *vcpu, ulong ea, ulong seg_size)
ulong seg_mask = -seg_size; ulong seg_mask = -seg_size;
int i; int i;
for (i = 1; i < svcpu->slb_max; i++) { for (i = 0; i < svcpu->slb_max; i++) {
if ((svcpu->slb[i].esid & SLB_ESID_V) && if ((svcpu->slb[i].esid & SLB_ESID_V) &&
(svcpu->slb[i].esid & seg_mask) == ea) { (svcpu->slb[i].esid & seg_mask) == ea) {
/* Invalidate this entry */ /* Invalidate this entry */
...@@ -373,7 +370,7 @@ void kvmppc_mmu_flush_segment(struct kvm_vcpu *vcpu, ulong ea, ulong seg_size) ...@@ -373,7 +370,7 @@ void kvmppc_mmu_flush_segment(struct kvm_vcpu *vcpu, ulong ea, ulong seg_size)
void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu) void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu)
{ {
struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
svcpu->slb_max = 1; svcpu->slb_max = 0;
svcpu->slb[0].esid = 0; svcpu->slb[0].esid = 0;
svcpu_put(svcpu); svcpu_put(svcpu);
} }
......
...@@ -52,7 +52,7 @@ static void kvmppc_rmap_reset(struct kvm *kvm); ...@@ -52,7 +52,7 @@ static void kvmppc_rmap_reset(struct kvm *kvm);
long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp) long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp)
{ {
unsigned long hpt; unsigned long hpt = 0;
struct revmap_entry *rev; struct revmap_entry *rev;
struct page *page = NULL; struct page *page = NULL;
long order = KVM_DEFAULT_HPT_ORDER; long order = KVM_DEFAULT_HPT_ORDER;
...@@ -64,22 +64,11 @@ long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp) ...@@ -64,22 +64,11 @@ long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp)
} }
kvm->arch.hpt_cma_alloc = 0; kvm->arch.hpt_cma_alloc = 0;
/* VM_BUG_ON(order < KVM_CMA_CHUNK_ORDER);
* try first to allocate it from the kernel page allocator. page = kvm_alloc_hpt(1 << (order - PAGE_SHIFT));
* We keep the CMA reserved for failed allocation. if (page) {
*/ hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
hpt = __get_free_pages(GFP_KERNEL | __GFP_ZERO | __GFP_REPEAT | kvm->arch.hpt_cma_alloc = 1;
__GFP_NOWARN, order - PAGE_SHIFT);
/* Next try to allocate from the preallocated pool */
if (!hpt) {
VM_BUG_ON(order < KVM_CMA_CHUNK_ORDER);
page = kvm_alloc_hpt(1 << (order - PAGE_SHIFT));
if (page) {
hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
kvm->arch.hpt_cma_alloc = 1;
} else
--order;
} }
/* Lastly try successively smaller sizes from the page allocator */ /* Lastly try successively smaller sizes from the page allocator */
...@@ -596,6 +585,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -596,6 +585,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
struct kvm *kvm = vcpu->kvm; struct kvm *kvm = vcpu->kvm;
unsigned long *hptep, hpte[3], r; unsigned long *hptep, hpte[3], r;
unsigned long mmu_seq, psize, pte_size; unsigned long mmu_seq, psize, pte_size;
unsigned long gpa_base, gfn_base;
unsigned long gpa, gfn, hva, pfn; unsigned long gpa, gfn, hva, pfn;
struct kvm_memory_slot *memslot; struct kvm_memory_slot *memslot;
unsigned long *rmap; unsigned long *rmap;
...@@ -634,7 +624,9 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -634,7 +624,9 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
/* Translate the logical address and get the page */ /* Translate the logical address and get the page */
psize = hpte_page_size(hpte[0], r); psize = hpte_page_size(hpte[0], r);
gpa = (r & HPTE_R_RPN & ~(psize - 1)) | (ea & (psize - 1)); gpa_base = r & HPTE_R_RPN & ~(psize - 1);
gfn_base = gpa_base >> PAGE_SHIFT;
gpa = gpa_base | (ea & (psize - 1));
gfn = gpa >> PAGE_SHIFT; gfn = gpa >> PAGE_SHIFT;
memslot = gfn_to_memslot(kvm, gfn); memslot = gfn_to_memslot(kvm, gfn);
...@@ -646,6 +638,13 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -646,6 +638,13 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (!kvm->arch.using_mmu_notifiers) if (!kvm->arch.using_mmu_notifiers)
return -EFAULT; /* should never get here */ return -EFAULT; /* should never get here */
/*
* This should never happen, because of the slot_is_aligned()
* check in kvmppc_do_h_enter().
*/
if (gfn_base < memslot->base_gfn)
return -EFAULT;
/* used to check for invalidations in progress */ /* used to check for invalidations in progress */
mmu_seq = kvm->mmu_notifier_seq; mmu_seq = kvm->mmu_notifier_seq;
smp_rmb(); smp_rmb();
...@@ -738,7 +737,8 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -738,7 +737,8 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
goto out_unlock; goto out_unlock;
hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID; hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
rmap = &memslot->arch.rmap[gfn - memslot->base_gfn]; /* Always put the HPTE in the rmap chain for the page base address */
rmap = &memslot->arch.rmap[gfn_base - memslot->base_gfn];
lock_rmap(rmap); lock_rmap(rmap);
/* Check if we might have been invalidated; let the guest retry if so */ /* Check if we might have been invalidated; let the guest retry if so */
...@@ -1060,22 +1060,33 @@ void kvm_set_spte_hva_hv(struct kvm *kvm, unsigned long hva, pte_t pte) ...@@ -1060,22 +1060,33 @@ void kvm_set_spte_hva_hv(struct kvm *kvm, unsigned long hva, pte_t pte)
kvm_handle_hva(kvm, hva, kvm_unmap_rmapp); kvm_handle_hva(kvm, hva, kvm_unmap_rmapp);
} }
static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp) static int vcpus_running(struct kvm *kvm)
{
return atomic_read(&kvm->arch.vcpus_running) != 0;
}
/*
* Returns the number of system pages that are dirty.
* This can be more than 1 if we find a huge-page HPTE.
*/
static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp)
{ {
struct revmap_entry *rev = kvm->arch.revmap; struct revmap_entry *rev = kvm->arch.revmap;
unsigned long head, i, j; unsigned long head, i, j;
unsigned long n;
unsigned long v, r;
unsigned long *hptep; unsigned long *hptep;
int ret = 0; int npages_dirty = 0;
retry: retry:
lock_rmap(rmapp); lock_rmap(rmapp);
if (*rmapp & KVMPPC_RMAP_CHANGED) { if (*rmapp & KVMPPC_RMAP_CHANGED) {
*rmapp &= ~KVMPPC_RMAP_CHANGED; *rmapp &= ~KVMPPC_RMAP_CHANGED;
ret = 1; npages_dirty = 1;
} }
if (!(*rmapp & KVMPPC_RMAP_PRESENT)) { if (!(*rmapp & KVMPPC_RMAP_PRESENT)) {
unlock_rmap(rmapp); unlock_rmap(rmapp);
return ret; return npages_dirty;
} }
i = head = *rmapp & KVMPPC_RMAP_INDEX; i = head = *rmapp & KVMPPC_RMAP_INDEX;
...@@ -1083,7 +1094,22 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp) ...@@ -1083,7 +1094,22 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp)
hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4)); hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4));
j = rev[i].forw; j = rev[i].forw;
if (!(hptep[1] & HPTE_R_C)) /*
* Checking the C (changed) bit here is racy since there
* is no guarantee about when the hardware writes it back.
* If the HPTE is not writable then it is stable since the
* page can't be written to, and we would have done a tlbie
* (which forces the hardware to complete any writeback)
* when making the HPTE read-only.
* If vcpus are running then this call is racy anyway
* since the page could get dirtied subsequently, so we
* expect there to be a further call which would pick up
* any delayed C bit writeback.
* Otherwise we need to do the tlbie even if C==0 in
* order to pick up any delayed writeback of C.
*/
if (!(hptep[1] & HPTE_R_C) &&
(!hpte_is_writable(hptep[1]) || vcpus_running(kvm)))
continue; continue;
if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) { if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
...@@ -1095,24 +1121,33 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp) ...@@ -1095,24 +1121,33 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp)
} }
/* Now check and modify the HPTE */ /* Now check and modify the HPTE */
if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_C)) { if (!(hptep[0] & HPTE_V_VALID))
/* need to make it temporarily absent to clear C */ continue;
hptep[0] |= HPTE_V_ABSENT;
kvmppc_invalidate_hpte(kvm, hptep, i); /* need to make it temporarily absent so C is stable */
hptep[1] &= ~HPTE_R_C; hptep[0] |= HPTE_V_ABSENT;
eieio(); kvmppc_invalidate_hpte(kvm, hptep, i);
hptep[0] = (hptep[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID; v = hptep[0];
r = hptep[1];
if (r & HPTE_R_C) {
hptep[1] = r & ~HPTE_R_C;
if (!(rev[i].guest_rpte & HPTE_R_C)) { if (!(rev[i].guest_rpte & HPTE_R_C)) {
rev[i].guest_rpte |= HPTE_R_C; rev[i].guest_rpte |= HPTE_R_C;
note_hpte_modification(kvm, &rev[i]); note_hpte_modification(kvm, &rev[i]);
} }
ret = 1; n = hpte_page_size(v, r);
n = (n + PAGE_SIZE - 1) >> PAGE_SHIFT;
if (n > npages_dirty)
npages_dirty = n;
eieio();
} }
hptep[0] &= ~HPTE_V_HVLOCK; v &= ~(HPTE_V_ABSENT | HPTE_V_HVLOCK);
v |= HPTE_V_VALID;
hptep[0] = v;
} while ((i = j) != head); } while ((i = j) != head);
unlock_rmap(rmapp); unlock_rmap(rmapp);
return ret; return npages_dirty;
} }
static void harvest_vpa_dirty(struct kvmppc_vpa *vpa, static void harvest_vpa_dirty(struct kvmppc_vpa *vpa,
...@@ -1136,15 +1171,22 @@ static void harvest_vpa_dirty(struct kvmppc_vpa *vpa, ...@@ -1136,15 +1171,22 @@ static void harvest_vpa_dirty(struct kvmppc_vpa *vpa,
long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot, long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot,
unsigned long *map) unsigned long *map)
{ {
unsigned long i; unsigned long i, j;
unsigned long *rmapp; unsigned long *rmapp;
struct kvm_vcpu *vcpu; struct kvm_vcpu *vcpu;
preempt_disable(); preempt_disable();
rmapp = memslot->arch.rmap; rmapp = memslot->arch.rmap;
for (i = 0; i < memslot->npages; ++i) { for (i = 0; i < memslot->npages; ++i) {
if (kvm_test_clear_dirty(kvm, rmapp) && map) int npages = kvm_test_clear_dirty_npages(kvm, rmapp);
__set_bit_le(i, map); /*
* Note that if npages > 0 then i must be a multiple of npages,
* since we always put huge-page HPTEs in the rmap chain
* corresponding to their page base address.
*/
if (npages && map)
for (j = i; npages; ++j, --npages)
__set_bit_le(j, map);
++rmapp; ++rmapp;
} }
......
...@@ -17,30 +17,9 @@ ...@@ -17,30 +17,9 @@
* Authors: Alexander Graf <agraf@suse.de> * Authors: Alexander Graf <agraf@suse.de>
*/ */
#ifdef __LITTLE_ENDIAN__ #define SHADOW_SLB_ENTRY_LEN 0x10
#error Need to fix SLB shadow accesses in little endian mode #define OFFSET_ESID(x) (SHADOW_SLB_ENTRY_LEN * x)
#endif #define OFFSET_VSID(x) ((SHADOW_SLB_ENTRY_LEN * x) + 8)
#define SHADOW_SLB_ESID(num) (SLBSHADOW_SAVEAREA + (num * 0x10))
#define SHADOW_SLB_VSID(num) (SLBSHADOW_SAVEAREA + (num * 0x10) + 0x8)
#define UNBOLT_SLB_ENTRY(num) \
ld r9, SHADOW_SLB_ESID(num)(r12); \
/* Invalid? Skip. */; \
rldicl. r0, r9, 37, 63; \
beq slb_entry_skip_ ## num; \
xoris r9, r9, SLB_ESID_V@h; \
std r9, SHADOW_SLB_ESID(num)(r12); \
slb_entry_skip_ ## num:
#define REBOLT_SLB_ENTRY(num) \
ld r10, SHADOW_SLB_ESID(num)(r11); \
cmpdi r10, 0; \
beq slb_exit_skip_ ## num; \
oris r10, r10, SLB_ESID_V@h; \
ld r9, SHADOW_SLB_VSID(num)(r11); \
slbmte r9, r10; \
std r10, SHADOW_SLB_ESID(num)(r11); \
slb_exit_skip_ ## num:
/****************************************************************************** /******************************************************************************
* * * *
...@@ -64,20 +43,15 @@ slb_exit_skip_ ## num: ...@@ -64,20 +43,15 @@ slb_exit_skip_ ## num:
* SVCPU[LR] = guest LR * SVCPU[LR] = guest LR
*/ */
/* Remove LPAR shadow entries */ BEGIN_FW_FTR_SECTION
#if SLB_NUM_BOLTED == 3 /* Declare SLB shadow as 0 entries big */
ld r12, PACA_SLBSHADOWPTR(r13) ld r11, PACA_SLBSHADOWPTR(r13)
li r8, 0
stb r8, 3(r11)
/* Remove bolted entries */ END_FW_FTR_SECTION_IFSET(FW_FEATURE_LPAR)
UNBOLT_SLB_ENTRY(0)
UNBOLT_SLB_ENTRY(1)
UNBOLT_SLB_ENTRY(2)
#else
#error unknown number of bolted entries
#endif
/* Flush SLB */ /* Flush SLB */
...@@ -100,7 +74,7 @@ slb_loop_enter: ...@@ -100,7 +74,7 @@ slb_loop_enter:
ld r10, 0(r11) ld r10, 0(r11)
rldicl. r0, r10, 37, 63 andis. r9, r10, SLB_ESID_V@h
beq slb_loop_enter_skip beq slb_loop_enter_skip
ld r9, 8(r11) ld r9, 8(r11)
...@@ -137,23 +111,42 @@ slb_do_enter: ...@@ -137,23 +111,42 @@ slb_do_enter:
* *
*/ */
/* Restore bolted entries from the shadow and fix it along the way */ /* Remove all SLB entries that are in use. */
/* We don't store anything in entry 0, so we don't need to take care of it */ li r0, r0
slbmte r0, r0
slbia slbia
isync
#if SLB_NUM_BOLTED == 3 /* Restore bolted entries from the shadow */
ld r11, PACA_SLBSHADOWPTR(r13) ld r11, PACA_SLBSHADOWPTR(r13)
REBOLT_SLB_ENTRY(0) BEGIN_FW_FTR_SECTION
REBOLT_SLB_ENTRY(1)
REBOLT_SLB_ENTRY(2) /* Declare SLB shadow as SLB_NUM_BOLTED entries big */
#else li r8, SLB_NUM_BOLTED
#error unknown number of bolted entries stb r8, 3(r11)
#endif
END_FW_FTR_SECTION_IFSET(FW_FEATURE_LPAR)
/* Manually load all entries from shadow SLB */
li r8, SLBSHADOW_SAVEAREA
li r7, SLBSHADOW_SAVEAREA + 8
.rept SLB_NUM_BOLTED
LDX_BE r10, r11, r8
cmpdi r10, 0
beq 1f
LDX_BE r9, r11, r7
slbmte r9, r10
1: addi r7, r7, SHADOW_SLB_ENTRY_LEN
addi r8, r8, SHADOW_SLB_ENTRY_LEN
.endr
isync
sync
slb_do_exit: slb_do_exit:
......
...@@ -80,7 +80,7 @@ static bool spr_allowed(struct kvm_vcpu *vcpu, enum priv_level level) ...@@ -80,7 +80,7 @@ static bool spr_allowed(struct kvm_vcpu *vcpu, enum priv_level level)
return false; return false;
/* Limit user space to its own small SPR set */ /* Limit user space to its own small SPR set */
if ((vcpu->arch.shared->msr & MSR_PR) && level > PRIV_PROBLEM) if ((kvmppc_get_msr(vcpu) & MSR_PR) && level > PRIV_PROBLEM)
return false; return false;
return true; return true;
...@@ -94,14 +94,31 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -94,14 +94,31 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
int rs = get_rs(inst); int rs = get_rs(inst);
int ra = get_ra(inst); int ra = get_ra(inst);
int rb = get_rb(inst); int rb = get_rb(inst);
u32 inst_sc = 0x44000002;
switch (get_op(inst)) { switch (get_op(inst)) {
case 0:
emulated = EMULATE_FAIL;
if ((kvmppc_get_msr(vcpu) & MSR_LE) &&
(inst == swab32(inst_sc))) {
/*
* This is the byte reversed syscall instruction of our
* hypercall handler. Early versions of LE Linux didn't
* swap the instructions correctly and ended up in
* illegal instructions.
* Just always fail hypercalls on these broken systems.
*/
kvmppc_set_gpr(vcpu, 3, EV_UNIMPLEMENTED);
kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4);
emulated = EMULATE_DONE;
}
break;
case 19: case 19:
switch (get_xop(inst)) { switch (get_xop(inst)) {
case OP_19_XOP_RFID: case OP_19_XOP_RFID:
case OP_19_XOP_RFI: case OP_19_XOP_RFI:
kvmppc_set_pc(vcpu, vcpu->arch.shared->srr0); kvmppc_set_pc(vcpu, kvmppc_get_srr0(vcpu));
kvmppc_set_msr(vcpu, vcpu->arch.shared->srr1); kvmppc_set_msr(vcpu, kvmppc_get_srr1(vcpu));
*advance = 0; *advance = 0;
break; break;
...@@ -113,16 +130,16 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -113,16 +130,16 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
case 31: case 31:
switch (get_xop(inst)) { switch (get_xop(inst)) {
case OP_31_XOP_MFMSR: case OP_31_XOP_MFMSR:
kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->msr); kvmppc_set_gpr(vcpu, rt, kvmppc_get_msr(vcpu));
break; break;
case OP_31_XOP_MTMSRD: case OP_31_XOP_MTMSRD:
{ {
ulong rs_val = kvmppc_get_gpr(vcpu, rs); ulong rs_val = kvmppc_get_gpr(vcpu, rs);
if (inst & 0x10000) { if (inst & 0x10000) {
ulong new_msr = vcpu->arch.shared->msr; ulong new_msr = kvmppc_get_msr(vcpu);
new_msr &= ~(MSR_RI | MSR_EE); new_msr &= ~(MSR_RI | MSR_EE);
new_msr |= rs_val & (MSR_RI | MSR_EE); new_msr |= rs_val & (MSR_RI | MSR_EE);
vcpu->arch.shared->msr = new_msr; kvmppc_set_msr_fast(vcpu, new_msr);
} else } else
kvmppc_set_msr(vcpu, rs_val); kvmppc_set_msr(vcpu, rs_val);
break; break;
...@@ -179,7 +196,7 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -179,7 +196,7 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
ulong cmd = kvmppc_get_gpr(vcpu, 3); ulong cmd = kvmppc_get_gpr(vcpu, 3);
int i; int i;
if ((vcpu->arch.shared->msr & MSR_PR) || if ((kvmppc_get_msr(vcpu) & MSR_PR) ||
!vcpu->arch.papr_enabled) { !vcpu->arch.papr_enabled) {
emulated = EMULATE_FAIL; emulated = EMULATE_FAIL;
break; break;
...@@ -261,14 +278,14 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -261,14 +278,14 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
ra_val = kvmppc_get_gpr(vcpu, ra); ra_val = kvmppc_get_gpr(vcpu, ra);
addr = (ra_val + rb_val) & ~31ULL; addr = (ra_val + rb_val) & ~31ULL;
if (!(vcpu->arch.shared->msr & MSR_SF)) if (!(kvmppc_get_msr(vcpu) & MSR_SF))
addr &= 0xffffffff; addr &= 0xffffffff;
vaddr = addr; vaddr = addr;
r = kvmppc_st(vcpu, &addr, 32, zeros, true); r = kvmppc_st(vcpu, &addr, 32, zeros, true);
if ((r == -ENOENT) || (r == -EPERM)) { if ((r == -ENOENT) || (r == -EPERM)) {
*advance = 0; *advance = 0;
vcpu->arch.shared->dar = vaddr; kvmppc_set_dar(vcpu, vaddr);
vcpu->arch.fault_dar = vaddr; vcpu->arch.fault_dar = vaddr;
dsisr = DSISR_ISSTORE; dsisr = DSISR_ISSTORE;
...@@ -277,7 +294,7 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -277,7 +294,7 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
else if (r == -EPERM) else if (r == -EPERM)
dsisr |= DSISR_PROTFAULT; dsisr |= DSISR_PROTFAULT;
vcpu->arch.shared->dsisr = dsisr; kvmppc_set_dsisr(vcpu, dsisr);
vcpu->arch.fault_dsisr = dsisr; vcpu->arch.fault_dsisr = dsisr;
kvmppc_book3s_queue_irqprio(vcpu, kvmppc_book3s_queue_irqprio(vcpu,
...@@ -356,10 +373,10 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) ...@@ -356,10 +373,10 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
to_book3s(vcpu)->sdr1 = spr_val; to_book3s(vcpu)->sdr1 = spr_val;
break; break;
case SPRN_DSISR: case SPRN_DSISR:
vcpu->arch.shared->dsisr = spr_val; kvmppc_set_dsisr(vcpu, spr_val);
break; break;
case SPRN_DAR: case SPRN_DAR:
vcpu->arch.shared->dar = spr_val; kvmppc_set_dar(vcpu, spr_val);
break; break;
case SPRN_HIOR: case SPRN_HIOR:
to_book3s(vcpu)->hior = spr_val; to_book3s(vcpu)->hior = spr_val;
...@@ -438,6 +455,31 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) ...@@ -438,6 +455,31 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
case SPRN_GQR7: case SPRN_GQR7:
to_book3s(vcpu)->gqr[sprn - SPRN_GQR0] = spr_val; to_book3s(vcpu)->gqr[sprn - SPRN_GQR0] = spr_val;
break; break;
case SPRN_FSCR:
vcpu->arch.fscr = spr_val;
break;
#ifdef CONFIG_PPC_BOOK3S_64
case SPRN_BESCR:
vcpu->arch.bescr = spr_val;
break;
case SPRN_EBBHR:
vcpu->arch.ebbhr = spr_val;
break;
case SPRN_EBBRR:
vcpu->arch.ebbrr = spr_val;
break;
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
case SPRN_TFHAR:
vcpu->arch.tfhar = spr_val;
break;
case SPRN_TEXASR:
vcpu->arch.texasr = spr_val;
break;
case SPRN_TFIAR:
vcpu->arch.tfiar = spr_val;
break;
#endif
#endif
case SPRN_ICTC: case SPRN_ICTC:
case SPRN_THRM1: case SPRN_THRM1:
case SPRN_THRM2: case SPRN_THRM2:
...@@ -455,6 +497,13 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) ...@@ -455,6 +497,13 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
case SPRN_WPAR_GEKKO: case SPRN_WPAR_GEKKO:
case SPRN_MSSSR0: case SPRN_MSSSR0:
case SPRN_DABR: case SPRN_DABR:
#ifdef CONFIG_PPC_BOOK3S_64
case SPRN_MMCRS:
case SPRN_MMCRA:
case SPRN_MMCR0:
case SPRN_MMCR1:
case SPRN_MMCR2:
#endif
break; break;
unprivileged: unprivileged:
default: default:
...@@ -493,10 +542,10 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val ...@@ -493,10 +542,10 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
*spr_val = to_book3s(vcpu)->sdr1; *spr_val = to_book3s(vcpu)->sdr1;
break; break;
case SPRN_DSISR: case SPRN_DSISR:
*spr_val = vcpu->arch.shared->dsisr; *spr_val = kvmppc_get_dsisr(vcpu);
break; break;
case SPRN_DAR: case SPRN_DAR:
*spr_val = vcpu->arch.shared->dar; *spr_val = kvmppc_get_dar(vcpu);
break; break;
case SPRN_HIOR: case SPRN_HIOR:
*spr_val = to_book3s(vcpu)->hior; *spr_val = to_book3s(vcpu)->hior;
...@@ -538,6 +587,31 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val ...@@ -538,6 +587,31 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
case SPRN_GQR7: case SPRN_GQR7:
*spr_val = to_book3s(vcpu)->gqr[sprn - SPRN_GQR0]; *spr_val = to_book3s(vcpu)->gqr[sprn - SPRN_GQR0];
break; break;
case SPRN_FSCR:
*spr_val = vcpu->arch.fscr;
break;
#ifdef CONFIG_PPC_BOOK3S_64
case SPRN_BESCR:
*spr_val = vcpu->arch.bescr;
break;
case SPRN_EBBHR:
*spr_val = vcpu->arch.ebbhr;
break;
case SPRN_EBBRR:
*spr_val = vcpu->arch.ebbrr;
break;
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
case SPRN_TFHAR:
*spr_val = vcpu->arch.tfhar;
break;
case SPRN_TEXASR:
*spr_val = vcpu->arch.texasr;
break;
case SPRN_TFIAR:
*spr_val = vcpu->arch.tfiar;
break;
#endif
#endif
case SPRN_THRM1: case SPRN_THRM1:
case SPRN_THRM2: case SPRN_THRM2:
case SPRN_THRM3: case SPRN_THRM3:
...@@ -553,6 +627,14 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val ...@@ -553,6 +627,14 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
case SPRN_WPAR_GEKKO: case SPRN_WPAR_GEKKO:
case SPRN_MSSSR0: case SPRN_MSSSR0:
case SPRN_DABR: case SPRN_DABR:
#ifdef CONFIG_PPC_BOOK3S_64
case SPRN_MMCRS:
case SPRN_MMCRA:
case SPRN_MMCR0:
case SPRN_MMCR1:
case SPRN_MMCR2:
case SPRN_TIR:
#endif
*spr_val = 0; *spr_val = 0;
break; break;
default: default:
...@@ -569,48 +651,17 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val ...@@ -569,48 +651,17 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst) u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst)
{ {
u32 dsisr = 0; return make_dsisr(inst);
/*
* This is what the spec says about DSISR bits (not mentioned = 0):
*
* 12:13 [DS] Set to bits 30:31
* 15:16 [X] Set to bits 29:30
* 17 [X] Set to bit 25
* [D/DS] Set to bit 5
* 18:21 [X] Set to bits 21:24
* [D/DS] Set to bits 1:4
* 22:26 Set to bits 6:10 (RT/RS/FRT/FRS)
* 27:31 Set to bits 11:15 (RA)
*/
switch (get_op(inst)) {
/* D-form */
case OP_LFS:
case OP_LFD:
case OP_STFD:
case OP_STFS:
dsisr |= (inst >> 12) & 0x4000; /* bit 17 */
dsisr |= (inst >> 17) & 0x3c00; /* bits 18:21 */
break;
/* X-form */
case 31:
dsisr |= (inst << 14) & 0x18000; /* bits 15:16 */
dsisr |= (inst << 8) & 0x04000; /* bit 17 */
dsisr |= (inst << 3) & 0x03c00; /* bits 18:21 */
break;
default:
printk(KERN_INFO "KVM: Unaligned instruction 0x%x\n", inst);
break;
}
dsisr |= (inst >> 16) & 0x03ff; /* bits 22:31 */
return dsisr;
} }
ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst) ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst)
{ {
#ifdef CONFIG_PPC_BOOK3S_64
/*
* Linux's fix_alignment() assumes that DAR is valid, so can we
*/
return vcpu->arch.fault_dar;
#else
ulong dar = 0; ulong dar = 0;
ulong ra = get_ra(inst); ulong ra = get_ra(inst);
ulong rb = get_rb(inst); ulong rb = get_rb(inst);
...@@ -635,4 +686,5 @@ ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst) ...@@ -635,4 +686,5 @@ ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst)
} }
return dar; return dar;
#endif
} }
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
*/ */
#include <linux/export.h> #include <linux/export.h>
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s.h> #include <asm/kvm_book3s.h>
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
......
...@@ -879,24 +879,9 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, ...@@ -879,24 +879,9 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_IAMR: case KVM_REG_PPC_IAMR:
*val = get_reg_val(id, vcpu->arch.iamr); *val = get_reg_val(id, vcpu->arch.iamr);
break; break;
case KVM_REG_PPC_FSCR:
*val = get_reg_val(id, vcpu->arch.fscr);
break;
case KVM_REG_PPC_PSPB: case KVM_REG_PPC_PSPB:
*val = get_reg_val(id, vcpu->arch.pspb); *val = get_reg_val(id, vcpu->arch.pspb);
break; break;
case KVM_REG_PPC_EBBHR:
*val = get_reg_val(id, vcpu->arch.ebbhr);
break;
case KVM_REG_PPC_EBBRR:
*val = get_reg_val(id, vcpu->arch.ebbrr);
break;
case KVM_REG_PPC_BESCR:
*val = get_reg_val(id, vcpu->arch.bescr);
break;
case KVM_REG_PPC_TAR:
*val = get_reg_val(id, vcpu->arch.tar);
break;
case KVM_REG_PPC_DPDES: case KVM_REG_PPC_DPDES:
*val = get_reg_val(id, vcpu->arch.vcore->dpdes); *val = get_reg_val(id, vcpu->arch.vcore->dpdes);
break; break;
...@@ -1091,24 +1076,9 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, ...@@ -1091,24 +1076,9 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_IAMR: case KVM_REG_PPC_IAMR:
vcpu->arch.iamr = set_reg_val(id, *val); vcpu->arch.iamr = set_reg_val(id, *val);
break; break;
case KVM_REG_PPC_FSCR:
vcpu->arch.fscr = set_reg_val(id, *val);
break;
case KVM_REG_PPC_PSPB: case KVM_REG_PPC_PSPB:
vcpu->arch.pspb = set_reg_val(id, *val); vcpu->arch.pspb = set_reg_val(id, *val);
break; break;
case KVM_REG_PPC_EBBHR:
vcpu->arch.ebbhr = set_reg_val(id, *val);
break;
case KVM_REG_PPC_EBBRR:
vcpu->arch.ebbrr = set_reg_val(id, *val);
break;
case KVM_REG_PPC_BESCR:
vcpu->arch.bescr = set_reg_val(id, *val);
break;
case KVM_REG_PPC_TAR:
vcpu->arch.tar = set_reg_val(id, *val);
break;
case KVM_REG_PPC_DPDES: case KVM_REG_PPC_DPDES:
vcpu->arch.vcore->dpdes = set_reg_val(id, *val); vcpu->arch.vcore->dpdes = set_reg_val(id, *val);
break; break;
...@@ -1280,6 +1250,17 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, ...@@ -1280,6 +1250,17 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
goto free_vcpu; goto free_vcpu;
vcpu->arch.shared = &vcpu->arch.shregs; vcpu->arch.shared = &vcpu->arch.shregs;
#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
/*
* The shared struct is never shared on HV,
* so we can always use host endianness
*/
#ifdef __BIG_ENDIAN__
vcpu->arch.shared_big_endian = true;
#else
vcpu->arch.shared_big_endian = false;
#endif
#endif
vcpu->arch.mmcr[0] = MMCR0_FC; vcpu->arch.mmcr[0] = MMCR0_FC;
vcpu->arch.ctrl = CTRL_RUNLATCH; vcpu->arch.ctrl = CTRL_RUNLATCH;
/* default to host PVR, since we can't spoof it */ /* default to host PVR, since we can't spoof it */
...@@ -1949,6 +1930,13 @@ static void kvmppc_add_seg_page_size(struct kvm_ppc_one_seg_page_size **sps, ...@@ -1949,6 +1930,13 @@ static void kvmppc_add_seg_page_size(struct kvm_ppc_one_seg_page_size **sps,
* support pte_enc here * support pte_enc here
*/ */
(*sps)->enc[0].pte_enc = def->penc[linux_psize]; (*sps)->enc[0].pte_enc = def->penc[linux_psize];
/*
* Add 16MB MPSS support if host supports it
*/
if (linux_psize != MMU_PAGE_16M && def->penc[MMU_PAGE_16M] != -1) {
(*sps)->enc[1].page_shift = 24;
(*sps)->enc[1].pte_enc = def->penc[MMU_PAGE_16M];
}
(*sps)++; (*sps)++;
} }
......
...@@ -42,13 +42,14 @@ static int global_invalidates(struct kvm *kvm, unsigned long flags) ...@@ -42,13 +42,14 @@ static int global_invalidates(struct kvm *kvm, unsigned long flags)
/* /*
* If there is only one vcore, and it's currently running, * If there is only one vcore, and it's currently running,
* as indicated by local_paca->kvm_hstate.kvm_vcpu being set,
* we can use tlbiel as long as we mark all other physical * we can use tlbiel as long as we mark all other physical
* cores as potentially having stale TLB entries for this lpid. * cores as potentially having stale TLB entries for this lpid.
* If we're not using MMU notifiers, we never take pages away * If we're not using MMU notifiers, we never take pages away
* from the guest, so we can use tlbiel if requested. * from the guest, so we can use tlbiel if requested.
* Otherwise, don't use tlbiel. * Otherwise, don't use tlbiel.
*/ */
if (kvm->arch.online_vcores == 1 && local_paca->kvm_hstate.kvm_vcore) if (kvm->arch.online_vcores == 1 && local_paca->kvm_hstate.kvm_vcpu)
global = 0; global = 0;
else if (kvm->arch.using_mmu_notifiers) else if (kvm->arch.using_mmu_notifiers)
global = 1; global = 1;
......
...@@ -86,6 +86,12 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) ...@@ -86,6 +86,12 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
lbz r4, LPPACA_PMCINUSE(r3) lbz r4, LPPACA_PMCINUSE(r3)
cmpwi r4, 0 cmpwi r4, 0
beq 23f /* skip if not */ beq 23f /* skip if not */
BEGIN_FTR_SECTION
ld r3, HSTATE_MMCR(r13)
andi. r4, r3, MMCR0_PMAO_SYNC | MMCR0_PMAO
cmpwi r4, MMCR0_PMAO
beql kvmppc_fix_pmao
END_FTR_SECTION_IFSET(CPU_FTR_PMAO_BUG)
lwz r3, HSTATE_PMC(r13) lwz r3, HSTATE_PMC(r13)
lwz r4, HSTATE_PMC + 4(r13) lwz r4, HSTATE_PMC + 4(r13)
lwz r5, HSTATE_PMC + 8(r13) lwz r5, HSTATE_PMC + 8(r13)
...@@ -726,6 +732,12 @@ skip_tm: ...@@ -726,6 +732,12 @@ skip_tm:
sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */ sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */
mtspr SPRN_MMCR0, r3 /* freeze all counters, disable ints */ mtspr SPRN_MMCR0, r3 /* freeze all counters, disable ints */
isync isync
BEGIN_FTR_SECTION
ld r3, VCPU_MMCR(r4)
andi. r5, r3, MMCR0_PMAO_SYNC | MMCR0_PMAO
cmpwi r5, MMCR0_PMAO
beql kvmppc_fix_pmao
END_FTR_SECTION_IFSET(CPU_FTR_PMAO_BUG)
lwz r3, VCPU_PMC(r4) /* always load up guest PMU registers */ lwz r3, VCPU_PMC(r4) /* always load up guest PMU registers */
lwz r5, VCPU_PMC + 4(r4) /* to prevent information leak */ lwz r5, VCPU_PMC + 4(r4) /* to prevent information leak */
lwz r6, VCPU_PMC + 8(r4) lwz r6, VCPU_PMC + 8(r4)
...@@ -1324,6 +1336,30 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) ...@@ -1324,6 +1336,30 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
25: 25:
/* Save PMU registers if requested */ /* Save PMU registers if requested */
/* r8 and cr0.eq are live here */ /* r8 and cr0.eq are live here */
BEGIN_FTR_SECTION
/*
* POWER8 seems to have a hardware bug where setting
* MMCR0[PMAE] along with MMCR0[PMC1CE] and/or MMCR0[PMCjCE]
* when some counters are already negative doesn't seem
* to cause a performance monitor alert (and hence interrupt).
* The effect of this is that when saving the PMU state,
* if there is no PMU alert pending when we read MMCR0
* before freezing the counters, but one becomes pending
* before we read the counters, we lose it.
* To work around this, we need a way to freeze the counters
* before reading MMCR0. Normally, freezing the counters
* is done by writing MMCR0 (to set MMCR0[FC]) which
* unavoidably writes MMCR0[PMA0] as well. On POWER8,
* we can also freeze the counters using MMCR2, by writing
* 1s to all the counter freeze condition bits (there are
* 9 bits each for 6 counters).
*/
li r3, -1 /* set all freeze bits */
clrrdi r3, r3, 10
mfspr r10, SPRN_MMCR2
mtspr SPRN_MMCR2, r3
isync
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
li r3, 1 li r3, 1
sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */ sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */
mfspr r4, SPRN_MMCR0 /* save MMCR0 */ mfspr r4, SPRN_MMCR0 /* save MMCR0 */
...@@ -1347,6 +1383,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) ...@@ -1347,6 +1383,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
std r4, VCPU_MMCR(r9) std r4, VCPU_MMCR(r9)
std r5, VCPU_MMCR + 8(r9) std r5, VCPU_MMCR + 8(r9)
std r6, VCPU_MMCR + 16(r9) std r6, VCPU_MMCR + 16(r9)
BEGIN_FTR_SECTION
std r10, VCPU_MMCR + 24(r9)
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
std r7, VCPU_SIAR(r9) std r7, VCPU_SIAR(r9)
std r8, VCPU_SDAR(r9) std r8, VCPU_SDAR(r9)
mfspr r3, SPRN_PMC1 mfspr r3, SPRN_PMC1
...@@ -1370,12 +1409,10 @@ BEGIN_FTR_SECTION ...@@ -1370,12 +1409,10 @@ BEGIN_FTR_SECTION
stw r11, VCPU_PMC + 28(r9) stw r11, VCPU_PMC + 28(r9)
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
BEGIN_FTR_SECTION BEGIN_FTR_SECTION
mfspr r4, SPRN_MMCR2
mfspr r5, SPRN_SIER mfspr r5, SPRN_SIER
mfspr r6, SPRN_SPMC1 mfspr r6, SPRN_SPMC1
mfspr r7, SPRN_SPMC2 mfspr r7, SPRN_SPMC2
mfspr r8, SPRN_MMCRS mfspr r8, SPRN_MMCRS
std r4, VCPU_MMCR + 24(r9)
std r5, VCPU_SIER(r9) std r5, VCPU_SIER(r9)
stw r6, VCPU_PMC + 24(r9) stw r6, VCPU_PMC + 24(r9)
stw r7, VCPU_PMC + 28(r9) stw r7, VCPU_PMC + 28(r9)
...@@ -2107,6 +2144,7 @@ machine_check_realmode: ...@@ -2107,6 +2144,7 @@ machine_check_realmode:
beq mc_cont beq mc_cont
/* If not, deliver a machine check. SRR0/1 are already set */ /* If not, deliver a machine check. SRR0/1 are already set */
li r10, BOOK3S_INTERRUPT_MACHINE_CHECK li r10, BOOK3S_INTERRUPT_MACHINE_CHECK
ld r11, VCPU_MSR(r9)
bl kvmppc_msr_interrupt bl kvmppc_msr_interrupt
b fast_interrupt_c_return b fast_interrupt_c_return
...@@ -2311,3 +2349,21 @@ kvmppc_msr_interrupt: ...@@ -2311,3 +2349,21 @@ kvmppc_msr_interrupt:
li r0, 1 li r0, 1
1: rldimi r11, r0, MSR_TS_S_LG, 63 - MSR_TS_T_LG 1: rldimi r11, r0, MSR_TS_S_LG, 63 - MSR_TS_T_LG
blr blr
/*
* This works around a hardware bug on POWER8E processors, where
* writing a 1 to the MMCR0[PMAO] bit doesn't generate a
* performance monitor interrupt. Instead, when we need to have
* an interrupt pending, we have to arrange for a counter to overflow.
*/
kvmppc_fix_pmao:
li r3, 0
mtspr SPRN_MMCR2, r3
lis r3, (MMCR0_PMXE | MMCR0_FCECE)@h
ori r3, r3, MMCR0_PMCjCE | MMCR0_C56RUN
mtspr SPRN_MMCR0, r3
lis r3, 0x7fff
ori r3, r3, 0xffff
mtspr SPRN_PMC6, r3
isync
blr
...@@ -104,8 +104,27 @@ kvm_start_lightweight: ...@@ -104,8 +104,27 @@ kvm_start_lightweight:
stb r3, HSTATE_RESTORE_HID5(r13) stb r3, HSTATE_RESTORE_HID5(r13)
/* Load up guest SPRG3 value, since it's user readable */ /* Load up guest SPRG3 value, since it's user readable */
ld r3, VCPU_SHARED(r4) lwz r3, VCPU_SHAREDBE(r4)
ld r3, VCPU_SHARED_SPRG3(r3) cmpwi r3, 0
ld r5, VCPU_SHARED(r4)
beq sprg3_little_endian
sprg3_big_endian:
#ifdef __BIG_ENDIAN__
ld r3, VCPU_SHARED_SPRG3(r5)
#else
addi r5, r5, VCPU_SHARED_SPRG3
ldbrx r3, 0, r5
#endif
b after_sprg3_load
sprg3_little_endian:
#ifdef __LITTLE_ENDIAN__
ld r3, VCPU_SHARED_SPRG3(r5)
#else
addi r5, r5, VCPU_SHARED_SPRG3
ldbrx r3, 0, r5
#endif
after_sprg3_load:
mtspr SPRN_SPRG3, r3 mtspr SPRN_SPRG3, r3
#endif /* CONFIG_PPC_BOOK3S_64 */ #endif /* CONFIG_PPC_BOOK3S_64 */
......
...@@ -165,16 +165,18 @@ static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt) ...@@ -165,16 +165,18 @@ static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt)
static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store) static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store)
{ {
u64 dsisr; u32 dsisr;
struct kvm_vcpu_arch_shared *shared = vcpu->arch.shared; u64 msr = kvmppc_get_msr(vcpu);
shared->msr = kvmppc_set_field(shared->msr, 33, 36, 0); msr = kvmppc_set_field(msr, 33, 36, 0);
shared->msr = kvmppc_set_field(shared->msr, 42, 47, 0); msr = kvmppc_set_field(msr, 42, 47, 0);
shared->dar = eaddr; kvmppc_set_msr(vcpu, msr);
kvmppc_set_dar(vcpu, eaddr);
/* Page Fault */ /* Page Fault */
dsisr = kvmppc_set_field(0, 33, 33, 1); dsisr = kvmppc_set_field(0, 33, 33, 1);
if (is_store) if (is_store)
shared->dsisr = kvmppc_set_field(dsisr, 38, 38, 1); dsisr = kvmppc_set_field(dsisr, 38, 38, 1);
kvmppc_set_dsisr(vcpu, dsisr);
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE); kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE);
} }
...@@ -660,7 +662,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu) ...@@ -660,7 +662,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu)
if (!kvmppc_inst_is_paired_single(vcpu, inst)) if (!kvmppc_inst_is_paired_single(vcpu, inst))
return EMULATE_FAIL; return EMULATE_FAIL;
if (!(vcpu->arch.shared->msr & MSR_FP)) { if (!(kvmppc_get_msr(vcpu) & MSR_FP)) {
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL); kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL);
return EMULATE_AGAIN; return EMULATE_AGAIN;
} }
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
ulong msr); ulong msr);
static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac);
/* Some compatibility defines */ /* Some compatibility defines */
#ifdef CONFIG_PPC_BOOK3S_32 #ifdef CONFIG_PPC_BOOK3S_32
...@@ -89,6 +90,7 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu) ...@@ -89,6 +90,7 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
#endif #endif
kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX); kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
vcpu->cpu = -1; vcpu->cpu = -1;
} }
...@@ -115,6 +117,9 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu, ...@@ -115,6 +117,9 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu,
svcpu->ctr = vcpu->arch.ctr; svcpu->ctr = vcpu->arch.ctr;
svcpu->lr = vcpu->arch.lr; svcpu->lr = vcpu->arch.lr;
svcpu->pc = vcpu->arch.pc; svcpu->pc = vcpu->arch.pc;
#ifdef CONFIG_PPC_BOOK3S_64
svcpu->shadow_fscr = vcpu->arch.shadow_fscr;
#endif
svcpu->in_use = true; svcpu->in_use = true;
} }
...@@ -158,6 +163,9 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, ...@@ -158,6 +163,9 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu,
vcpu->arch.fault_dar = svcpu->fault_dar; vcpu->arch.fault_dar = svcpu->fault_dar;
vcpu->arch.fault_dsisr = svcpu->fault_dsisr; vcpu->arch.fault_dsisr = svcpu->fault_dsisr;
vcpu->arch.last_inst = svcpu->last_inst; vcpu->arch.last_inst = svcpu->last_inst;
#ifdef CONFIG_PPC_BOOK3S_64
vcpu->arch.shadow_fscr = svcpu->shadow_fscr;
#endif
svcpu->in_use = false; svcpu->in_use = false;
out: out:
...@@ -246,14 +254,15 @@ static void kvm_set_spte_hva_pr(struct kvm *kvm, unsigned long hva, pte_t pte) ...@@ -246,14 +254,15 @@ static void kvm_set_spte_hva_pr(struct kvm *kvm, unsigned long hva, pte_t pte)
static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu) static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
{ {
ulong smsr = vcpu->arch.shared->msr; ulong guest_msr = kvmppc_get_msr(vcpu);
ulong smsr = guest_msr;
/* Guest MSR values */ /* Guest MSR values */
smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE; smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_LE;
/* Process MSR values */ /* Process MSR values */
smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE; smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
/* External providers the guest reserved */ /* External providers the guest reserved */
smsr |= (vcpu->arch.shared->msr & vcpu->arch.guest_owned_ext); smsr |= (guest_msr & vcpu->arch.guest_owned_ext);
/* 64-bit Process MSR values */ /* 64-bit Process MSR values */
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
smsr |= MSR_ISF | MSR_HV; smsr |= MSR_ISF | MSR_HV;
...@@ -263,14 +272,14 @@ static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu) ...@@ -263,14 +272,14 @@ static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr) static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
{ {
ulong old_msr = vcpu->arch.shared->msr; ulong old_msr = kvmppc_get_msr(vcpu);
#ifdef EXIT_DEBUG #ifdef EXIT_DEBUG
printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr); printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
#endif #endif
msr &= to_book3s(vcpu)->msr_mask; msr &= to_book3s(vcpu)->msr_mask;
vcpu->arch.shared->msr = msr; kvmppc_set_msr_fast(vcpu, msr);
kvmppc_recalc_shadow_msr(vcpu); kvmppc_recalc_shadow_msr(vcpu);
if (msr & MSR_POW) { if (msr & MSR_POW) {
...@@ -281,11 +290,11 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr) ...@@ -281,11 +290,11 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
/* Unset POW bit after we woke up */ /* Unset POW bit after we woke up */
msr &= ~MSR_POW; msr &= ~MSR_POW;
vcpu->arch.shared->msr = msr; kvmppc_set_msr_fast(vcpu, msr);
} }
} }
if ((vcpu->arch.shared->msr & (MSR_PR|MSR_IR|MSR_DR)) != if ((kvmppc_get_msr(vcpu) & (MSR_PR|MSR_IR|MSR_DR)) !=
(old_msr & (MSR_PR|MSR_IR|MSR_DR))) { (old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
kvmppc_mmu_flush_segments(vcpu); kvmppc_mmu_flush_segments(vcpu);
kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
...@@ -317,7 +326,7 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr) ...@@ -317,7 +326,7 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
} }
/* Preload FPU if it's enabled */ /* Preload FPU if it's enabled */
if (vcpu->arch.shared->msr & MSR_FP) if (kvmppc_get_msr(vcpu) & MSR_FP)
kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
} }
...@@ -427,8 +436,8 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte) ...@@ -427,8 +436,8 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
/* patch dcbz into reserved instruction, so we trap */ /* patch dcbz into reserved instruction, so we trap */
for (i=hpage_offset; i < hpage_offset + (HW_PAGE_SIZE / 4); i++) for (i=hpage_offset; i < hpage_offset + (HW_PAGE_SIZE / 4); i++)
if ((page[i] & 0xff0007ff) == INS_DCBZ) if ((be32_to_cpu(page[i]) & 0xff0007ff) == INS_DCBZ)
page[i] &= 0xfffffff7; page[i] &= cpu_to_be32(0xfffffff7);
kunmap_atomic(page); kunmap_atomic(page);
put_page(hpage); put_page(hpage);
...@@ -438,7 +447,7 @@ static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn) ...@@ -438,7 +447,7 @@ static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn)
{ {
ulong mp_pa = vcpu->arch.magic_page_pa; ulong mp_pa = vcpu->arch.magic_page_pa;
if (!(vcpu->arch.shared->msr & MSR_SF)) if (!(kvmppc_get_msr(vcpu) & MSR_SF))
mp_pa = (uint32_t)mp_pa; mp_pa = (uint32_t)mp_pa;
if (unlikely(mp_pa) && if (unlikely(mp_pa) &&
...@@ -459,8 +468,8 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -459,8 +468,8 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
int page_found = 0; int page_found = 0;
struct kvmppc_pte pte; struct kvmppc_pte pte;
bool is_mmio = false; bool is_mmio = false;
bool dr = (vcpu->arch.shared->msr & MSR_DR) ? true : false; bool dr = (kvmppc_get_msr(vcpu) & MSR_DR) ? true : false;
bool ir = (vcpu->arch.shared->msr & MSR_IR) ? true : false; bool ir = (kvmppc_get_msr(vcpu) & MSR_IR) ? true : false;
u64 vsid; u64 vsid;
relocated = data ? dr : ir; relocated = data ? dr : ir;
...@@ -480,7 +489,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -480,7 +489,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
pte.page_size = MMU_PAGE_64K; pte.page_size = MMU_PAGE_64K;
} }
switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { switch (kvmppc_get_msr(vcpu) & (MSR_DR|MSR_IR)) {
case 0: case 0:
pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12)); pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
break; break;
...@@ -488,7 +497,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -488,7 +497,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
case MSR_IR: case MSR_IR:
vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid); vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
if ((vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) == MSR_DR) if ((kvmppc_get_msr(vcpu) & (MSR_DR|MSR_IR)) == MSR_DR)
pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12)); pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12));
else else
pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12)); pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12));
...@@ -511,22 +520,25 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -511,22 +520,25 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (page_found == -ENOENT) { if (page_found == -ENOENT) {
/* Page not found in guest PTE entries */ /* Page not found in guest PTE entries */
vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); u64 ssrr1 = vcpu->arch.shadow_srr1;
vcpu->arch.shared->dsisr = vcpu->arch.fault_dsisr; u64 msr = kvmppc_get_msr(vcpu);
vcpu->arch.shared->msr |= kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
vcpu->arch.shadow_srr1 & 0x00000000f8000000ULL; kvmppc_set_dsisr(vcpu, vcpu->arch.fault_dsisr);
kvmppc_set_msr_fast(vcpu, msr | (ssrr1 & 0xf8000000ULL));
kvmppc_book3s_queue_irqprio(vcpu, vec); kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EPERM) { } else if (page_found == -EPERM) {
/* Storage protection */ /* Storage protection */
vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); u32 dsisr = vcpu->arch.fault_dsisr;
vcpu->arch.shared->dsisr = vcpu->arch.fault_dsisr & ~DSISR_NOHPTE; u64 ssrr1 = vcpu->arch.shadow_srr1;
vcpu->arch.shared->dsisr |= DSISR_PROTFAULT; u64 msr = kvmppc_get_msr(vcpu);
vcpu->arch.shared->msr |= kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
vcpu->arch.shadow_srr1 & 0x00000000f8000000ULL; dsisr = (dsisr & ~DSISR_NOHPTE) | DSISR_PROTFAULT;
kvmppc_set_dsisr(vcpu, dsisr);
kvmppc_set_msr_fast(vcpu, msr | (ssrr1 & 0xf8000000ULL));
kvmppc_book3s_queue_irqprio(vcpu, vec); kvmppc_book3s_queue_irqprio(vcpu, vec);
} else if (page_found == -EINVAL) { } else if (page_found == -EINVAL) {
/* Page not found in guest SLB */ /* Page not found in guest SLB */
vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80); kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80);
} else if (!is_mmio && } else if (!is_mmio &&
kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) { kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) {
...@@ -606,6 +618,25 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr) ...@@ -606,6 +618,25 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
kvmppc_recalc_shadow_msr(vcpu); kvmppc_recalc_shadow_msr(vcpu);
} }
/* Give up facility (TAR / EBB / DSCR) */
static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac)
{
#ifdef CONFIG_PPC_BOOK3S_64
if (!(vcpu->arch.shadow_fscr & (1ULL << fac))) {
/* Facility not available to the guest, ignore giveup request*/
return;
}
switch (fac) {
case FSCR_TAR_LG:
vcpu->arch.tar = mfspr(SPRN_TAR);
mtspr(SPRN_TAR, current->thread.tar);
vcpu->arch.shadow_fscr &= ~FSCR_TAR;
break;
}
#endif
}
static int kvmppc_read_inst(struct kvm_vcpu *vcpu) static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
{ {
ulong srr0 = kvmppc_get_pc(vcpu); ulong srr0 = kvmppc_get_pc(vcpu);
...@@ -614,11 +645,12 @@ static int kvmppc_read_inst(struct kvm_vcpu *vcpu) ...@@ -614,11 +645,12 @@ static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false); ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
if (ret == -ENOENT) { if (ret == -ENOENT) {
ulong msr = vcpu->arch.shared->msr; ulong msr = kvmppc_get_msr(vcpu);
msr = kvmppc_set_field(msr, 33, 33, 1); msr = kvmppc_set_field(msr, 33, 33, 1);
msr = kvmppc_set_field(msr, 34, 36, 0); msr = kvmppc_set_field(msr, 34, 36, 0);
vcpu->arch.shared->msr = kvmppc_set_field(msr, 42, 47, 0); msr = kvmppc_set_field(msr, 42, 47, 0);
kvmppc_set_msr_fast(vcpu, msr);
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE); kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
return EMULATE_AGAIN; return EMULATE_AGAIN;
} }
...@@ -651,7 +683,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, ...@@ -651,7 +683,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE) if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)
return RESUME_GUEST; return RESUME_GUEST;
if (!(vcpu->arch.shared->msr & msr)) { if (!(kvmppc_get_msr(vcpu) & msr)) {
kvmppc_book3s_queue_irqprio(vcpu, exit_nr); kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
return RESUME_GUEST; return RESUME_GUEST;
} }
...@@ -683,16 +715,20 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, ...@@ -683,16 +715,20 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
#endif #endif
if (msr & MSR_FP) { if (msr & MSR_FP) {
preempt_disable();
enable_kernel_fp(); enable_kernel_fp();
load_fp_state(&vcpu->arch.fp); load_fp_state(&vcpu->arch.fp);
t->fp_save_area = &vcpu->arch.fp; t->fp_save_area = &vcpu->arch.fp;
preempt_enable();
} }
if (msr & MSR_VEC) { if (msr & MSR_VEC) {
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
preempt_disable();
enable_kernel_altivec(); enable_kernel_altivec();
load_vr_state(&vcpu->arch.vr); load_vr_state(&vcpu->arch.vr);
t->vr_save_area = &vcpu->arch.vr; t->vr_save_area = &vcpu->arch.vr;
preempt_enable();
#endif #endif
} }
...@@ -716,18 +752,90 @@ static void kvmppc_handle_lost_ext(struct kvm_vcpu *vcpu) ...@@ -716,18 +752,90 @@ static void kvmppc_handle_lost_ext(struct kvm_vcpu *vcpu)
return; return;
if (lost_ext & MSR_FP) { if (lost_ext & MSR_FP) {
preempt_disable();
enable_kernel_fp(); enable_kernel_fp();
load_fp_state(&vcpu->arch.fp); load_fp_state(&vcpu->arch.fp);
preempt_enable();
} }
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
if (lost_ext & MSR_VEC) { if (lost_ext & MSR_VEC) {
preempt_disable();
enable_kernel_altivec(); enable_kernel_altivec();
load_vr_state(&vcpu->arch.vr); load_vr_state(&vcpu->arch.vr);
preempt_enable();
} }
#endif #endif
current->thread.regs->msr |= lost_ext; current->thread.regs->msr |= lost_ext;
} }
#ifdef CONFIG_PPC_BOOK3S_64
static void kvmppc_trigger_fac_interrupt(struct kvm_vcpu *vcpu, ulong fac)
{
/* Inject the Interrupt Cause field and trigger a guest interrupt */
vcpu->arch.fscr &= ~(0xffULL << 56);
vcpu->arch.fscr |= (fac << 56);
kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FAC_UNAVAIL);
}
static void kvmppc_emulate_fac(struct kvm_vcpu *vcpu, ulong fac)
{
enum emulation_result er = EMULATE_FAIL;
if (!(kvmppc_get_msr(vcpu) & MSR_PR))
er = kvmppc_emulate_instruction(vcpu->run, vcpu);
if ((er != EMULATE_DONE) && (er != EMULATE_AGAIN)) {
/* Couldn't emulate, trigger interrupt in guest */
kvmppc_trigger_fac_interrupt(vcpu, fac);
}
}
/* Enable facilities (TAR, EBB, DSCR) for the guest */
static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac)
{
bool guest_fac_enabled;
BUG_ON(!cpu_has_feature(CPU_FTR_ARCH_207S));
/*
* Not every facility is enabled by FSCR bits, check whether the
* guest has this facility enabled at all.
*/
switch (fac) {
case FSCR_TAR_LG:
case FSCR_EBB_LG:
guest_fac_enabled = (vcpu->arch.fscr & (1ULL << fac));
break;
case FSCR_TM_LG:
guest_fac_enabled = kvmppc_get_msr(vcpu) & MSR_TM;
break;
default:
guest_fac_enabled = false;
break;
}
if (!guest_fac_enabled) {
/* Facility not enabled by the guest */
kvmppc_trigger_fac_interrupt(vcpu, fac);
return RESUME_GUEST;
}
switch (fac) {
case FSCR_TAR_LG:
/* TAR switching isn't lazy in Linux yet */
current->thread.tar = mfspr(SPRN_TAR);
mtspr(SPRN_TAR, vcpu->arch.tar);
vcpu->arch.shadow_fscr |= FSCR_TAR;
break;
default:
kvmppc_emulate_fac(vcpu, fac);
break;
}
return RESUME_GUEST;
}
#endif
int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned int exit_nr) unsigned int exit_nr)
{ {
...@@ -784,7 +892,9 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -784,7 +892,9 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL); kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
r = RESUME_GUEST; r = RESUME_GUEST;
} else { } else {
vcpu->arch.shared->msr |= shadow_srr1 & 0x58000000; u64 msr = kvmppc_get_msr(vcpu);
msr |= shadow_srr1 & 0x58000000;
kvmppc_set_msr_fast(vcpu, msr);
kvmppc_book3s_queue_irqprio(vcpu, exit_nr); kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
r = RESUME_GUEST; r = RESUME_GUEST;
} }
...@@ -824,8 +934,8 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -824,8 +934,8 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr); r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
srcu_read_unlock(&vcpu->kvm->srcu, idx); srcu_read_unlock(&vcpu->kvm->srcu, idx);
} else { } else {
vcpu->arch.shared->dar = dar; kvmppc_set_dar(vcpu, dar);
vcpu->arch.shared->dsisr = fault_dsisr; kvmppc_set_dsisr(vcpu, fault_dsisr);
kvmppc_book3s_queue_irqprio(vcpu, exit_nr); kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
r = RESUME_GUEST; r = RESUME_GUEST;
} }
...@@ -833,7 +943,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -833,7 +943,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
} }
case BOOK3S_INTERRUPT_DATA_SEGMENT: case BOOK3S_INTERRUPT_DATA_SEGMENT:
if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) { if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) {
vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
kvmppc_book3s_queue_irqprio(vcpu, kvmppc_book3s_queue_irqprio(vcpu,
BOOK3S_INTERRUPT_DATA_SEGMENT); BOOK3S_INTERRUPT_DATA_SEGMENT);
} }
...@@ -871,7 +981,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -871,7 +981,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
program_interrupt: program_interrupt:
flags = vcpu->arch.shadow_srr1 & 0x1f0000ull; flags = vcpu->arch.shadow_srr1 & 0x1f0000ull;
if (vcpu->arch.shared->msr & MSR_PR) { if (kvmppc_get_msr(vcpu) & MSR_PR) {
#ifdef EXIT_DEBUG #ifdef EXIT_DEBUG
printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu)); printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
#endif #endif
...@@ -913,7 +1023,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -913,7 +1023,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
case BOOK3S_INTERRUPT_SYSCALL: case BOOK3S_INTERRUPT_SYSCALL:
if (vcpu->arch.papr_enabled && if (vcpu->arch.papr_enabled &&
(kvmppc_get_last_sc(vcpu) == 0x44000022) && (kvmppc_get_last_sc(vcpu) == 0x44000022) &&
!(vcpu->arch.shared->msr & MSR_PR)) { !(kvmppc_get_msr(vcpu) & MSR_PR)) {
/* SC 1 papr hypercalls */ /* SC 1 papr hypercalls */
ulong cmd = kvmppc_get_gpr(vcpu, 3); ulong cmd = kvmppc_get_gpr(vcpu, 3);
int i; int i;
...@@ -945,7 +1055,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -945,7 +1055,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
gprs[i] = kvmppc_get_gpr(vcpu, i); gprs[i] = kvmppc_get_gpr(vcpu, i);
vcpu->arch.osi_needed = 1; vcpu->arch.osi_needed = 1;
r = RESUME_HOST_NV; r = RESUME_HOST_NV;
} else if (!(vcpu->arch.shared->msr & MSR_PR) && } else if (!(kvmppc_get_msr(vcpu) & MSR_PR) &&
(((u32)kvmppc_get_gpr(vcpu, 0)) == KVM_SC_MAGIC_R0)) { (((u32)kvmppc_get_gpr(vcpu, 0)) == KVM_SC_MAGIC_R0)) {
/* KVM PV hypercalls */ /* KVM PV hypercalls */
kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu)); kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu));
...@@ -986,14 +1096,26 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -986,14 +1096,26 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
} }
case BOOK3S_INTERRUPT_ALIGNMENT: case BOOK3S_INTERRUPT_ALIGNMENT:
if (kvmppc_read_inst(vcpu) == EMULATE_DONE) { if (kvmppc_read_inst(vcpu) == EMULATE_DONE) {
vcpu->arch.shared->dsisr = kvmppc_alignment_dsisr(vcpu, u32 last_inst = kvmppc_get_last_inst(vcpu);
kvmppc_get_last_inst(vcpu)); u32 dsisr;
vcpu->arch.shared->dar = kvmppc_alignment_dar(vcpu, u64 dar;
kvmppc_get_last_inst(vcpu));
dsisr = kvmppc_alignment_dsisr(vcpu, last_inst);
dar = kvmppc_alignment_dar(vcpu, last_inst);
kvmppc_set_dsisr(vcpu, dsisr);
kvmppc_set_dar(vcpu, dar);
kvmppc_book3s_queue_irqprio(vcpu, exit_nr); kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
} }
r = RESUME_GUEST; r = RESUME_GUEST;
break; break;
#ifdef CONFIG_PPC_BOOK3S_64
case BOOK3S_INTERRUPT_FAC_UNAVAIL:
kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56);
r = RESUME_GUEST;
break;
#endif
case BOOK3S_INTERRUPT_MACHINE_CHECK: case BOOK3S_INTERRUPT_MACHINE_CHECK:
case BOOK3S_INTERRUPT_TRACE: case BOOK3S_INTERRUPT_TRACE:
kvmppc_book3s_queue_irqprio(vcpu, exit_nr); kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
...@@ -1054,7 +1176,7 @@ static int kvm_arch_vcpu_ioctl_get_sregs_pr(struct kvm_vcpu *vcpu, ...@@ -1054,7 +1176,7 @@ static int kvm_arch_vcpu_ioctl_get_sregs_pr(struct kvm_vcpu *vcpu,
} }
} else { } else {
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
sregs->u.s.ppc32.sr[i] = vcpu->arch.shared->sr[i]; sregs->u.s.ppc32.sr[i] = kvmppc_get_sr(vcpu, i);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw; sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw;
...@@ -1110,6 +1232,15 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, ...@@ -1110,6 +1232,15 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_HIOR: case KVM_REG_PPC_HIOR:
*val = get_reg_val(id, to_book3s(vcpu)->hior); *val = get_reg_val(id, to_book3s(vcpu)->hior);
break; break;
case KVM_REG_PPC_LPCR:
/*
* We are only interested in the LPCR_ILE bit
*/
if (vcpu->arch.intr_msr & MSR_LE)
*val = get_reg_val(id, LPCR_ILE);
else
*val = get_reg_val(id, 0);
break;
default: default:
r = -EINVAL; r = -EINVAL;
break; break;
...@@ -1118,6 +1249,14 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, ...@@ -1118,6 +1249,14 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
return r; return r;
} }
static void kvmppc_set_lpcr_pr(struct kvm_vcpu *vcpu, u64 new_lpcr)
{
if (new_lpcr & LPCR_ILE)
vcpu->arch.intr_msr |= MSR_LE;
else
vcpu->arch.intr_msr &= ~MSR_LE;
}
static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
union kvmppc_one_reg *val) union kvmppc_one_reg *val)
{ {
...@@ -1128,6 +1267,9 @@ static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, ...@@ -1128,6 +1267,9 @@ static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
to_book3s(vcpu)->hior = set_reg_val(id, *val); to_book3s(vcpu)->hior = set_reg_val(id, *val);
to_book3s(vcpu)->hior_explicit = true; to_book3s(vcpu)->hior_explicit = true;
break; break;
case KVM_REG_PPC_LPCR:
kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val));
break;
default: default:
r = -EINVAL; r = -EINVAL;
break; break;
...@@ -1170,8 +1312,14 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm, ...@@ -1170,8 +1312,14 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm,
goto uninit_vcpu; goto uninit_vcpu;
/* the real shared page fills the last 4k of our page */ /* the real shared page fills the last 4k of our page */
vcpu->arch.shared = (void *)(p + PAGE_SIZE - 4096); vcpu->arch.shared = (void *)(p + PAGE_SIZE - 4096);
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
/* Always start the shared struct in native endian mode */
#ifdef __BIG_ENDIAN__
vcpu->arch.shared_big_endian = true;
#else
vcpu->arch.shared_big_endian = false;
#endif
/* /*
* Default to the same as the host if we're on sufficiently * Default to the same as the host if we're on sufficiently
* recent machine that we have 1TB segments; * recent machine that we have 1TB segments;
...@@ -1180,6 +1328,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm, ...@@ -1180,6 +1328,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm,
vcpu->arch.pvr = 0x3C0301; vcpu->arch.pvr = 0x3C0301;
if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
vcpu->arch.pvr = mfspr(SPRN_PVR); vcpu->arch.pvr = mfspr(SPRN_PVR);
vcpu->arch.intr_msr = MSR_SF;
#else #else
/* default to book3s_32 (750) */ /* default to book3s_32 (750) */
vcpu->arch.pvr = 0x84202; vcpu->arch.pvr = 0x84202;
...@@ -1187,7 +1336,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm, ...@@ -1187,7 +1336,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm,
kvmppc_set_pvr_pr(vcpu, vcpu->arch.pvr); kvmppc_set_pvr_pr(vcpu, vcpu->arch.pvr);
vcpu->arch.slb_nr = 64; vcpu->arch.slb_nr = 64;
vcpu->arch.shadow_msr = MSR_USER64; vcpu->arch.shadow_msr = MSR_USER64 & ~MSR_LE;
err = kvmppc_mmu_init(vcpu); err = kvmppc_mmu_init(vcpu);
if (err < 0) if (err < 0)
...@@ -1264,7 +1413,7 @@ static int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) ...@@ -1264,7 +1413,7 @@ static int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
#endif #endif
/* Preload FPU if it's enabled */ /* Preload FPU if it's enabled */
if (vcpu->arch.shared->msr & MSR_FP) if (kvmppc_get_msr(vcpu) & MSR_FP)
kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
kvmppc_fix_ee_before_entry(); kvmppc_fix_ee_before_entry();
...@@ -1277,6 +1426,9 @@ static int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) ...@@ -1277,6 +1426,9 @@ static int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
/* Make sure we save the guest FPU/Altivec/VSX state */ /* Make sure we save the guest FPU/Altivec/VSX state */
kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX); kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
/* Make sure we save the guest TAR/EBB/DSCR state */
kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
out: out:
vcpu->mode = OUTSIDE_GUEST_MODE; vcpu->mode = OUTSIDE_GUEST_MODE;
return ret; return ret;
......
...@@ -57,7 +57,7 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu) ...@@ -57,7 +57,7 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
for (i = 0; ; ++i) { for (i = 0; ; ++i) {
if (i == 8) if (i == 8)
goto done; goto done;
if ((*hpte & HPTE_V_VALID) == 0) if ((be64_to_cpu(*hpte) & HPTE_V_VALID) == 0)
break; break;
hpte += 2; hpte += 2;
} }
...@@ -67,8 +67,8 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu) ...@@ -67,8 +67,8 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
goto done; goto done;
} }
hpte[0] = kvmppc_get_gpr(vcpu, 6); hpte[0] = cpu_to_be64(kvmppc_get_gpr(vcpu, 6));
hpte[1] = kvmppc_get_gpr(vcpu, 7); hpte[1] = cpu_to_be64(kvmppc_get_gpr(vcpu, 7));
pteg_addr += i * HPTE_SIZE; pteg_addr += i * HPTE_SIZE;
copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE); copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE);
kvmppc_set_gpr(vcpu, 4, pte_index | i); kvmppc_set_gpr(vcpu, 4, pte_index | i);
...@@ -93,6 +93,8 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu) ...@@ -93,6 +93,8 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
pteg = get_pteg_addr(vcpu, pte_index); pteg = get_pteg_addr(vcpu, pte_index);
mutex_lock(&vcpu->kvm->arch.hpt_mutex); mutex_lock(&vcpu->kvm->arch.hpt_mutex);
copy_from_user(pte, (void __user *)pteg, sizeof(pte)); copy_from_user(pte, (void __user *)pteg, sizeof(pte));
pte[0] = be64_to_cpu(pte[0]);
pte[1] = be64_to_cpu(pte[1]);
ret = H_NOT_FOUND; ret = H_NOT_FOUND;
if ((pte[0] & HPTE_V_VALID) == 0 || if ((pte[0] & HPTE_V_VALID) == 0 ||
...@@ -169,6 +171,8 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu) ...@@ -169,6 +171,8 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX); pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX);
copy_from_user(pte, (void __user *)pteg, sizeof(pte)); copy_from_user(pte, (void __user *)pteg, sizeof(pte));
pte[0] = be64_to_cpu(pte[0]);
pte[1] = be64_to_cpu(pte[1]);
/* tsl = AVPN */ /* tsl = AVPN */
flags = (tsh & H_BULK_REMOVE_FLAGS) >> 26; flags = (tsh & H_BULK_REMOVE_FLAGS) >> 26;
...@@ -207,6 +211,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) ...@@ -207,6 +211,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
pteg = get_pteg_addr(vcpu, pte_index); pteg = get_pteg_addr(vcpu, pte_index);
mutex_lock(&vcpu->kvm->arch.hpt_mutex); mutex_lock(&vcpu->kvm->arch.hpt_mutex);
copy_from_user(pte, (void __user *)pteg, sizeof(pte)); copy_from_user(pte, (void __user *)pteg, sizeof(pte));
pte[0] = be64_to_cpu(pte[0]);
pte[1] = be64_to_cpu(pte[1]);
ret = H_NOT_FOUND; ret = H_NOT_FOUND;
if ((pte[0] & HPTE_V_VALID) == 0 || if ((pte[0] & HPTE_V_VALID) == 0 ||
...@@ -225,6 +231,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) ...@@ -225,6 +231,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
rb = compute_tlbie_rb(v, r, pte_index); rb = compute_tlbie_rb(v, r, pte_index);
vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false); vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
pte[0] = cpu_to_be64(pte[0]);
pte[1] = cpu_to_be64(pte[1]);
copy_to_user((void __user *)pteg, pte, sizeof(pte)); copy_to_user((void __user *)pteg, pte, sizeof(pte));
ret = H_SUCCESS; ret = H_SUCCESS;
...@@ -270,7 +278,7 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) ...@@ -270,7 +278,7 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
case H_PUT_TCE: case H_PUT_TCE:
return kvmppc_h_pr_put_tce(vcpu); return kvmppc_h_pr_put_tce(vcpu);
case H_CEDE: case H_CEDE:
vcpu->arch.shared->msr |= MSR_EE; kvmppc_set_msr_fast(vcpu, kvmppc_get_msr(vcpu) | MSR_EE);
kvm_vcpu_block(vcpu); kvm_vcpu_block(vcpu);
clear_bit(KVM_REQ_UNHALT, &vcpu->requests); clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
vcpu->stat.halt_wakeup++; vcpu->stat.halt_wakeup++;
......
...@@ -205,6 +205,32 @@ int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp) ...@@ -205,6 +205,32 @@ int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp)
return rc; return rc;
} }
static void kvmppc_rtas_swap_endian_in(struct rtas_args *args)
{
#ifdef __LITTLE_ENDIAN__
int i;
args->token = be32_to_cpu(args->token);
args->nargs = be32_to_cpu(args->nargs);
args->nret = be32_to_cpu(args->nret);
for (i = 0; i < args->nargs; i++)
args->args[i] = be32_to_cpu(args->args[i]);
#endif
}
static void kvmppc_rtas_swap_endian_out(struct rtas_args *args)
{
#ifdef __LITTLE_ENDIAN__
int i;
for (i = 0; i < args->nret; i++)
args->args[i] = cpu_to_be32(args->args[i]);
args->token = cpu_to_be32(args->token);
args->nargs = cpu_to_be32(args->nargs);
args->nret = cpu_to_be32(args->nret);
#endif
}
int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu) int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
{ {
struct rtas_token_definition *d; struct rtas_token_definition *d;
...@@ -223,6 +249,8 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu) ...@@ -223,6 +249,8 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
if (rc) if (rc)
goto fail; goto fail;
kvmppc_rtas_swap_endian_in(&args);
/* /*
* args->rets is a pointer into args->args. Now that we've * args->rets is a pointer into args->args. Now that we've
* copied args we need to fix it up to point into our copy, * copied args we need to fix it up to point into our copy,
...@@ -247,6 +275,7 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu) ...@@ -247,6 +275,7 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
if (rc == 0) { if (rc == 0) {
args.rets = orig_rets; args.rets = orig_rets;
kvmppc_rtas_swap_endian_out(&args);
rc = kvm_write_guest(vcpu->kvm, args_phys, &args, sizeof(args)); rc = kvm_write_guest(vcpu->kvm, args_phys, &args, sizeof(args));
if (rc) if (rc)
goto fail; goto fail;
......
...@@ -90,6 +90,15 @@ kvmppc_handler_trampoline_enter: ...@@ -90,6 +90,15 @@ kvmppc_handler_trampoline_enter:
LOAD_GUEST_SEGMENTS LOAD_GUEST_SEGMENTS
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
BEGIN_FTR_SECTION
/* Save host FSCR */
mfspr r8, SPRN_FSCR
std r8, HSTATE_HOST_FSCR(r13)
/* Set FSCR during guest execution */
ld r9, SVCPU_SHADOW_FSCR(r13)
mtspr SPRN_FSCR, r9
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
/* Some guests may need to have dcbz set to 32 byte length. /* Some guests may need to have dcbz set to 32 byte length.
* *
* Usually we ensure that by patching the guest's instructions * Usually we ensure that by patching the guest's instructions
...@@ -255,6 +264,10 @@ BEGIN_FTR_SECTION ...@@ -255,6 +264,10 @@ BEGIN_FTR_SECTION
cmpwi r12, BOOK3S_INTERRUPT_H_EMUL_ASSIST cmpwi r12, BOOK3S_INTERRUPT_H_EMUL_ASSIST
beq- ld_last_inst beq- ld_last_inst
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
BEGIN_FTR_SECTION
cmpwi r12, BOOK3S_INTERRUPT_FAC_UNAVAIL
beq- ld_last_inst
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
#endif #endif
b no_ld_last_inst b no_ld_last_inst
...@@ -311,6 +324,18 @@ no_ld_last_inst: ...@@ -311,6 +324,18 @@ no_ld_last_inst:
no_dcbz32_off: no_dcbz32_off:
BEGIN_FTR_SECTION
/* Save guest FSCR on a FAC_UNAVAIL interrupt */
cmpwi r12, BOOK3S_INTERRUPT_FAC_UNAVAIL
bne+ no_fscr_save
mfspr r7, SPRN_FSCR
std r7, SVCPU_SHADOW_FSCR(r13)
no_fscr_save:
/* Restore host FSCR */
ld r8, HSTATE_HOST_FSCR(r13)
mtspr SPRN_FSCR, r8
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
#endif /* CONFIG_PPC_BOOK3S_64 */ #endif /* CONFIG_PPC_BOOK3S_64 */
/* /*
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "booke.h" #include "booke.h"
#include "e500.h" #include "e500.h"
#define XOP_DCBTLS 166
#define XOP_MSGSND 206 #define XOP_MSGSND 206
#define XOP_MSGCLR 238 #define XOP_MSGCLR 238
#define XOP_TLBIVAX 786 #define XOP_TLBIVAX 786
...@@ -103,6 +104,15 @@ static int kvmppc_e500_emul_ehpriv(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -103,6 +104,15 @@ static int kvmppc_e500_emul_ehpriv(struct kvm_run *run, struct kvm_vcpu *vcpu,
return emulated; return emulated;
} }
static int kvmppc_e500_emul_dcbtls(struct kvm_vcpu *vcpu)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
/* Always fail to lock the cache */
vcpu_e500->l1csr0 |= L1CSR0_CUL;
return EMULATE_DONE;
}
int kvmppc_core_emulate_op_e500(struct kvm_run *run, struct kvm_vcpu *vcpu, int kvmppc_core_emulate_op_e500(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned int inst, int *advance) unsigned int inst, int *advance)
{ {
...@@ -116,6 +126,10 @@ int kvmppc_core_emulate_op_e500(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -116,6 +126,10 @@ int kvmppc_core_emulate_op_e500(struct kvm_run *run, struct kvm_vcpu *vcpu,
case 31: case 31:
switch (get_xop(inst)) { switch (get_xop(inst)) {
case XOP_DCBTLS:
emulated = kvmppc_e500_emul_dcbtls(vcpu);
break;
#ifdef CONFIG_KVM_E500MC #ifdef CONFIG_KVM_E500MC
case XOP_MSGSND: case XOP_MSGSND:
emulated = kvmppc_e500_emul_msgsnd(vcpu, rb); emulated = kvmppc_e500_emul_msgsnd(vcpu, rb);
...@@ -222,6 +236,7 @@ int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va ...@@ -222,6 +236,7 @@ int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va
break; break;
case SPRN_L1CSR1: case SPRN_L1CSR1:
vcpu_e500->l1csr1 = spr_val; vcpu_e500->l1csr1 = spr_val;
vcpu_e500->l1csr1 &= ~(L1CSR1_ICFI | L1CSR1_ICLFR);
break; break;
case SPRN_HID0: case SPRN_HID0:
vcpu_e500->hid0 = spr_val; vcpu_e500->hid0 = spr_val;
......
...@@ -97,10 +97,10 @@ static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) ...@@ -97,10 +97,10 @@ static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
switch (sprn) { switch (sprn) {
case SPRN_SRR0: case SPRN_SRR0:
vcpu->arch.shared->srr0 = spr_val; kvmppc_set_srr0(vcpu, spr_val);
break; break;
case SPRN_SRR1: case SPRN_SRR1:
vcpu->arch.shared->srr1 = spr_val; kvmppc_set_srr1(vcpu, spr_val);
break; break;
/* XXX We need to context-switch the timebase for /* XXX We need to context-switch the timebase for
...@@ -114,16 +114,16 @@ static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) ...@@ -114,16 +114,16 @@ static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
break; break;
case SPRN_SPRG0: case SPRN_SPRG0:
vcpu->arch.shared->sprg0 = spr_val; kvmppc_set_sprg0(vcpu, spr_val);
break; break;
case SPRN_SPRG1: case SPRN_SPRG1:
vcpu->arch.shared->sprg1 = spr_val; kvmppc_set_sprg1(vcpu, spr_val);
break; break;
case SPRN_SPRG2: case SPRN_SPRG2:
vcpu->arch.shared->sprg2 = spr_val; kvmppc_set_sprg2(vcpu, spr_val);
break; break;
case SPRN_SPRG3: case SPRN_SPRG3:
vcpu->arch.shared->sprg3 = spr_val; kvmppc_set_sprg3(vcpu, spr_val);
break; break;
/* PIR can legally be written, but we ignore it */ /* PIR can legally be written, but we ignore it */
...@@ -150,10 +150,10 @@ static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) ...@@ -150,10 +150,10 @@ static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
switch (sprn) { switch (sprn) {
case SPRN_SRR0: case SPRN_SRR0:
spr_val = vcpu->arch.shared->srr0; spr_val = kvmppc_get_srr0(vcpu);
break; break;
case SPRN_SRR1: case SPRN_SRR1:
spr_val = vcpu->arch.shared->srr1; spr_val = kvmppc_get_srr1(vcpu);
break; break;
case SPRN_PVR: case SPRN_PVR:
spr_val = vcpu->arch.pvr; spr_val = vcpu->arch.pvr;
...@@ -173,16 +173,16 @@ static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) ...@@ -173,16 +173,16 @@ static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
break; break;
case SPRN_SPRG0: case SPRN_SPRG0:
spr_val = vcpu->arch.shared->sprg0; spr_val = kvmppc_get_sprg0(vcpu);
break; break;
case SPRN_SPRG1: case SPRN_SPRG1:
spr_val = vcpu->arch.shared->sprg1; spr_val = kvmppc_get_sprg1(vcpu);
break; break;
case SPRN_SPRG2: case SPRN_SPRG2:
spr_val = vcpu->arch.shared->sprg2; spr_val = kvmppc_get_sprg2(vcpu);
break; break;
case SPRN_SPRG3: case SPRN_SPRG3:
spr_val = vcpu->arch.shared->sprg3; spr_val = kvmppc_get_sprg3(vcpu);
break; break;
/* Note: SPRG4-7 are user-readable, so we don't get /* Note: SPRG4-7 are user-readable, so we don't get
* a trap. */ * a trap. */
......
...@@ -126,6 +126,8 @@ static int openpic_cpu_write_internal(void *opaque, gpa_t addr, ...@@ -126,6 +126,8 @@ static int openpic_cpu_write_internal(void *opaque, gpa_t addr,
u32 val, int idx); u32 val, int idx);
static int openpic_cpu_read_internal(void *opaque, gpa_t addr, static int openpic_cpu_read_internal(void *opaque, gpa_t addr,
u32 *ptr, int idx); u32 *ptr, int idx);
static inline void write_IRQreg_idr(struct openpic *opp, int n_IRQ,
uint32_t val);
enum irq_type { enum irq_type {
IRQ_TYPE_NORMAL = 0, IRQ_TYPE_NORMAL = 0,
...@@ -528,7 +530,6 @@ static void openpic_reset(struct openpic *opp) ...@@ -528,7 +530,6 @@ static void openpic_reset(struct openpic *opp)
/* Initialise IRQ sources */ /* Initialise IRQ sources */
for (i = 0; i < opp->max_irq; i++) { for (i = 0; i < opp->max_irq; i++) {
opp->src[i].ivpr = opp->ivpr_reset; opp->src[i].ivpr = opp->ivpr_reset;
opp->src[i].idr = opp->idr_reset;
switch (opp->src[i].type) { switch (opp->src[i].type) {
case IRQ_TYPE_NORMAL: case IRQ_TYPE_NORMAL:
...@@ -543,6 +544,8 @@ static void openpic_reset(struct openpic *opp) ...@@ -543,6 +544,8 @@ static void openpic_reset(struct openpic *opp)
case IRQ_TYPE_FSLSPECIAL: case IRQ_TYPE_FSLSPECIAL:
break; break;
} }
write_IRQreg_idr(opp, i, opp->idr_reset);
} }
/* Initialise IRQ destinations */ /* Initialise IRQ destinations */
for (i = 0; i < MAX_CPU; i++) { for (i = 0; i < MAX_CPU; i++) {
......
...@@ -125,6 +125,27 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu) ...@@ -125,6 +125,27 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
} }
EXPORT_SYMBOL_GPL(kvmppc_prepare_to_enter); EXPORT_SYMBOL_GPL(kvmppc_prepare_to_enter);
#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
static void kvmppc_swab_shared(struct kvm_vcpu *vcpu)
{
struct kvm_vcpu_arch_shared *shared = vcpu->arch.shared;
int i;
shared->sprg0 = swab64(shared->sprg0);
shared->sprg1 = swab64(shared->sprg1);
shared->sprg2 = swab64(shared->sprg2);
shared->sprg3 = swab64(shared->sprg3);
shared->srr0 = swab64(shared->srr0);
shared->srr1 = swab64(shared->srr1);
shared->dar = swab64(shared->dar);
shared->msr = swab64(shared->msr);
shared->dsisr = swab32(shared->dsisr);
shared->int_pending = swab32(shared->int_pending);
for (i = 0; i < ARRAY_SIZE(shared->sr); i++)
shared->sr[i] = swab32(shared->sr[i]);
}
#endif
int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
{ {
int nr = kvmppc_get_gpr(vcpu, 11); int nr = kvmppc_get_gpr(vcpu, 11);
...@@ -135,7 +156,7 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) ...@@ -135,7 +156,7 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
unsigned long __maybe_unused param4 = kvmppc_get_gpr(vcpu, 6); unsigned long __maybe_unused param4 = kvmppc_get_gpr(vcpu, 6);
unsigned long r2 = 0; unsigned long r2 = 0;
if (!(vcpu->arch.shared->msr & MSR_SF)) { if (!(kvmppc_get_msr(vcpu) & MSR_SF)) {
/* 32 bit mode */ /* 32 bit mode */
param1 &= 0xffffffff; param1 &= 0xffffffff;
param2 &= 0xffffffff; param2 &= 0xffffffff;
...@@ -146,8 +167,28 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) ...@@ -146,8 +167,28 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
switch (nr) { switch (nr) {
case KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE): case KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE):
{ {
vcpu->arch.magic_page_pa = param1; #if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
vcpu->arch.magic_page_ea = param2; /* Book3S can be little endian, find it out here */
int shared_big_endian = true;
if (vcpu->arch.intr_msr & MSR_LE)
shared_big_endian = false;
if (shared_big_endian != vcpu->arch.shared_big_endian)
kvmppc_swab_shared(vcpu);
vcpu->arch.shared_big_endian = shared_big_endian;
#endif
if (!(param2 & MAGIC_PAGE_FLAG_NOT_MAPPED_NX)) {
/*
* Older versions of the Linux magic page code had
* a bug where they would map their trampoline code
* NX. If that's the case, remove !PR NX capability.
*/
vcpu->arch.disable_kernel_nx = true;
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
}
vcpu->arch.magic_page_pa = param1 & ~0xfffULL;
vcpu->arch.magic_page_ea = param2 & ~0xfffULL;
r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7; r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7;
...@@ -375,6 +416,7 @@ int kvm_dev_ioctl_check_extension(long ext) ...@@ -375,6 +416,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_SPAPR_TCE: case KVM_CAP_SPAPR_TCE:
case KVM_CAP_PPC_ALLOC_HTAB: case KVM_CAP_PPC_ALLOC_HTAB:
case KVM_CAP_PPC_RTAS: case KVM_CAP_PPC_RTAS:
case KVM_CAP_PPC_FIXUP_HCALL:
#ifdef CONFIG_KVM_XICS #ifdef CONFIG_KVM_XICS
case KVM_CAP_IRQ_XICS: case KVM_CAP_IRQ_XICS:
#endif #endif
...@@ -1015,10 +1057,10 @@ static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo) ...@@ -1015,10 +1057,10 @@ static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
u32 inst_nop = 0x60000000; u32 inst_nop = 0x60000000;
#ifdef CONFIG_KVM_BOOKE_HV #ifdef CONFIG_KVM_BOOKE_HV
u32 inst_sc1 = 0x44000022; u32 inst_sc1 = 0x44000022;
pvinfo->hcall[0] = inst_sc1; pvinfo->hcall[0] = cpu_to_be32(inst_sc1);
pvinfo->hcall[1] = inst_nop; pvinfo->hcall[1] = cpu_to_be32(inst_nop);
pvinfo->hcall[2] = inst_nop; pvinfo->hcall[2] = cpu_to_be32(inst_nop);
pvinfo->hcall[3] = inst_nop; pvinfo->hcall[3] = cpu_to_be32(inst_nop);
#else #else
u32 inst_lis = 0x3c000000; u32 inst_lis = 0x3c000000;
u32 inst_ori = 0x60000000; u32 inst_ori = 0x60000000;
...@@ -1034,10 +1076,10 @@ static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo) ...@@ -1034,10 +1076,10 @@ static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
* sc * sc
* nop * nop
*/ */
pvinfo->hcall[0] = inst_lis | ((KVM_SC_MAGIC_R0 >> 16) & inst_imm_mask); pvinfo->hcall[0] = cpu_to_be32(inst_lis | ((KVM_SC_MAGIC_R0 >> 16) & inst_imm_mask));
pvinfo->hcall[1] = inst_ori | (KVM_SC_MAGIC_R0 & inst_imm_mask); pvinfo->hcall[1] = cpu_to_be32(inst_ori | (KVM_SC_MAGIC_R0 & inst_imm_mask));
pvinfo->hcall[2] = inst_sc; pvinfo->hcall[2] = cpu_to_be32(inst_sc);
pvinfo->hcall[3] = inst_nop; pvinfo->hcall[3] = cpu_to_be32(inst_nop);
#endif #endif
pvinfo->flags = KVM_PPC_PVINFO_FLAGS_EV_IDLE; pvinfo->flags = KVM_PPC_PVINFO_FLAGS_EV_IDLE;
......
...@@ -255,7 +255,7 @@ TRACE_EVENT(kvm_exit, ...@@ -255,7 +255,7 @@ TRACE_EVENT(kvm_exit,
__entry->exit_nr = exit_nr; __entry->exit_nr = exit_nr;
__entry->pc = kvmppc_get_pc(vcpu); __entry->pc = kvmppc_get_pc(vcpu);
__entry->dar = kvmppc_get_fault_dar(vcpu); __entry->dar = kvmppc_get_fault_dar(vcpu);
__entry->msr = vcpu->arch.shared->msr; __entry->msr = kvmppc_get_msr(vcpu);
__entry->srr1 = vcpu->arch.shadow_srr1; __entry->srr1 = vcpu->arch.shadow_srr1;
__entry->last_inst = vcpu->arch.last_inst; __entry->last_inst = vcpu->arch.last_inst;
), ),
......
...@@ -97,7 +97,7 @@ static inline void create_shadowed_slbe(unsigned long ea, int ssize, ...@@ -97,7 +97,7 @@ static inline void create_shadowed_slbe(unsigned long ea, int ssize,
static void __slb_flush_and_rebolt(void) static void __slb_flush_and_rebolt(void)
{ {
/* If you change this make sure you change SLB_NUM_BOLTED /* If you change this make sure you change SLB_NUM_BOLTED
* appropriately too. */ * and PR KVM appropriately too. */
unsigned long linear_llp, vmalloc_llp, lflags, vflags; unsigned long linear_llp, vmalloc_llp, lflags, vflags;
unsigned long ksp_esid_data, ksp_vsid_data; unsigned long ksp_esid_data, ksp_vsid_data;
......
...@@ -757,6 +757,7 @@ struct kvm_ppc_smmu_info { ...@@ -757,6 +757,7 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_IOEVENTFD_NO_LENGTH 100 #define KVM_CAP_IOEVENTFD_NO_LENGTH 100
#define KVM_CAP_VM_ATTRIBUTES 101 #define KVM_CAP_VM_ATTRIBUTES 101
#define KVM_CAP_ARM_PSCI_0_2 102 #define KVM_CAP_ARM_PSCI_0_2 102
#define KVM_CAP_PPC_FIXUP_HCALL 103
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment