book3s_64_emulate.c 10.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/*
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Copyright SUSE Linux Products GmbH 2009
 *
 * Authors: Alexander Graf <agraf@suse.de>
 */

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

#define OP_19_XOP_RFID		18
#define OP_19_XOP_RFI		50

#define OP_31_XOP_MFMSR		83
#define OP_31_XOP_MTMSR		146
#define OP_31_XOP_MTMSRD	178
31
#define OP_31_XOP_MTSR		210
32 33 34 35 36 37 38 39 40 41 42 43 44 45
#define OP_31_XOP_MTSRIN	242
#define OP_31_XOP_TLBIEL	274
#define OP_31_XOP_TLBIE		306
#define OP_31_XOP_SLBMTE	402
#define OP_31_XOP_SLBIE		434
#define OP_31_XOP_SLBIA		498
#define OP_31_XOP_MFSRIN	659
#define OP_31_XOP_SLBMFEV	851
#define OP_31_XOP_EIOIO		854
#define OP_31_XOP_SLBMFEE	915

/* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */
#define OP_31_XOP_DCBZ		1010

A
Alexander Graf 已提交
46 47 48 49 50 51 52 53 54
#define SPRN_GQR0		912
#define SPRN_GQR1		913
#define SPRN_GQR2		914
#define SPRN_GQR3		915
#define SPRN_GQR4		916
#define SPRN_GQR5		917
#define SPRN_GQR6		918
#define SPRN_GQR7		919

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                           unsigned int inst, int *advance)
{
	int emulated = EMULATE_DONE;

	switch (get_op(inst)) {
	case 19:
		switch (get_xop(inst)) {
		case OP_19_XOP_RFID:
		case OP_19_XOP_RFI:
			vcpu->arch.pc = vcpu->arch.srr0;
			kvmppc_set_msr(vcpu, vcpu->arch.srr1);
			*advance = 0;
			break;

		default:
			emulated = EMULATE_FAIL;
			break;
		}
		break;
	case 31:
		switch (get_xop(inst)) {
		case OP_31_XOP_MFMSR:
78
			kvmppc_set_gpr(vcpu, get_rt(inst), vcpu->arch.msr);
79 80 81
			break;
		case OP_31_XOP_MTMSRD:
		{
82
			ulong rs = kvmppc_get_gpr(vcpu, get_rs(inst));
83 84 85 86 87 88 89 90
			if (inst & 0x10000) {
				vcpu->arch.msr &= ~(MSR_RI | MSR_EE);
				vcpu->arch.msr |= rs & (MSR_RI | MSR_EE);
			} else
				kvmppc_set_msr(vcpu, rs);
			break;
		}
		case OP_31_XOP_MTMSR:
91
			kvmppc_set_msr(vcpu, kvmppc_get_gpr(vcpu, get_rs(inst)));
92 93 94 95 96
			break;
		case OP_31_XOP_MFSRIN:
		{
			int srnum;

97
			srnum = (kvmppc_get_gpr(vcpu, get_rb(inst)) >> 28) & 0xf;
98 99 100
			if (vcpu->arch.mmu.mfsrin) {
				u32 sr;
				sr = vcpu->arch.mmu.mfsrin(vcpu, srnum);
101
				kvmppc_set_gpr(vcpu, get_rt(inst), sr);
102 103 104
			}
			break;
		}
105 106 107 108 109
		case OP_31_XOP_MTSR:
			vcpu->arch.mmu.mtsrin(vcpu,
				(inst >> 16) & 0xf,
				kvmppc_get_gpr(vcpu, get_rs(inst)));
			break;
110 111
		case OP_31_XOP_MTSRIN:
			vcpu->arch.mmu.mtsrin(vcpu,
112 113
				(kvmppc_get_gpr(vcpu, get_rb(inst)) >> 28) & 0xf,
				kvmppc_get_gpr(vcpu, get_rs(inst)));
114 115 116 117 118
			break;
		case OP_31_XOP_TLBIE:
		case OP_31_XOP_TLBIEL:
		{
			bool large = (inst & 0x00200000) ? true : false;
119
			ulong addr = kvmppc_get_gpr(vcpu, get_rb(inst));
120 121 122 123 124 125 126 127 128
			vcpu->arch.mmu.tlbie(vcpu, addr, large);
			break;
		}
		case OP_31_XOP_EIOIO:
			break;
		case OP_31_XOP_SLBMTE:
			if (!vcpu->arch.mmu.slbmte)
				return EMULATE_FAIL;

129 130 131
			vcpu->arch.mmu.slbmte(vcpu,
					kvmppc_get_gpr(vcpu, get_rs(inst)),
					kvmppc_get_gpr(vcpu, get_rb(inst)));
132 133 134 135 136
			break;
		case OP_31_XOP_SLBIE:
			if (!vcpu->arch.mmu.slbie)
				return EMULATE_FAIL;

137 138
			vcpu->arch.mmu.slbie(vcpu,
					kvmppc_get_gpr(vcpu, get_rb(inst)));
139 140 141 142 143 144 145 146 147 148 149 150 151
			break;
		case OP_31_XOP_SLBIA:
			if (!vcpu->arch.mmu.slbia)
				return EMULATE_FAIL;

			vcpu->arch.mmu.slbia(vcpu);
			break;
		case OP_31_XOP_SLBMFEE:
			if (!vcpu->arch.mmu.slbmfee) {
				emulated = EMULATE_FAIL;
			} else {
				ulong t, rb;

152
				rb = kvmppc_get_gpr(vcpu, get_rb(inst));
153
				t = vcpu->arch.mmu.slbmfee(vcpu, rb);
154
				kvmppc_set_gpr(vcpu, get_rt(inst), t);
155 156 157 158 159 160 161 162
			}
			break;
		case OP_31_XOP_SLBMFEV:
			if (!vcpu->arch.mmu.slbmfev) {
				emulated = EMULATE_FAIL;
			} else {
				ulong t, rb;

163
				rb = kvmppc_get_gpr(vcpu, get_rb(inst));
164
				t = vcpu->arch.mmu.slbmfev(vcpu, rb);
165
				kvmppc_set_gpr(vcpu, get_rt(inst), t);
166 167 168 169
			}
			break;
		case OP_31_XOP_DCBZ:
		{
170
			ulong rb = kvmppc_get_gpr(vcpu, get_rb(inst));
171
			ulong ra = 0;
172
			ulong addr, vaddr;
173 174 175
			u32 zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

			if (get_ra(inst))
176
				ra = kvmppc_get_gpr(vcpu, get_ra(inst));
177 178 179 180

			addr = (ra + rb) & ~31ULL;
			if (!(vcpu->arch.msr & MSR_SF))
				addr &= 0xffffffff;
181
			vaddr = addr;
182

183 184 185
			if (kvmppc_st(vcpu, &addr, 32, zeros, true)) {
				vcpu->arch.dear = vaddr;
				vcpu->arch.fault_dear = vaddr;
186 187 188 189
				to_book3s(vcpu)->dsisr = DSISR_PROTFAULT |
						      DSISR_ISSTORE;
				kvmppc_book3s_queue_irqprio(vcpu,
					BOOK3S_INTERRUPT_DATA_STORAGE);
190
				kvmppc_mmu_pte_flush(vcpu, vaddr, ~0xFFFULL);
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
			}

			break;
		}
		default:
			emulated = EMULATE_FAIL;
		}
		break;
	default:
		emulated = EMULATE_FAIL;
	}

	return emulated;
}

