aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarsten Otte <cotte@de.ibm.com>2012-01-04 04:25:22 -0500
committerAvi Kivity <avi@redhat.com>2012-03-05 07:52:19 -0500
commite168bf8de33e16a909df2401af1f7d419c5780de (patch)
tree49dee8cc76e65eb1347895a6cb8f8843f690066d
parent27e0393f15fc8bc855c6a888387ff5ffd2181089 (diff)
KVM: s390: ucontrol: export page faults to user
This patch introduces a new exit reason in the kvm_run structure named KVM_EXIT_S390_UCONTROL. This exit indicates, that a virtual cpu has regognized a fault on the host page table. The idea is that userspace can handle this fault by mapping memory at the fault location into the cpu's address space and then continue to run the virtual cpu. Signed-off-by: Carsten Otte <cotte@de.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Documentation/virtual/kvm/api.txt14
-rw-r--r--arch/s390/kvm/kvm-s390.c32
-rw-r--r--arch/s390/kvm/kvm-s390.h1
-rw-r--r--include/linux/kvm.h6
4 files changed, 48 insertions, 5 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index ee394b26326..6e53ff51422 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1694,6 +1694,20 @@ s390 specific.
1694 1694
1695s390 specific. 1695s390 specific.
1696 1696
1697 /* KVM_EXIT_S390_UCONTROL */
1698 struct {
1699 __u64 trans_exc_code;
1700 __u32 pgm_code;
1701 } s390_ucontrol;
1702
1703s390 specific. A page fault has occurred for a user controlled virtual
1704machine (KVM_VM_S390_UNCONTROL) on it's host page table that cannot be
1705resolved by the kernel.
1706The program code and the translation exception code that were placed
1707in the cpu's lowcore are presented here as defined by the z Architecture
1708Principles of Operation Book in the Chapter for Dynamic Address Translation
1709(DAT)
1710
1697 /* KVM_EXIT_DCR */ 1711 /* KVM_EXIT_DCR */
1698 struct { 1712 struct {
1699 __u32 dcrn; 1713 __u32 dcrn;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 2d3248895de..af05328aca2 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -493,8 +493,10 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
493 return -EINVAL; /* not implemented yet */ 493 return -EINVAL; /* not implemented yet */
494} 494}
495 495
496static void __vcpu_run(struct kvm_vcpu *vcpu) 496static int __vcpu_run(struct kvm_vcpu *vcpu)
497{ 497{
498 int rc;
499
498 memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16); 500 memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
499 501
500 if (need_resched()) 502 if (need_resched())
@@ -511,9 +513,15 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
511 local_irq_enable(); 513 local_irq_enable();
512 VCPU_EVENT(vcpu, 6, "entering sie flags %x", 514 VCPU_EVENT(vcpu, 6, "entering sie flags %x",
513 atomic_read(&vcpu->arch.sie_block->cpuflags)); 515 atomic_read(&vcpu->arch.sie_block->cpuflags));
514 if (sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs)) { 516 rc = sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs);
515 VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction"); 517 if (rc) {
516 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 518 if (kvm_is_ucontrol(vcpu->kvm)) {
519 rc = SIE_INTERCEPT_UCONTROL;
520 } else {
521 VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
522 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
523 rc = 0;
524 }
517 } 525 }
518 VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", 526 VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
519 vcpu->arch.sie_block->icptcode); 527 vcpu->arch.sie_block->icptcode);
@@ -522,6 +530,7 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
522 local_irq_enable(); 530 local_irq_enable();
523 531
524 memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16); 532 memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16);
533 return rc;
525} 534}
526 535
527int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 536int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -542,6 +551,7 @@ rerun_vcpu:
542 case KVM_EXIT_UNKNOWN: 551 case KVM_EXIT_UNKNOWN:
543 case KVM_EXIT_INTR: 552 case KVM_EXIT_INTR:
544 case KVM_EXIT_S390_RESET: 553 case KVM_EXIT_S390_RESET:
554 case KVM_EXIT_S390_UCONTROL:
545 break; 555 break;
546 default: 556 default:
547 BUG(); 557 BUG();
@@ -553,7 +563,9 @@ rerun_vcpu:
553 might_fault(); 563 might_fault();
554 564
555 do { 565 do {
556 __vcpu_run(vcpu); 566 rc = __vcpu_run(vcpu);
567 if (rc)
568 break;
557 rc = kvm_handle_sie_intercept(vcpu); 569 rc = kvm_handle_sie_intercept(vcpu);
558 } while (!signal_pending(current) && !rc); 570 } while (!signal_pending(current) && !rc);
559 571
@@ -565,6 +577,16 @@ rerun_vcpu:
565 rc = -EINTR; 577 rc = -EINTR;
566 } 578 }
567 579
580#ifdef CONFIG_KVM_S390_UCONTROL
581 if (rc == SIE_INTERCEPT_UCONTROL) {
582 kvm_run->exit_reason = KVM_EXIT_S390_UCONTROL;
583 kvm_run->s390_ucontrol.trans_exc_code =
584 current->thread.gmap_addr;
585 kvm_run->s390_ucontrol.pgm_code = 0x10;
586 rc = 0;
587 }
588#endif
589
568 if (rc == -EOPNOTSUPP) { 590 if (rc == -EOPNOTSUPP) {
569 /* intercept cannot be handled in-kernel, prepare kvm-run */ 591 /* intercept cannot be handled in-kernel, prepare kvm-run */
570 kvm_run->exit_reason = KVM_EXIT_S390_SIEIC; 592 kvm_run->exit_reason = KVM_EXIT_S390_SIEIC;
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 45b236a7c73..62aa5f19bb9 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -26,6 +26,7 @@ typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
26 26
27/* negativ values are error codes, positive values for internal conditions */ 27/* negativ values are error codes, positive values for internal conditions */
28#define SIE_INTERCEPT_RERUNVCPU (1<<0) 28#define SIE_INTERCEPT_RERUNVCPU (1<<0)
29#define SIE_INTERCEPT_UCONTROL (1<<1)
29int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu); 30int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu);
30 31
31#define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\ 32#define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 0a66c107269..7f686f6708b 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -162,6 +162,7 @@ struct kvm_pit_config {
162#define KVM_EXIT_INTERNAL_ERROR 17 162#define KVM_EXIT_INTERNAL_ERROR 17
163#define KVM_EXIT_OSI 18 163#define KVM_EXIT_OSI 18
164#define KVM_EXIT_PAPR_HCALL 19 164#define KVM_EXIT_PAPR_HCALL 19
165#define KVM_EXIT_S390_UCONTROL 20
165 166
166/* For KVM_EXIT_INTERNAL_ERROR */ 167/* For KVM_EXIT_INTERNAL_ERROR */
167#define KVM_INTERNAL_ERROR_EMULATION 1 168#define KVM_INTERNAL_ERROR_EMULATION 1
@@ -249,6 +250,11 @@ struct kvm_run {
249#define KVM_S390_RESET_CPU_INIT 8 250#define KVM_S390_RESET_CPU_INIT 8
250#define KVM_S390_RESET_IPL 16 251#define KVM_S390_RESET_IPL 16
251 __u64 s390_reset_flags; 252 __u64 s390_reset_flags;
253 /* KVM_EXIT_S390_UCONTROL */
254 struct {
255 __u64 trans_exc_code;
256 __u32 pgm_code;
257 } s390_ucontrol;
252 /* KVM_EXIT_DCR */ 258 /* KVM_EXIT_DCR */
253 struct { 259 struct {
254 __u32 dcrn; 260 __u32 dcrn;