diff options
Diffstat (limited to 'arch/powerpc/kvm/book3s.c')
-rw-r--r-- | arch/powerpc/kvm/book3s.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 3f2a8360c857..a4b645285240 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c | |||
@@ -411,6 +411,15 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
411 | return 0; | 411 | return 0; |
412 | } | 412 | } |
413 | 413 | ||
414 | int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu) | ||
415 | { | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu) | ||
420 | { | ||
421 | } | ||
422 | |||
414 | int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | 423 | int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) |
415 | { | 424 | { |
416 | int i; | 425 | int i; |
@@ -476,6 +485,122 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | |||
476 | return -ENOTSUPP; | 485 | return -ENOTSUPP; |
477 | } | 486 | } |
478 | 487 | ||
488 | int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | ||
489 | { | ||
490 | int r; | ||
491 | union kvmppc_one_reg val; | ||
492 | int size; | ||
493 | long int i; | ||
494 | |||
495 | size = one_reg_size(reg->id); | ||
496 | if (size > sizeof(val)) | ||
497 | return -EINVAL; | ||
498 | |||
499 | r = kvmppc_get_one_reg(vcpu, reg->id, &val); | ||
500 | |||
501 | if (r == -EINVAL) { | ||
502 | r = 0; | ||
503 | switch (reg->id) { | ||
504 | case KVM_REG_PPC_DAR: | ||
505 | val = get_reg_val(reg->id, vcpu->arch.shared->dar); | ||
506 | break; | ||
507 | case KVM_REG_PPC_DSISR: | ||
508 | val = get_reg_val(reg->id, vcpu->arch.shared->dsisr); | ||
509 | break; | ||
510 | case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: | ||
511 | i = reg->id - KVM_REG_PPC_FPR0; | ||
512 | val = get_reg_val(reg->id, vcpu->arch.fpr[i]); | ||
513 | break; | ||
514 | case KVM_REG_PPC_FPSCR: | ||
515 | val = get_reg_val(reg->id, vcpu->arch.fpscr); | ||
516 | break; | ||
517 | #ifdef CONFIG_ALTIVEC | ||
518 | case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31: | ||
519 | if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { | ||
520 | r = -ENXIO; | ||
521 | break; | ||
522 | } | ||
523 | val.vval = vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0]; | ||
524 | break; | ||
525 | case KVM_REG_PPC_VSCR: | ||
526 | if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { | ||
527 | r = -ENXIO; | ||
528 | break; | ||
529 | } | ||
530 | val = get_reg_val(reg->id, vcpu->arch.vscr.u[3]); | ||
531 | break; | ||
532 | #endif /* CONFIG_ALTIVEC */ | ||
533 | default: | ||
534 | r = -EINVAL; | ||
535 | break; | ||
536 | } | ||
537 | } | ||
538 | if (r) | ||
539 | return r; | ||
540 | |||
541 | if (copy_to_user((char __user *)(unsigned long)reg->addr, &val, size)) | ||
542 | r = -EFAULT; | ||
543 | |||
544 | return r; | ||
545 | } | ||
546 | |||
547 | int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | ||
548 | { | ||
549 | int r; | ||
550 | union kvmppc_one_reg val; | ||
551 | int size; | ||
552 | long int i; | ||
553 | |||
554 | size = one_reg_size(reg->id); | ||
555 | if (size > sizeof(val)) | ||
556 | return -EINVAL; | ||
557 | |||
558 | if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size)) | ||
559 | return -EFAULT; | ||
560 | |||
561 | r = kvmppc_set_one_reg(vcpu, reg->id, &val); | ||
562 | |||
563 | if (r == -EINVAL) { | ||
564 | r = 0; | ||
565 | switch (reg->id) { | ||
566 | case KVM_REG_PPC_DAR: | ||
567 | vcpu->arch.shared->dar = set_reg_val(reg->id, val); | ||
568 | break; | ||
569 | case KVM_REG_PPC_DSISR: | ||
570 | vcpu->arch.shared->dsisr = set_reg_val(reg->id, val); | ||
571 | break; | ||
572 | case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: | ||
573 | i = reg->id - KVM_REG_PPC_FPR0; | ||
574 | vcpu->arch.fpr[i] = set_reg_val(reg->id, val); | ||
575 | break; | ||
576 | case KVM_REG_PPC_FPSCR: | ||
577 | vcpu->arch.fpscr = set_reg_val(reg->id, val); | ||
578 | break; | ||
579 | #ifdef CONFIG_ALTIVEC | ||
580 | case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31: | ||
581 | if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { | ||
582 | r = -ENXIO; | ||
583 | break; | ||
584 | } | ||
585 | vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0] = val.vval; | ||
586 | break; | ||
587 | case KVM_REG_PPC_VSCR: | ||
588 | if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { | ||
589 | r = -ENXIO; | ||
590 | break; | ||
591 | } | ||
592 | vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val); | ||
593 | break; | ||
594 | #endif /* CONFIG_ALTIVEC */ | ||
595 | default: | ||
596 | r = -EINVAL; | ||
597 | break; | ||
598 | } | ||
599 | } | ||
600 | |||
601 | return r; | ||
602 | } | ||
603 | |||
479 | int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, | 604 | int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, |
480 | struct kvm_translation *tr) | 605 | struct kvm_translation *tr) |
481 | { | 606 | { |