diff options
| -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) |
