book3s.c 15 KB
Newer Older
Alexander Graf's avatar
Alexander Graf committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
 * Copyright (C) 2009. SUSE Linux Products GmbH. All rights reserved.
 *
 * Authors:
 *    Alexander Graf <agraf@suse.de>
 *    Kevin Wolf <mail@kevin-wolf.de>
 *
 * Description:
 * This file is derived from arch/powerpc/kvm/44x.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 <linux/kvm_host.h>
#include <linux/err.h>
19
#include <linux/export.h>
20
#include <linux/slab.h>
Alexander Graf's avatar
Alexander Graf committed
21
22
23
24
25
26
27
28
29
30

#include <asm/reg.h>
#include <asm/cputable.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s.h>
#include <asm/mmu_context.h>
31
#include <asm/page.h>
32
#include <linux/gfp.h>
Alexander Graf's avatar
Alexander Graf committed
33
34
#include <linux/sched.h>
#include <linux/vmalloc.h>
Alexander Graf's avatar
Alexander Graf committed
35
#include <linux/highmem.h>
Alexander Graf's avatar
Alexander Graf committed
36

37
38
#include "trace.h"

Alexander Graf's avatar
Alexander Graf committed
39
40
41
#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU

/* #define EXIT_DEBUG */
42

Alexander Graf's avatar
Alexander Graf committed
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
struct kvm_stats_debugfs_item debugfs_entries[] = {
	{ "exits",       VCPU_STAT(sum_exits) },
	{ "mmio",        VCPU_STAT(mmio_exits) },
	{ "sig",         VCPU_STAT(signal_exits) },
	{ "sysc",        VCPU_STAT(syscall_exits) },
	{ "inst_emu",    VCPU_STAT(emulated_inst_exits) },
	{ "dec",         VCPU_STAT(dec_exits) },
	{ "ext_intr",    VCPU_STAT(ext_intr_exits) },
	{ "queue_intr",  VCPU_STAT(queue_intr) },
	{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
	{ "pf_storage",  VCPU_STAT(pf_storage) },
	{ "sp_storage",  VCPU_STAT(sp_storage) },
	{ "pf_instruc",  VCPU_STAT(pf_instruc) },
	{ "sp_instruc",  VCPU_STAT(sp_instruc) },
	{ "ld",          VCPU_STAT(ld) },
	{ "ld_slow",     VCPU_STAT(ld_slow) },
	{ "st",          VCPU_STAT(st) },
	{ "st_slow",     VCPU_STAT(st_slow) },
	{ NULL }
};

void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu)
{
}

void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu)
{
}

void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
{
74
75
	vcpu->arch.shared->srr0 = kvmppc_get_pc(vcpu);
	vcpu->arch.shared->srr1 = vcpu->arch.shared->msr | flags;
76
	kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec);
Alexander Graf's avatar
Alexander Graf committed
77
78
79
	vcpu->arch.mmu.reset_msr(vcpu);
}