206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, bool upper,
                    u32 val)
{
	if (upper) {
		/* Upper BAT */
		u32 bl = (val >> 2) & 0x7ff;
		bat->bepi_mask = (~bl << 17);
		bat->bepi = val & 0xfffe0000;
		bat->vs = (val & 2) ? 1 : 0;
		bat->vp = (val & 1) ? 1 : 0;
		bat->raw = (bat->raw & 0xffffffff00000000ULL) | val;
	} else {
		/* Lower BAT */
		bat->brpn = val & 0xfffe0000;
		bat->wimg = (val >> 3) & 0xf;
		bat->pp = val & 3;
		bat->raw = (bat->raw & 0x00000000ffffffffULL) | ((u64)val << 32);
	}
}

static void kvmppc_write_bat(struct kvm_vcpu *vcpu, int sprn, u32 val)
227 228 229 230 231 232 233 234 235
{
	struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu);
	struct kvmppc_bat *bat;

	switch (sprn) {
	case SPRN_IBAT0U ... SPRN_IBAT3L:
		bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT0U) / 2];
		break;
	case SPRN_IBAT4U ... SPRN_IBAT7L:
236
		bat = &vcpu_book3s->ibat[4 + ((sprn - SPRN_IBAT4U) / 2)];
237 238 239 240 241
		break;
	case SPRN_DBAT0U ... SPRN_DBAT3L:
		bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT0U) / 2];
		break;
	case SPRN_DBAT4U ... SPRN_DBAT7L:
