• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/powerpc/kvm/
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2, as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
14 *
15 * Copyright IBM Corp. 2008
16 *
17 * Authors: Hollis Blanchard <hollisb@us.ibm.com>
18 */
19
20#include <linux/kvm_host.h>
21#include <asm/disassemble.h>
22
23#include "booke.h"
24
25#define OP_19_XOP_RFI     50
26
27#define OP_31_XOP_MFMSR   83
28#define OP_31_XOP_WRTEE   131
29#define OP_31_XOP_MTMSR   146
30#define OP_31_XOP_WRTEEI  163
31
32static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
33{
34	vcpu->arch.pc = vcpu->arch.srr0;
35	kvmppc_set_msr(vcpu, vcpu->arch.srr1);
36}
37
38int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
39                            unsigned int inst, int *advance)
40{
41	int emulated = EMULATE_DONE;
42	int rs;
43	int rt;
44
45	switch (get_op(inst)) {
46	case 19:
47		switch (get_xop(inst)) {
48		case OP_19_XOP_RFI:
49			kvmppc_emul_rfi(vcpu);
50			kvmppc_set_exit_type(vcpu, EMULATED_RFI_EXITS);
51			*advance = 0;
52			break;
53
54		default:
55			emulated = EMULATE_FAIL;
56			break;
57		}
58		break;
59
60	case 31:
61		switch (get_xop(inst)) {
62
63		case OP_31_XOP_MFMSR:
64			rt = get_rt(inst);
65			kvmppc_set_gpr(vcpu, rt, vcpu->arch.msr);
66			kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS);
67			break;
68
69		case OP_31_XOP_MTMSR:
70			rs = get_rs(inst);
71			kvmppc_set_exit_type(vcpu, EMULATED_MTMSR_EXITS);
72			kvmppc_set_msr(vcpu, kvmppc_get_gpr(vcpu, rs));
73			break;
74
75		case OP_31_XOP_WRTEE:
76			rs = get_rs(inst);
77			vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
78					| (kvmppc_get_gpr(vcpu, rs) & MSR_EE);
79			kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
80			break;
81
82		case OP_31_XOP_WRTEEI:
83			vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
84							 | (inst & MSR_EE);
85			kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
86			break;
87
88		default:
89			emulated = EMULATE_FAIL;
90		}
91
92		break;
93
94	default:
95		emulated = EMULATE_FAIL;
96	}
97
98	return emulated;
99}
100
101int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
102{
103	int emulated = EMULATE_DONE;
104	ulong spr_val = kvmppc_get_gpr(vcpu, rs);
105
106	switch (sprn) {
107	case SPRN_DEAR:
108		vcpu->arch.dear = spr_val; break;
109	case SPRN_ESR:
110		vcpu->arch.esr = spr_val; break;
111	case SPRN_DBCR0:
112		vcpu->arch.dbcr0 = spr_val; break;
113	case SPRN_DBCR1:
114		vcpu->arch.dbcr1 = spr_val; break;
115	case SPRN_DBSR:
116		vcpu->arch.dbsr &= ~spr_val; break;
117	case SPRN_TSR:
118		vcpu->arch.tsr &= ~spr_val; break;
119	case SPRN_TCR:
120		vcpu->arch.tcr = spr_val;
121		kvmppc_emulate_dec(vcpu);
122		break;
123
124	/* Note: SPRG4-7 are user-readable. These values are
125	 * loaded into the real SPRGs when resuming the
126	 * guest. */
127	case SPRN_SPRG4:
128		vcpu->arch.sprg4 = spr_val; break;
129	case SPRN_SPRG5:
130		vcpu->arch.sprg5 = spr_val; break;
131	case SPRN_SPRG6:
132		vcpu->arch.sprg6 = spr_val; break;
133	case SPRN_SPRG7:
134		vcpu->arch.sprg7 = spr_val; break;
135
136	case SPRN_IVPR:
137		vcpu->arch.ivpr = spr_val;
138		break;
139	case SPRN_IVOR0:
140		vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = spr_val;
141		break;
142	case SPRN_IVOR1:
143		vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = spr_val;
144		break;
145	case SPRN_IVOR2:
146		vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = spr_val;
147		break;
148	case SPRN_IVOR3:
149		vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = spr_val;
150		break;
151	case SPRN_IVOR4:
152		vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = spr_val;
153		break;
154	case SPRN_IVOR5:
155		vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = spr_val;
156		break;
157	case SPRN_IVOR6:
158		vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = spr_val;
159		break;
160	case SPRN_IVOR7:
161		vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = spr_val;
162		break;
163	case SPRN_IVOR8:
164		vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = spr_val;
165		break;
166	case SPRN_IVOR9:
167		vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = spr_val;
168		break;
169	case SPRN_IVOR10:
170		vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = spr_val;
171		break;
172	case SPRN_IVOR11:
173		vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = spr_val;
174		break;
175	case SPRN_IVOR12:
176		vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = spr_val;
177		break;
178	case SPRN_IVOR13:
179		vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = spr_val;
180		break;
181	case SPRN_IVOR14:
182		vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = spr_val;
183		break;
184	case SPRN_IVOR15:
185		vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = spr_val;
186		break;
187
188	default:
189		emulated = EMULATE_FAIL;
190	}
191
192	return emulated;
193}
194
195int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
196{
197	int emulated = EMULATE_DONE;
198
199	switch (sprn) {
200	case SPRN_IVPR:
201		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivpr); break;
202	case SPRN_DEAR:
203		kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear); break;
204	case SPRN_ESR:
205		kvmppc_set_gpr(vcpu, rt, vcpu->arch.esr); break;
206	case SPRN_DBCR0:
207		kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr0); break;
208	case SPRN_DBCR1:
209		kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbcr1); break;
210	case SPRN_DBSR:
211		kvmppc_set_gpr(vcpu, rt, vcpu->arch.dbsr); break;
212
213	case SPRN_IVOR0:
214		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL]);
215		break;
216	case SPRN_IVOR1:
217		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK]);
218		break;
219	case SPRN_IVOR2:
220		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE]);
221		break;
222	case SPRN_IVOR3:
223		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE]);
224		break;
225	case SPRN_IVOR4:
226		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL]);
227		break;
228	case SPRN_IVOR5:
229		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT]);
230		break;
231	case SPRN_IVOR6:
232		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM]);
233		break;
234	case SPRN_IVOR7:
235		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL]);
236		break;
237	case SPRN_IVOR8:
238		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL]);
239		break;
240	case SPRN_IVOR9:
241		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL]);
242		break;
243	case SPRN_IVOR10:
244		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER]);
245		break;
246	case SPRN_IVOR11:
247		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_FIT]);
248		break;
249	case SPRN_IVOR12:
250		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG]);
251		break;
252	case SPRN_IVOR13:
253		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]);
254		break;
255	case SPRN_IVOR14:
256		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]);
257		break;
258	case SPRN_IVOR15:
259		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]);
260		break;
261
262	default:
263		emulated = EMULATE_FAIL;
264	}
265
266	return emulated;
267}
268