80
static int kvmppc_book3s_vec2irqprio(unsigned int vec)
Alexander Graf's avatar
Alexander Graf committed
81
82
83
84
85
86
87
88
89
90
91
{
	unsigned int prio;

	switch (vec) {
	case 0x100: prio = BOOK3S_IRQPRIO_SYSTEM_RESET;		break;
	case 0x200: prio = BOOK3S_IRQPRIO_MACHINE_CHECK;	break;
	case 0x300: prio = BOOK3S_IRQPRIO_DATA_STORAGE;		break;
	case 0x380: prio = BOOK3S_IRQPRIO_DATA_SEGMENT;		break;
	case 0x400: prio = BOOK3S_IRQPRIO_INST_STORAGE;		break;
	case 0x480: prio = BOOK3S_IRQPRIO_INST_SEGMENT;		break;
	case 0x500: prio = BOOK3S_IRQPRIO_EXTERNAL;		break;
92
	case 0x501: prio = BOOK3S_IRQPRIO_EXTERNAL_LEVEL;	break;
Alexander Graf's avatar
Alexander Graf committed
93
94
95
96
97
98
99
100
101
102
103
	case 0x600: prio = BOOK3S_IRQPRIO_ALIGNMENT;		break;
	case 0x700: prio = BOOK3S_IRQPRIO_PROGRAM;		break;
	case 0x800: prio = BOOK3S_IRQPRIO_FP_UNAVAIL;		break;
	case 0x900: prio = BOOK3S_IRQPRIO_DECREMENTER;		break;
	case 0xc00: prio = BOOK3S_IRQPRIO_SYSCALL;		break;
	case 0xd00: prio = BOOK3S_IRQPRIO_DEBUG;		break;
	case 0xf20: prio = BOOK3S_IRQPRIO_ALTIVEC;		break;
	case 0xf40: prio = BOOK3S_IRQPRIO_VSX;			break;
	default:    prio = BOOK3S_IRQPRIO_MAX;			break;
	}

104
105
106
	return prio;
}

107
108
109
static void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
					  unsigned int vec)
{
110
111
	unsigned long old_pending = vcpu->arch.pending_exceptions;

112
113
	clear_bit(kvmppc_book3s_vec2irqprio(vec),
		  &vcpu->arch.pending_exceptions);
114

115
116
	kvmppc_update_int_pending(vcpu, vcpu->arch.pending_exceptions,
				  old_pending);
117
118
}

119
120
121
122
123
124
void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
{
	vcpu->stat.queue_intr++;

	set_bit(kvmppc_book3s_vec2irqprio(vec),
		&vcpu->arch.pending_exceptions);
Alexander Graf's avatar
Alexander Graf committed
125
126
127
128
129
130
#ifdef EXIT_DEBUG
	printk(KERN_INFO "Queueing interrupt %x\n", vec);
#endif
}


131
void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags)
Alexander Graf's avatar
Alexander Graf committed
132
{
133
134
	/* might as well deliver this straight away */
	kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_PROGRAM, flags);
Alexander Graf's avatar
Alexander Graf committed
135
136
137
138
139
140
141
142
143
}

void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu)
{
	kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER);
}

int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu)
{
144
	return test_bit(BOOK3S_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions);
Alexander Graf's avatar
Alexander Graf committed
145
146
}

147
148
149
150
151
void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu)
{
	kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER);
}

Alexander Graf's avatar
Alexander Graf committed
152
153
154
void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                struct kvm_interrupt *irq)
{
155
156
157
158
159
160
	unsigned int vec = BOOK3S_INTERRUPT_EXTERNAL;

	if (irq->irq == KVM_INTERRUPT_SET_LEVEL)
		vec = BOOK3S_INTERRUPT_EXTERNAL_LEVEL;

	kvmppc_book3s_queue_irqprio(vcpu, vec);
Alexander Graf's avatar
Alexander Graf committed
161
162
}

163
void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu)
164
165
{
	kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL);
166
	kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL_LEVEL);
167
168
}