242
		bat = &vcpu_book3s->dbat[4 + ((sprn - SPRN_DBAT4U) / 2)];
243 244 245 246 247
		break;
	default:
		BUG();
	}

248
	kvmppc_set_bat(vcpu, bat, !(sprn % 2), val);
249 250 251 252 253
}

int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
{
	int emulated = EMULATE_DONE;
254
	ulong spr_val = kvmppc_get_gpr(vcpu, rs);
255 256 257

	switch (sprn) {
	case SPRN_SDR1:
258
		to_book3s(vcpu)->sdr1 = spr_val;
259 260
		break;
	case SPRN_DSISR:
261
		to_book3s(vcpu)->dsisr = spr_val;
262 263
		break;
	case SPRN_DAR:
264
		vcpu->arch.dear = spr_val;
265 266
		break;
	case SPRN_HIOR:
267
		to_book3s(vcpu)->hior = spr_val;
268 269 270 271 272
		break;
	case SPRN_IBAT0U ... SPRN_IBAT3L:
	case SPRN_IBAT4U ... SPRN_IBAT7L:
	case SPRN_DBAT0U ... SPRN_DBAT3L:
	case SPRN_DBAT4U ... SPRN_DBAT7L:
273
		kvmppc_write_bat(vcpu, sprn, (u32)spr_val);
274 275 276 277 278
		/* BAT writes happen so rarely that we're ok to flush
		 * everything here */
		kvmppc_mmu_pte_flush(vcpu, 0, 0);
		break;
	case SPRN_HID0:
279
		to_book3s(vcpu)->hid[0] = spr_val;
280 281
		break;
	case SPRN_HID1:
282
		to_book3s(vcpu)->hid[1] = spr_val;
283 284
		break;
	case SPRN_HID2:
285
		to_book3s(vcpu)->hid[2] = spr_val;
286
		break;
A
Alexander Graf 已提交
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
	case SPRN_HID2_GEKKO:
		to_book3s(vcpu)->hid[2] = spr_val;
		/* HID2.PSE controls paired single on gekko */
		switch (vcpu->arch.pvr) {
		case 0x00080200:	/* lonestar 2.0 */
		case 0x00088202:	/* lonestar 2.2 */
		case 0x70000100:	/* gekko 1.0 */
		case 0x00080100:	/* gekko 2.0 */
		case 0x00083203:	/* gekko 2.3a */
		case 0x00083213:	/* gekko 2.3b */
		case 0x00083204:	/* gekko 2.4 */
		case 0x00083214:	/* gekko 2.4e (8SE) - retail HW2 */
			if (spr_val & (1 << 29)) { /* HID2.PSE */
				vcpu->arch.hflags |= BOOK3S_HFLAG_PAIRED_SINGLE;
				kvmppc_giveup_ext(vcpu, MSR_FP);
			} else {
				vcpu->arch.hflags &= ~BOOK3S_HFLAG_PAIRED_SINGLE;
			}
			break;
		}
		break;
308
	case SPRN_HID4:
A
Alexander Graf 已提交
309
	case SPRN_HID4_GEKKO:
310
		to_book3s(vcpu)->hid[4] = spr_val;
311 312
		break;
	case SPRN_HID5:
313
		to_book3s(vcpu)->hid[5] = spr_val;
314 315 316 317 318
		/* guest HID5 set can change is_dcbz32 */
		if (vcpu->arch.mmu.is_dcbz32(vcpu) &&
		    (mfmsr() & MSR_HV))
			vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
		break;
A
Alexander Graf 已提交
319 320 321 322 323 324 325 326 327 328
	case SPRN_GQR0:
	case SPRN_GQR1:
	case SPRN_GQR2:
	case SPRN_GQR3:
	case SPRN_GQR4:
	case SPRN_GQR5:
	case SPRN_GQR6:
	case SPRN_GQR7:
		to_book3s(vcpu)->gqr[sprn - SPRN_GQR0] = spr_val;
		break;
329 330 331 332 333 334
	case SPRN_ICTC:
	case SPRN_THRM1:
	case SPRN_THRM2:
	case SPRN_THRM3:
	case SPRN_CTRLF:
	case SPRN_CTRLT:
A
Alexander Graf 已提交
335 336 337 338 339 340 341 342
	case SPRN_L2CR:
	case SPRN_MMCR0_GEKKO:
	case SPRN_MMCR1_GEKKO:
	case SPRN_PMC1_GEKKO:
	case SPRN_PMC2_GEKKO:
	case SPRN_PMC3_GEKKO:
	case SPRN_PMC4_GEKKO:
	case SPRN_WPAR_GEKKO:
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
		break;
	default:
		printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn);
#ifndef DEBUG_SPR
		emulated = EMULATE_FAIL;
#endif
		break;
	}

	return emulated;
}

