• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/powerpc/kvm/
1/*
2 * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
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>
17#include <asm/kvm_e500.h>
18
19#include "booke.h"
20#include "e500_tlb.h"
21
22#define XOP_TLBIVAX 786
23#define XOP_TLBSX   914
24#define XOP_TLBRE   946
25#define XOP_TLBWE   978
26
27int 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;
33
34	switch (get_op(inst)) {
35	case 31:
36		switch (get_xop(inst)) {
37
38		case XOP_TLBRE:
39			emulated = kvmppc_e500_emul_tlbre(vcpu);
40			break;
41
42		case XOP_TLBWE:
43			emulated = kvmppc_e500_emul_tlbwe(vcpu);
44			break;
45
46		case XOP_TLBSX:
47			rb = get_rb(inst);
48			emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
49			break;
50
51		case XOP_TLBIVAX:
52			ra = get_ra(inst);
53			rb = get_rb(inst);
54			emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb);
55			break;
56
57		default:
58			emulated = EMULATE_FAIL;
59		}
60
61		break;
62
63	default:
64		emulated = EMULATE_FAIL;
65	}
66
67	if (emulated == EMULATE_FAIL)
68		emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance);
69
70	return emulated;
71}
72
73int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
74{
75	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
76	int emulated = EMULATE_DONE;
77	ulong spr_val = kvmppc_get_gpr(vcpu, rs);
78
79	switch (sprn) {
80	case SPRN_PID:
81		vcpu_e500->pid[0] = vcpu->arch.shadow_pid =
82			vcpu->arch.pid = spr_val;
83		break;
84	case SPRN_PID1:
85		vcpu_e500->pid[1] = spr_val; break;
86	case SPRN_PID2:
87		vcpu_e500->pid[2] = spr_val; break;
88	case SPRN_MAS0:
89		vcpu_e500->mas0 = spr_val; break;
90	case SPRN_MAS1:
91		vcpu_e500->mas1 = spr_val; break;
92	case SPRN_MAS2:
93		vcpu_e500->mas2 = spr_val; break;
94	case SPRN_MAS3:
95		vcpu_e500->mas3 = spr_val; break;
96	case SPRN_MAS4:
97		vcpu_e500->mas4 = spr_val; break;
98	case SPRN_MAS6:
99		vcpu_e500->mas6 = spr_val; break;
100	case SPRN_MAS7:
101		vcpu_e500->mas7 = spr_val; break;
102	case SPRN_L1CSR0:
103		vcpu_e500->l1csr0 = spr_val;
104		vcpu_e500->l1csr0 &= ~(L1CSR0_DCFI | L1CSR0_CLFC);
105		break;
106	case SPRN_L1CSR1:
107		vcpu_e500->l1csr1 = spr_val; break;
108	case SPRN_HID0:
109		vcpu_e500->hid0 = spr_val; break;
110	case SPRN_HID1:
111		vcpu_e500->hid1 = spr_val; break;
112
113	case SPRN_MMUCSR0:
114		emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500,
115				spr_val);
116		break;
117
118	/* extra exceptions */
119	case SPRN_IVOR32:
120		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
121		break;
122	case SPRN_IVOR33:
123		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = spr_val;
124		break;
125	case SPRN_IVOR34:
126		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val;
127		break;
128	case SPRN_IVOR35:
129		vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val;
130		break;
131
132	default:
133		emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs);
134	}
135
136	return emulated;
137}
138
139int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
140{
141	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
142	int emulated = EMULATE_DONE;
143
144	switch (sprn) {
145	case SPRN_PID:
146		kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[0]); break;
147	case SPRN_PID1:
148		kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[1]); break;
149	case SPRN_PID2:
150		kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[2]); break;
151	case SPRN_MAS0:
152		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas0); break;
153	case SPRN_MAS1:
154		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas1); break;
155	case SPRN_MAS2:
156		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas2); break;
157	case SPRN_MAS3:
158		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas3); break;
159	case SPRN_MAS4:
160		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas4); break;
161	case SPRN_MAS6:
162		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas6); break;
163	case SPRN_MAS7:
164		kvmppc_set_gpr(vcpu, rt, vcpu_e500->mas7); break;
165
166	case SPRN_TLB0CFG:
167		kvmppc_set_gpr(vcpu, rt, vcpu_e500->tlb0cfg); break;
168	case SPRN_TLB1CFG:
169		kvmppc_set_gpr(vcpu, rt, vcpu_e500->tlb1cfg); break;
170	case SPRN_L1CSR0:
171		kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr0); break;
172	case SPRN_L1CSR1:
173		kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr1); break;
174	case SPRN_HID0:
175		kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid0); break;
176	case SPRN_HID1:
177		kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid1); break;
178
179	case SPRN_MMUCSR0:
180		kvmppc_set_gpr(vcpu, rt, 0); break;
181
182	case SPRN_MMUCFG:
183		kvmppc_set_gpr(vcpu, rt, mfspr(SPRN_MMUCFG)); break;
184
185	/* extra exceptions */
186	case SPRN_IVOR32:
187		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]);
188		break;
189	case SPRN_IVOR33:
190		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]);
191		break;
192	case SPRN_IVOR34:
193		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]);
194		break;
195	case SPRN_IVOR35:
196		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]);
197		break;
198	default:
199		emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt);
200	}
201
202	return emulated;
203}
204