Alexander Graf's avatar
Alexander Graf committed
169
170
171
172
int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
{
	int deliver = 1;
	int vec = 0;
173
	bool crit = kvmppc_critical_section(vcpu);
Alexander Graf's avatar
Alexander Graf committed
174
175
176

	switch (priority) {
	case BOOK3S_IRQPRIO_DECREMENTER:
177
		deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
Alexander Graf's avatar
Alexander Graf committed
178
179
180
		vec = BOOK3S_INTERRUPT_DECREMENTER;
		break;
	case BOOK3S_IRQPRIO_EXTERNAL:
181
	case BOOK3S_IRQPRIO_EXTERNAL_LEVEL:
182
		deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
Alexander Graf's avatar
Alexander Graf committed
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
		vec = BOOK3S_INTERRUPT_EXTERNAL;
		break;
	case BOOK3S_IRQPRIO_SYSTEM_RESET:
		vec = BOOK3S_INTERRUPT_SYSTEM_RESET;
		break;
	case BOOK3S_IRQPRIO_MACHINE_CHECK:
		vec = BOOK3S_INTERRUPT_MACHINE_CHECK;
		break;
	case BOOK3S_IRQPRIO_DATA_STORAGE:
		vec = BOOK3S_INTERRUPT_DATA_STORAGE;
		break;
	case BOOK3S_IRQPRIO_INST_STORAGE:
		vec = BOOK3S_INTERRUPT_INST_STORAGE;
		break;
	case BOOK3S_IRQPRIO_DATA_SEGMENT:
		vec = BOOK3S_INTERRUPT_DATA_SEGMENT;
		break;
	case BOOK3S_IRQPRIO_INST_SEGMENT:
		vec = BOOK3S_INTERRUPT_INST_SEGMENT;
		break;
	case BOOK3S_IRQPRIO_ALIGNMENT:
		vec = BOOK3S_INTERRUPT_ALIGNMENT;
		break;
	case BOOK3S_IRQPRIO_PROGRAM:
		vec = BOOK3S_INTERRUPT_PROGRAM;
		break;
	case BOOK3S_IRQPRIO_VSX:
		vec = BOOK3S_INTERRUPT_VSX;
		break;
	case BOOK3S_IRQPRIO_ALTIVEC:
		vec = BOOK3S_INTERRUPT_ALTIVEC;
		break;
	case BOOK3S_IRQPRIO_FP_UNAVAIL:
		vec = BOOK3S_INTERRUPT_FP_UNAVAIL;
		break;
	case BOOK3S_IRQPRIO_SYSCALL:
		vec = BOOK3S_INTERRUPT_SYSCALL;
		break;
	case BOOK3S_IRQPRIO_DEBUG:
		vec = BOOK3S_INTERRUPT_TRACE;
		break;
	case BOOK3S_IRQPRIO_PERFORMANCE_MONITOR:
		vec = BOOK3S_INTERRUPT_PERFMON;
		break;
	default:
		deliver = 0;
		printk(KERN_ERR "KVM: Unknown interrupt: 0x%x\n", priority);
		break;
	}

#if 0
	printk(KERN_INFO "Deliver interrupt 0x%x? %x\n", vec, deliver);
#endif

	if (deliver)
238
		kvmppc_inject_interrupt(vcpu, vec, 0);
Alexander Graf's avatar
Alexander Graf committed
239
240
241
242

	return deliver;
}

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/*
 * This function determines if an irqprio should be cleared once issued.
 */
static bool clear_irqprio(struct kvm_vcpu *vcpu, unsigned int priority)
{
	switch (priority) {
		case BOOK3S_IRQPRIO_DECREMENTER:
			/* DEC interrupts get cleared by mtdec */
			return false;
		case BOOK3S_IRQPRIO_EXTERNAL_LEVEL:
			/* External interrupts get cleared by userspace */
			return false;
	}

	return true;
}

260
int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
Alexander Graf's avatar
Alexander Graf committed
261
262
{
	unsigned long *pending = &vcpu->arch.pending_exceptions;
263
	unsigned long old_pending = vcpu->arch.pending_exceptions;
Alexander Graf's avatar
Alexander Graf committed
264
265
266
267
268
269
270
	unsigned int priority;

#ifdef EXIT_DEBUG
	if (vcpu->arch.pending_exceptions)
		printk(KERN_EMERG "KVM: Check pending: %lx\n", vcpu->arch.pending_exceptions);
#endif
	priority = __ffs(*pending);
Alexander Graf's avatar
Alexander Graf committed
271
	while (priority < BOOK3S_IRQPRIO_MAX) {
272
		if (kvmppc_book3s_irqprio_deliver(vcpu, priority) &&
273
		    clear_irqprio(vcpu, priority)) {
Alexander Graf's avatar
Alexander Graf committed
274
275
276
277
278
279
280
281
			clear_bit(priority, &vcpu->arch.pending_exceptions);
			break;
		}

		priority = find_next_bit(pending,
					 BITS_PER_BYTE * sizeof(*pending),
					 priority + 1);
	}
282
283

	/* Tell the guest about our interrupt status */
284
	kvmppc_update_int_pending(vcpu, *pending, old_pending);
285
286

	return 0;
Alexander Graf's avatar
Alexander Graf committed
287
288
}