int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
{
	int emulated = EMULATE_DONE;

	switch (sprn) {
	case SPRN_SDR1:
361
		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->sdr1);
362 363
		break;
	case SPRN_DSISR:
364
		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->dsisr);
365 366
		break;
	case SPRN_DAR:
367
		kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear);
368 369
		break;
	case SPRN_HIOR:
370
		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hior);
371 372
		break;
	case SPRN_HID0:
373
		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[0]);
374 375
		break;
	case SPRN_HID1:
376
		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[1]);
377 378
		break;
	case SPRN_HID2:
A
Alexander Graf 已提交
379
	case SPRN_HID2_GEKKO:
380
		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[2]);
381 382
		break;
	case SPRN_HID4:
A
Alexander Graf 已提交
383
	case SPRN_HID4_GEKKO:
384
		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[4]);
385 386
		break;
	case SPRN_HID5:
387
		kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[5]);
388
		break;
A
Alexander Graf 已提交
389 390 391 392 393 394 395 396 397 398 399
	case SPRN_GQR0:
	case SPRN_GQR1:
	case SPRN_GQR2:
	case SPRN_GQR3:
	case SPRN_GQR4:
	case SPRN_GQR5:
	case SPRN_GQR6:
	case SPRN_GQR7:
		kvmppc_set_gpr(vcpu, rt,
			       to_book3s(vcpu)->gqr[sprn - SPRN_GQR0]);
		break;
400 401 402 403 404
	case SPRN_THRM1:
	case SPRN_THRM2:
	case SPRN_THRM3:
	case SPRN_CTRLF:
	case SPRN_CTRLT:
A
Alexander Graf 已提交
405 406 407 408 409 410 411 412
	case SPRN_L2CR:
	case SPRN_MMCR0_GEKKO:
	case SPRN_MMCR1_GEKKO:
	case SPRN_PMC1_GEKKO:
	case SPRN_PMC2_GEKKO:
	case SPRN_PMC3_GEKKO:
	case SPRN_PMC4_GEKKO:
	case SPRN_WPAR_GEKKO:
413
		kvmppc_set_gpr(vcpu, rt, 0);
414 415 416 417 418 419 420 421 422 423 424 425
		break;
	default:
		printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn);
#ifndef DEBUG_SPR
		emulated = EMULATE_FAIL;
#endif
		break;
	}

	return emulated;
}