diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2014-05-12 07:34:06 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-05-30 08:26:25 -0400 |
commit | ddca156ae6bafc0c6af61805bfe4b37440448a4c (patch) | |
tree | dca98cfc431c64d2b5a5a5b68e6f53df3a27f1c3 | |
parent | 7310f3a5b0ecc7ac8b57e70fe395968cbe0fc40a (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.h | 34 | ||||
-rw-r--r-- | arch/powerpc/kernel/align.c | 34 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_emulate.c | 39 |
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 | */ | ||
91 | static 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 | ||
29 | struct aligninfo { | 30 | struct 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 | */ | ||
197 | static 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 | ||
635 | u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst) | 635 | u32 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 | ||
677 | ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst) | 640 | ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst) |