289
290
291
292
pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn)
{
	ulong mp_pa = vcpu->arch.magic_page_pa;

293
294
295
	if (!(vcpu->arch.shared->msr & MSR_SF))
		mp_pa = (uint32_t)mp_pa;

296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
	/* Magic page override */
	if (unlikely(mp_pa) &&
	    unlikely(((gfn << PAGE_SHIFT) & KVM_PAM) ==
		     ((mp_pa & PAGE_MASK) & KVM_PAM))) {
		ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK;
		pfn_t pfn;

		pfn = (pfn_t)virt_to_phys((void*)shared_page) >> PAGE_SHIFT;
		get_page(pfn_to_page(pfn));
		return pfn;
	}

	return gfn_to_pfn(vcpu->kvm, gfn);
}

Alexander Graf's avatar
Alexander Graf committed
311
312
313
static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
			 struct kvmppc_pte *pte)
{
314
	int relocated = (vcpu->arch.shared->msr & (data ? MSR_DR : MSR_IR));
Alexander Graf's avatar
Alexander Graf committed
315
316
317
318
319
320
	int r;

	if (relocated) {
		r = vcpu->arch.mmu.xlate(vcpu, eaddr, pte, data);
	} else {
		pte->eaddr = eaddr;
Alexander Graf's avatar
Alexander Graf committed
321
		pte->raddr = eaddr & KVM_PAM;
322
		pte->vpage = VSID_REAL | eaddr >> 12;
Alexander Graf's avatar
Alexander Graf committed
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
		pte->may_read = true;
		pte->may_write = true;
		pte->may_execute = true;
		r = 0;
	}

	return r;
}

static hva_t kvmppc_bad_hva(void)
{
	return PAGE_OFFSET;
}

static hva_t kvmppc_pte_to_hva(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte,
			       bool read)
{
	hva_t hpage;

	if (read && !pte->may_read)
		goto err;

	if (!read && !pte->may_write)
		goto err;

	hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
	if (kvm_is_error_hva(hpage))
		goto err;

	return hpage | (pte->raddr & ~PAGE_MASK);
err:
	return kvmppc_bad_hva();
}

357
358
int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
	      bool data)
Alexander Graf's avatar
Alexander Graf committed
359
360
361
362
363
{
	struct kvmppc_pte pte;

	vcpu->stat.st++;

364
	if (kvmppc_xlate(vcpu, *eaddr, data, &pte))
Alexander Graf's avatar
Alexander Graf committed
365
		return -ENOENT;
366
367

	*eaddr = pte.raddr;
Alexander Graf's avatar
Alexander Graf committed
368

Alexander Graf's avatar
Alexander Graf committed
369
370
	if (!pte.may_write)
		return -EPERM;
Alexander Graf's avatar
Alexander Graf committed
371

Alexander Graf's avatar
Alexander Graf committed
372
373
	if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size))
		return EMULATE_DO_MMIO;
Alexander Graf's avatar
Alexander Graf committed
374

375
	return EMULATE_DONE;
Alexander Graf's avatar
Alexander Graf committed
376
377
}

