aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2014-05-12 07:34:06 -0400
committerAlexander Graf <agraf@suse.de>2014-05-30 08:26:25 -0400
commitddca156ae6bafc0c6af61805bfe4b37440448a4c (patch)
treedca98cfc431c64d2b5a5a5b68e6f53df3a27f1c3
parent7310f3a5b0ecc7ac8b57e70fe395968cbe0fc40a (diff)
KVM: PPC: BOOK3S: Remove open coded make_dsisr in alignment handler
Use make_dsisr instead of open coding it. This also have the added benefit of handling alignment interrupt on additional instructions. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Alexander Graf <agraf@suse.de>
-rw-r--r--arch/powerpc/include/asm/disassemble.h34
-rw-r--r--arch/powerpc/kernel/align.c34
-rw-r--r--arch/powerpc/kvm/book3s_emulate.c39
3 files changed, 36 insertions, 71 deletions
diff --git a/arch/powerpc/include/asm/disassemble.h b/arch/powerpc/include/asm/disassemble.h
index 856f8deb557a..6330a61b875a 100644
--- a/arch/powerpc/include/asm/disassemble.h
+++ b/arch/powerpc/include/asm/disassemble.h
@@ -81,4 +81,38 @@ static inline unsigned int get_oc(u32 inst)
81{ 81{
82 return (inst >> 11) & 0x7fff; 82 return (inst >> 11) & 0x7fff;
83} 83}
84
85#define IS_XFORM(inst) (get_op(inst) == 31)
86#define IS_DSFORM(inst) (get_op(inst) >= 56)
87
88/*
89 * Create a DSISR value from the instruction
90 */
91static inline unsigned make_dsisr(unsigned instr)
92{
93 unsigned dsisr;
94
95
96 /* bits 6:15 --> 22:31 */
97 dsisr = (instr & 0x03ff0000) >> 16;
98
99 if (IS_XFORM(instr)) {
100 /* bits 29:30 --> 15:16 */
101 dsisr |= (instr & 0x00000006) << 14;
102 /* bit 25 --> 17 */
103 dsisr |= (instr & 0x00000040) << 8;
104 /* bits 21:24 --> 18:21 */
105 dsisr |= (instr & 0x00000780) << 3;
106 } else {
107 /* bit 5 --> 17 */
108 dsisr |= (instr & 0x04000000) >> 12;
109 /* bits 1: 4 --> 18:21 */
110 dsisr |= (instr & 0x78000000) >> 17;
111 /* bits 30:31 --> 12:13 */
112 if (IS_DSFORM(instr))
113 dsisr |= (instr & 0x00000003) << 18;
114 }
115
116 return dsisr;
117}
84#endif /* __ASM_PPC_DISASSEMBLE_H__ */ 118#endif /* __ASM_PPC_DISASSEMBLE_H__ */
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 94908af308d8..34f55524d456 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -25,14 +25,13 @@
25#include <asm/cputable.h> 25#include <asm/cputable.h>
26#include <asm/emulated_ops.h> 26#include <asm/emulated_ops.h>
27#include <asm/switch_to.h> 27#include <asm/switch_to.h>
28#include <asm/disassemble.h>
28 29
29struct aligninfo { 30struct aligninfo {
30 unsigned char len; 31 unsigned char len;
31 unsigned char flags; 32 unsigned char flags;
32}; 33};
33 34
34#define IS_XFORM(inst) (((inst) >> 26) == 31)
35#define IS_DSFORM(inst) (((inst) >> 26) >= 56)
36 35
37#define INVALID { 0, 0 } 36#define INVALID { 0, 0 }
38 37
@@ -192,37 +191,6 @@ static struct aligninfo aligninfo[128] = {
192}; 191};
193 192
194/* 193/*
195 * Create a DSISR value from the instruction
196 */
197static inline unsigned make_dsisr(unsigned instr)
198{
199 unsigned dsisr;
200
201
202 /* bits 6:15 --> 22:31 */
203 dsisr = (instr & 0x03ff0000) >> 16;
204
205 if (IS_XFORM(instr)) {
206 /* bits 29:30 --> 15:16 */
207 dsisr |= (instr & 0x00000006) << 14;
208 /* bit 25 --> 17 */
209 dsisr |= (instr & 0x00000040) << 8;
210 /* bits 21:24 --> 18:21 */
211 dsisr |= (instr & 0x00000780) << 3;
212 } else {
213 /* bit 5 --> 17 */
214 dsisr |= (instr & 0x04000000) >> 12;
215 /* bits 1: 4 --> 18:21 */
216 dsisr |= (instr & 0x78000000) >> 17;
217 /* bits 30:31 --> 12:13 */
218 if (IS_DSFORM(instr))
219 dsisr |= (instr & 0x00000003) << 18;
220 }
221
222 return dsisr;
223}
224
225/*
226 * The dcbz (data cache block zero) instruction 194 * The dcbz (data cache block zero) instruction
227 * gives an alignment fault if used on non-cacheable 195 * gives an alignment fault if used on non-cacheable
228 * memory. We handle the fault mainly for the 196 * memory. We handle the fault mainly for the
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 61f38eb470b3..c9924475368f 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -634,44 +634,7 @@ unprivileged:
634 634
635u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst) 635u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst)
636{ 636{
637 u32 dsisr = 0; 637 return make_dsisr(inst);
638
639 /*
640 * This is what the spec says about DSISR bits (not mentioned = 0):
641 *
642 * 12:13 [DS] Set to bits 30:31
643 * 15:16 [X] Set to bits 29:30
644 * 17 [X] Set to bit 25
645 * [D/DS] Set to bit 5
646 * 18:21 [X] Set to bits 21:24
647 * [D/DS] Set to bits 1:4
648 * 22:26 Set to bits 6:10 (RT/RS/FRT/FRS)
649 * 27:31 Set to bits 11:15 (RA)
650 */
651
652 switch (get_op(inst)) {
653 /* D-form */
654 case OP_LFS:
655 case OP_LFD:
656 case OP_STFD:
657 case OP_STFS:
658 dsisr |= (inst >> 12) & 0x4000; /* bit 17 */
659 dsisr |= (inst >> 17) & 0x3c00; /* bits 18:21 */
660 break;
661 /* X-form */
662 case 31:
663 dsisr |= (inst << 14) & 0x18000; /* bits 15:16 */
664 dsisr |= (inst << 8) & 0x04000; /* bit 17 */
665 dsisr |= (inst << 3) & 0x03c00; /* bits 18:21 */
666 break;
667 default:
668 printk(KERN_INFO "KVM: Unaligned instruction 0x%x\n", inst);
669 break;
670 }
671
672 dsisr |= (inst >> 16) & 0x03ff; /* bits 22:31 */
673
674 return dsisr;
675} 638}
676 639
677ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst) 640ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst)