e500_emulate.c 5.3 KB
Newer Older
1
/*
S
Scott Wood 已提交
2
 * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * Author: Yu Liu, <yu.liu@freescale.com>
 *
 * Description:
 * This file is derived from arch/powerpc/kvm/44x_emulate.c,
 * by Hollis Blanchard <hollisb@us.ibm.com>.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 */

#include <asm/kvm_ppc.h>
#include <asm/disassemble.h>

#include "booke.h"
19
#include "e500.h"
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

#define XOP_TLBIVAX 786
#define XOP_TLBSX   914
#define XOP_TLBRE   946
#define XOP_TLBWE   978

int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                           unsigned int inst, int *advance)
{
	int emulated = EMULATE_DONE;
	int ra;
	int rb;

	switch (get_op(inst)) {
	case 31:
		switch (get_xop(inst)) {

		case XOP_TLBRE:
			emulated = kvmppc_e500_emul_tlbre(vcpu);
			break;

		case XOP_TLBWE:
			emulated = kvmppc_e500_emul_tlbwe(vcpu);
			break;

		case XOP_TLBSX:
			rb = get_rb(inst);
			emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
			break;

		case XOP_TLBIVAX:
			ra = get_ra(inst);
			rb = get_rb(inst);
			emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb);
			break;

		default:
			emulated = EMULATE_FAIL;
		}

		break;

	default:
		emulated = EMULATE_FAIL;
	}

	if (emulated == EMULATE_FAIL)
		emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance);

	return emulated;
}

int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
{
	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
	int emulated = EMULATE_DONE;
76
	ulong spr_val = kvmppc_get_gpr(vcpu, rs);
77 78 79

	switch (sprn) {
	case SPRN_PID:
S
Scott Wood 已提交
80
		kvmppc_set_pid(vcpu, spr_val);
81 82
		break;
	case SPRN_PID1:
L
Liu Yu 已提交
83 84
		if (spr_val != 0)
			return EMULATE_FAIL;
85
		vcpu_e500->pid[1] = spr_val; break;
86
	case SPRN_PID2:
L
Liu Yu 已提交
87 88
		if (spr_val != 0)
			return EMULATE_FAIL;
89
		vcpu_e500->pid[2] = spr_val; break;
90
	case SPRN_MAS0:
91
		vcpu->arch.shared->mas0 = spr_val; break;
92
	case SPRN_MAS1:
93
		vcpu->arch.shared->mas1 = spr_val; break;
94
	case SPRN_MAS2:
95
		vcpu->arch.shared->mas2 = spr_val; break;
96
	case SPRN_MAS3:
97 98
		vcpu->arch.shared->mas7_3 &= ~(u64)0xffffffff;
		vcpu->arch.shared->mas7_3 |= spr_val;
S
Scott Wood 已提交
99
		break;
100
	case SPRN_MAS4:
101
		vcpu->arch.shared->mas4 = spr_val; break;
102
	case SPRN_MAS6:
103
		vcpu->arch.shared->mas6 = spr_val; break;
104
	case SPRN_MAS7:
105 106
		vcpu->arch.shared->mas7_3 &= (u64)0xffffffff;
		vcpu->arch.shared->mas7_3 |= (u64)spr_val << 32;
S
Scott Wood 已提交
107
		break;
108 109 110 111
	case SPRN_L1CSR0:
		vcpu_e500->l1csr0 = spr_val;
		vcpu_e500->l1csr0 &= ~(L1CSR0_DCFI | L1CSR0_CLFC);
		break;
112
	case SPRN_L1CSR1:
113
		vcpu_e500->l1csr1 = spr_val; break;
114
	case SPRN_HID0:
115
		vcpu_e500->hid0 = spr_val; break;
116
	case SPRN_HID1:
117
		vcpu_e500->hid1 = spr_val; break;
118

119 120
	case SPRN_MMUCSR0:
		emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500,
121
				spr_val);
122 123
		break;

124 125
	/* extra exceptions */
	case SPRN_IVOR32:
126
		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
127 128
		break;
	case SPRN_IVOR33:
129
		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = spr_val;
130 131
		break;
	case SPRN_IVOR34:
132
		vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val;
133 134
		break;
	case SPRN_IVOR35:
135
		vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val;
136 137
		break;

138 139 140 141 142 143 144 145 146 147 148
	default:
		emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs);
	}

	return emulated;
}

int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
{
	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
	int emulated = EMULATE_DONE;
149
	unsigned long val;
150 151 152

	switch (sprn) {
	case SPRN_PID:
153
		kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[0]); break;
154
	case SPRN_PID1:
155
		kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[1]); break;
156
	case SPRN_PID2:
157
		kvmppc_set_gpr(vcpu, rt, vcpu_e500->pid[2]); break;
158
	case SPRN_MAS0:
159
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas0); break;
160
	case SPRN_MAS1:
161
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas1); break;
162
	case SPRN_MAS2:
163
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas2); break;
164
	case SPRN_MAS3:
165 166 167
		val = (u32)vcpu->arch.shared->mas7_3;
		kvmppc_set_gpr(vcpu, rt, val);
		break;
168
	case SPRN_MAS4:
169
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas4); break;
170
	case SPRN_MAS6:
171
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->mas6); break;
172
	case SPRN_MAS7:
173 174 175
		val = vcpu->arch.shared->mas7_3 >> 32;
		kvmppc_set_gpr(vcpu, rt, val);
		break;
176
	case SPRN_TLB0CFG:
177
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.tlbcfg[0]); break;
178
	case SPRN_TLB1CFG:
179
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.tlbcfg[1]); break;
180 181
	case SPRN_L1CSR0:
		kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr0); break;
182
	case SPRN_L1CSR1:
183
		kvmppc_set_gpr(vcpu, rt, vcpu_e500->l1csr1); break;
184
	case SPRN_HID0:
185
		kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid0); break;
186
	case SPRN_HID1:
187
		kvmppc_set_gpr(vcpu, rt, vcpu_e500->hid1); break;
S
Scott Wood 已提交
188 189
	case SPRN_SVR:
		kvmppc_set_gpr(vcpu, rt, vcpu_e500->svr); break;
190

191
	case SPRN_MMUCSR0:
192
		kvmppc_set_gpr(vcpu, rt, 0); break;
193

194
	case SPRN_MMUCFG:
195
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.mmucfg); break;
196

197 198
	/* extra exceptions */
	case SPRN_IVOR32:
199
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]);
200 201
		break;
	case SPRN_IVOR33:
202
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA]);
203 204
		break;
	case SPRN_IVOR34:
205
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND]);
206 207
		break;
	case SPRN_IVOR35:
208
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR]);
209
		break;
210 211 212 213 214 215 216
	default:
		emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt);
	}

	return emulated;
}