378
int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
Alexander Graf's avatar
Alexander Graf committed
379
380
381
		      bool data)
{
	struct kvmppc_pte pte;
382
	hva_t hva = *eaddr;
Alexander Graf's avatar
Alexander Graf committed
383
384
385

	vcpu->stat.ld++;

386
387
388
389
	if (kvmppc_xlate(vcpu, *eaddr, data, &pte))
		goto nopte;

	*eaddr = pte.raddr;
Alexander Graf's avatar
Alexander Graf committed
390
391
392

	hva = kvmppc_pte_to_hva(vcpu, &pte, true);
	if (kvm_is_error_hva(hva))
393
		goto mmio;
Alexander Graf's avatar
Alexander Graf committed
394
395
396

	if (copy_from_user(ptr, (void __user *)hva, size)) {
		printk(KERN_INFO "kvmppc_ld at 0x%lx failed\n", hva);
397
		goto mmio;
Alexander Graf's avatar
Alexander Graf committed
398
399
	}

400
	return EMULATE_DONE;
Alexander Graf's avatar
Alexander Graf committed
401

402
nopte:
Alexander Graf's avatar
Alexander Graf committed
403
	return -ENOENT;
404
405
mmio:
	return EMULATE_DO_MMIO;
Alexander Graf's avatar
Alexander Graf committed
406
407
408
409
410
411
412
}

int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
{
	return 0;
}

413
414
415
416
417
418
419
420
421
int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu)
{
	return 0;
}

void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu)
{
}

Alexander Graf's avatar
Alexander Graf committed
422
423
424
425
int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
{
	int i;

426
	regs->pc = kvmppc_get_pc(vcpu);
427
	regs->cr = kvmppc_get_cr(vcpu);
428
429
	regs->ctr = kvmppc_get_ctr(vcpu);
	regs->lr = kvmppc_get_lr(vcpu);
430
	regs->xer = kvmppc_get_xer(vcpu);
431
	regs->msr = vcpu->arch.shared->msr;
432
433
	regs->srr0 = vcpu->arch.shared->srr0;
	regs->srr1 = vcpu->arch.shared->srr1;
Alexander Graf's avatar
Alexander Graf committed
434
	regs->pid = vcpu->arch.pid;
435
436
437
438
	regs->sprg0 = vcpu->arch.shared->sprg0;
	regs->sprg1 = vcpu->arch.shared->sprg1;
	regs->sprg2 = vcpu->arch.shared->sprg2;
	regs->sprg3 = vcpu->arch.shared->sprg3;
439
440
441
442
	regs->sprg4 = vcpu->arch.shared->sprg4;
	regs->sprg5 = vcpu->arch.shared->sprg5;
	regs->sprg6 = vcpu->arch.shared->sprg6;
	regs->sprg7 = vcpu->arch.shared->sprg7;
Alexander Graf's avatar
Alexander Graf committed
443
444

	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
445
		regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
Alexander Graf's avatar
Alexander Graf committed
446
447
448
449
450
451
452
453

	return 0;
}

int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
{
	int i;

454
	kvmppc_set_pc(vcpu, regs->pc);
455
	kvmppc_set_cr(vcpu, regs->cr);
456
457
	kvmppc_set_ctr(vcpu, regs->ctr);
	kvmppc_set_lr(vcpu, regs->lr);
458
	kvmppc_set_xer(vcpu, regs->xer);
Alexander Graf's avatar
Alexander Graf committed
459
	kvmppc_set_msr(vcpu, regs->msr);
460
461
	vcpu->arch.shared->srr0 = regs->srr0;
	vcpu->arch.shared->srr1 = regs->srr1;
462
463
464
465
	vcpu->arch.shared->sprg0 = regs->sprg0;
	vcpu->arch.shared->sprg1 = regs->sprg1;
	vcpu->arch.shared->sprg2 = regs->sprg2;
	vcpu->arch.shared->sprg3 = regs->sprg3;
466
467
468
469
	vcpu->arch.shared->sprg4 = regs->sprg4;
	vcpu->arch.shared->sprg5 = regs->sprg5;
	vcpu->arch.shared->sprg6 = regs->sprg6;
	vcpu->arch.shared->sprg7 = regs->sprg7;
Alexander Graf's avatar
Alexander Graf committed
470

471
472
	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
		kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
Alexander Graf's avatar
Alexander Graf committed
473
474
475
476
477
478
479
480
481
482
483
484
485
486

	return 0;
}

int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
{
	return -ENOTSUPP;
}

int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
{
	return -ENOTSUPP;
}

487
488
489
490
491
int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
{
	int r;
	union kvmppc_one_reg val;
	int size;
492
	long int i;
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508

	size = one_reg_size(reg->id);
	if (size > sizeof(val))
		return -EINVAL;

	r = kvmppc_get_one_reg(vcpu, reg->id, &val);

	if (r == -EINVAL) {
		r = 0;
		switch (reg->id) {
		case KVM_REG_PPC_DAR:
			val = get_reg_val(reg->id, vcpu->arch.shared->dar);
			break;
		case KVM_REG_PPC_DSISR:
			val = get_reg_val(reg->id, vcpu->arch.shared->dsisr);
			break;
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
		case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
			i = reg->id - KVM_REG_PPC_FPR0;
			val = get_reg_val(reg->id, vcpu->arch.fpr[i]);
			break;
		case KVM_REG_PPC_FPSCR:
			val = get_reg_val(reg->id, vcpu->arch.fpscr);
			break;
#ifdef CONFIG_ALTIVEC
		case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
				r = -ENXIO;
				break;
			}
			val.vval = vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0];
			break;
		case KVM_REG_PPC_VSCR:
			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
				r = -ENXIO;
				break;
			}
			val = get_reg_val(reg->id, vcpu->arch.vscr.u[3]);
			break;
#endif /* CONFIG_ALTIVEC */
532
533
534
535
536
537
		case KVM_REG_PPC_DEBUG_INST: {
			u32 opcode = INS_TW;
			r = copy_to_user((u32 __user *)(long)reg->addr,
					 &opcode, sizeof(u32));
			break;
		}
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
		default:
			r = -EINVAL;
			break;
		}
	}
	if (r)
		return r;

	if (copy_to_user((char __user *)(unsigned long)reg->addr, &val, size))
		r = -EFAULT;

	return r;
}

int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
{
	int r;
	union kvmppc_one_reg val;
	int size;
557
	long int i;
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576

	size = one_reg_size(reg->id);
	if (size > sizeof(val))
		return -EINVAL;

	if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size))
		return -EFAULT;

	r = kvmppc_set_one_reg(vcpu, reg->id, &val);

	if (r == -EINVAL) {
		r = 0;
		switch (reg->id) {
		case KVM_REG_PPC_DAR:
			vcpu->arch.shared->dar = set_reg_val(reg->id, val);
			break;
		case KVM_REG_PPC_DSISR:
			vcpu->arch.shared->dsisr = set_reg_val(reg->id, val);
			break;
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
		case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
			i = reg->id - KVM_REG_PPC_FPR0;
			vcpu->arch.fpr[i] = set_reg_val(reg->id, val);
			break;
		case KVM_REG_PPC_FPSCR:
			vcpu->arch.fpscr = set_reg_val(reg->id, val);
			break;
#ifdef CONFIG_ALTIVEC
		case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
				r = -ENXIO;
				break;
			}
			vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
			break;
		case KVM_REG_PPC_VSCR:
			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
				r = -ENXIO;
				break;
			}
			vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val);
			break;
#endif /* CONFIG_ALTIVEC */
600
601
602
603
604
605
606
607
608
		default:
			r = -EINVAL;
			break;
		}
	}

	return r;
}

Alexander Graf's avatar
Alexander Graf committed
609
610
611
612
613
614
int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
                                  struct kvm_translation *tr)
{
	return 0;
}

615
616
617
618
619
620
621
void kvmppc_decrementer_func(unsigned long data)
{
	struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;

	kvmppc_core_queue_dec(vcpu);
	kvm_vcpu_kick(vcpu);
}