]>
Commit | Line | Data |
---|---|---|
bc8080cb | 1 | /* |
5ce941ee | 2 | * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved. |
bc8080cb HB |
3 | * |
4 | * Author: Yu Liu, <yu.liu@freescale.com> | |
5 | * | |
6 | * Description: | |
7 | * This file is derived from arch/powerpc/kvm/44x_emulate.c, | |
8 | * by Hollis Blanchard <hollisb@us.ibm.com>. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License, version 2, as | |
12 | * published by the Free Software Foundation. | |
13 | */ | |
14 | ||
15 | #include <asm/kvm_ppc.h> | |
16 | #include <asm/disassemble.h> | |
bc8080cb HB |
17 | |
18 | #include "booke.h" | |
29a5a6f9 | 19 | #include "e500.h" |
bc8080cb HB |
20 | |
21 | #define XOP_TLBIVAX 786 | |
22 | #define XOP_TLBSX 914 | |
23 | #define XOP_TLBRE 946 | |
24 | #define XOP_TLBWE 978 | |
ab9fc405 | 25 | #define XOP_TLBILX 18 |
bc8080cb HB |
26 | |
27 | int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |
28 | unsigned int inst, int *advance) | |
29 | { | |
30 | int emulated = EMULATE_DONE; | |
31 | int ra; | |
32 | int rb; | |
ab9fc405 | 33 | int rt; |
bc8080cb HB |
34 | |
35 | switch (get_op(inst)) { | |
36 | case 31: | |
37 | switch (get_xop(inst)) { | |
38 | ||
39 | case XOP_TLBRE: | |
40 | emulated = kvmppc_e500_emul_tlbre(vcpu); | |
41 | break; | |
42 | ||
43 | case XOP_TLBWE: | |
44 | emulated = kvmppc_e500_emul_tlbwe(vcpu); | |
45 | break; | |
46 | ||
47 | case XOP_TLBSX: | |
48 | rb = get_rb(inst); | |
49 | emulated = kvmppc_e500_emul_tlbsx(vcpu,rb); | |
50 | break; | |
51 | ||
ab9fc405 SW |
52 | case XOP_TLBILX: |
53 | ra = get_ra(inst); | |
54 | rb = get_rb(inst); | |
55 | rt = get_rt(inst); | |
56 | emulated = kvmppc_e500_emul_tlbilx(vcpu, rt, ra, rb); | |
57 | break; | |
58 | ||
bc8080cb HB |
59 | case XOP_TLBIVAX: |
60 | ra = get_ra(inst); | |
61 | rb = get_rb(inst); | |
62 | emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb); | |
63 | break; | |
64 | ||
65 | default: | |
66 | emulated = EMULATE_FAIL; | |
67 | } | |
68 | ||
69 | break; | |
70 | ||
71 | default: | |
72 | emulated = EMULATE_FAIL; | |
73 | } | |
74 | ||
75 | if (emulated == EMULATE_FAIL) | |
76 | emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance); | |
77 | ||
78 | return emulated; | |
79 | } | |
80 | ||
81 | int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | |
82 | { | |
83 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | |
84 | int emulated = EMULATE_DONE; | |
8e5b26b5 | 85 | ulong spr_val = kvmppc_get_gpr(vcpu, rs); |
bc8080cb HB |
86 | |
87 | switch (sprn) { | |
73196cd3 | 88 | #ifndef CONFIG_KVM_BOOKE_HV |
bc8080cb | 89 | case SPRN_PID: |
5ce941ee | 90 | kvmppc_set_pid(vcpu, spr_val); |
bc8080cb HB |
91 | break; |
92 | case SPRN_PID1: | |
dd9ebf1f LY |
93 | if (spr_val != 0) |
94 | return EMULATE_FAIL; | |
8e5b26b5 | 95 | vcpu_e500->pid[1] = spr_val; break; |
bc8080cb | 96 | case SPRN_PID2: |
dd9ebf1f LY |
97 | if (spr_val != 0) |
98 | return EMULATE_FAIL; | |
8e5b26b5 | 99 | vcpu_e500->pid[2] = spr_val; break; |
bc8080cb | 100 | case SPRN_MAS0: |
b5904972 | 101 | vcpu->arch.shared->mas0 = spr_val; break; |
bc8080cb | 102 | case SPRN_MAS1: |
b5904972 | 103 | vcpu->arch.shared->mas1 = spr_val; break; |
bc8080cb | 104 | case SPRN_MAS2: |
b5904972 | 105 | vcpu->arch.shared->mas2 = spr_val; break; |
bc8080cb | 106 | case SPRN_MAS3: |
b5904972 SW |
107 | vcpu->arch.shared->mas7_3 &= ~(u64)0xffffffff; |
108 | vcpu->arch.shared->mas7_3 |= spr_val; | |
dc83b8bc | 109 | break; |
bc8080cb | 110 | case SPRN_MAS4: |
b5904972 | 111 | vcpu->arch.shared->mas4 = spr_val; break; |
bc8080cb | 112 | case SPRN_MAS6: |
b5904972 | 113 | vcpu->arch.shared->mas6 = spr_val; break; |
bc8080cb | 114 | case SPRN_MAS7: |
b5904972 SW |
115 | vcpu->arch.shared->mas7_3 &= (u64)0xffffffff; |
116 | vcpu->arch.shared->mas7_3 |= (u64)spr_val << 32; | |
dc83b8bc | 117 | break; |
73196cd3 | 118 | #endif |
d86be077 LY |
119 | case SPRN_L1CSR0: |
120 | vcpu_e500->l1csr0 = spr_val; | |
121 | vcpu_e500->l1csr0 &= ~(L1CSR0_DCFI | L1CSR0_CLFC); | |
122 | break; | |
bc8080cb | 123 | case SPRN_L1CSR1: |
8e5b26b5 | 124 | vcpu_e500->l1csr1 = spr_val; break; |
bc8080cb | 125 | case SPRN_HID0: |
8e5b26b5 | 126 | vcpu_e500->hid0 = spr_val; break; |
bc8080cb | 127 | case SPRN_HID1: |
8e5b26b5 | 128 | vcpu_e500->hid1 = spr_val; break; |
bc8080cb | 129 | |
b0a1835d LY |
130 | case SPRN_MMUCSR0: |
131 | emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500, | |
8e5b26b5 | 132 | spr_val); |
b0a1835d LY |
133 | break; |
134 | ||
bb3a8a17 HB |
135 | /* extra exceptions */ |
136 | case SPRN_IVOR32: | |
8e5b26b5 | 137 | vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val; |
bb3a8a17 HB |
138 | break; |
139 | case SPRN_IVOR33: | |
8e5b26b5 | 140 | vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = spr_val; |
bb3a8a17 HB |
141 | break; |
142 | case SPRN_IVOR34: | |
8e5b26b5 | 143 | vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val; |
bb3a8a17 HB |
144 | break; |
145 | case SPRN_IVOR35: | |
8e5b26b5 | 146 | vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val; |
bb3a8a17 | 147 | break; |
73196cd3 SW |
148 | #ifdef CONFIG_KVM_BOOKE_HV |
149 | case SPRN_IVOR36: | |
150 | vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL] = spr_val; | |
151 | break; | |
152 | case SPRN_IVOR37: | |
153 | vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT] = spr_val; | |
154 | break; | |
155 | #endif | |
bc8080cb HB |
156 | default: |
157 | emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs); | |
158 | } | |
159 | ||
160 | return emulated; | |
161 | } | |
162 | ||
163 | int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) | |
164 | { | |
165 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | |
166 | int emulated = EMULATE_DONE; | |
167 | ||
168 | switch (sprn) { | |
73196cd3 SW |
169 | #ifndef CONFIG_KVM_BOOKE_HV |
170 | unsigned long val; | |
171 | ||
bc8080cb | 172 | case SPRN_PID: |
8e5b26b5 | 173 | kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[0]); break; |
bc8080cb | 174 | case SPRN_PID1: |
8e5b26b5 | 175 | kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[1]); break; |
bc8080cb | 176 | case SPRN_PID2: |
8e5b26b5 | 177 | kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[2]); break; |
bc8080cb | 178 | case SPRN_MAS0: |
b5904972 | 179 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas0); break; |
bc8080cb | 180 | case SPRN_MAS1: |
b5904972 | 181 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas1); break; |
bc8080cb | 182 | case SPRN_MAS2: |
b5904972 | 183 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas2); break; |
bc8080cb | 184 | case SPRN_MAS3: |
b5904972 SW |
185 | val = (u32)vcpu->arch.shared->mas7_3; |
186 | kvmppc_set_gpr(vcpu, rt, val); | |
187 | break; | |
bc8080cb | 188 | case SPRN_MAS4: |
b5904972 | 189 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas4); break; |
bc8080cb | 190 | case SPRN_MAS6: |
b5904972 | 191 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas6); break; |
bc8080cb | 192 | case SPRN_MAS7: |
b5904972 SW |
193 | val = vcpu->arch.shared->mas7_3 >> 32; |
194 | kvmppc_set_gpr(vcpu, rt, val); | |
195 | break; | |
73196cd3 | 196 | #endif |
bc8080cb | 197 | case SPRN_TLB0CFG: |
8fdd21a2 | 198 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.tlbcfg[0]); break; |
bc8080cb | 199 | case SPRN_TLB1CFG: |
8fdd21a2 | 200 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.tlbcfg[1]); break; |
d86be077 LY |
201 | case SPRN_L1CSR0: |
202 | kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr0); break; | |
bc8080cb | 203 | case SPRN_L1CSR1: |
8e5b26b5 | 204 | kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr1); break; |
bc8080cb | 205 | case SPRN_HID0: |
8e5b26b5 | 206 | kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid0); break; |
bc8080cb | 207 | case SPRN_HID1: |
8e5b26b5 | 208 | kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid1); break; |
90d34b0e SW |
209 | case SPRN_SVR: |
210 | kvmppc_set_gpr(vcpu, rt, vcpu_e500->svr); break; | |
bc8080cb | 211 | |
b0a1835d | 212 | case SPRN_MMUCSR0: |
8e5b26b5 | 213 | kvmppc_set_gpr(vcpu, rt, 0); break; |
b0a1835d | 214 | |
06579dd9 | 215 | case SPRN_MMUCFG: |
8fdd21a2 | 216 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.mmucfg); break; |
06579dd9 | 217 | |
bb3a8a17 HB |
218 | /* extra exceptions */ |
219 | case SPRN_IVOR32: | |
8e5b26b5 | 220 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]); |
bb3a8a17 HB |
221 | break; |
222 | case SPRN_IVOR33: | |
8e5b26b5 | 223 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]); |
bb3a8a17 HB |
224 | break; |
225 | case SPRN_IVOR34: | |
8e5b26b5 | 226 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]); |
bb3a8a17 HB |
227 | break; |
228 | case SPRN_IVOR35: | |
8e5b26b5 | 229 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]); |
bb3a8a17 | 230 | break; |
73196cd3 SW |
231 | #ifdef CONFIG_KVM_BOOKE_HV |
232 | case SPRN_IVOR36: | |
233 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL]); | |
234 | break; | |
235 | case SPRN_IVOR37: | |
236 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT]); | |
237 | break; | |
238 | #endif | |
bc8080cb HB |
239 | default: |
240 | emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt); | |
241 | } | |
242 | ||
243 | return emulated; | |
244 | } | |
245 |