diff options
-rw-r--r-- | Documentation/kvm/api.txt | 19 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_book3s.h | 5 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s.c | 24 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 12 | ||||
-rw-r--r-- | include/linux/kvm.h | 6 |
6 files changed, 59 insertions, 9 deletions
diff --git a/Documentation/kvm/api.txt b/Documentation/kvm/api.txt index f9724dc8d079..6f362356e738 100644 --- a/Documentation/kvm/api.txt +++ b/Documentation/kvm/api.txt | |||
@@ -958,9 +958,9 @@ executed a memory-mapped I/O instruction which could not be satisfied | |||
958 | by kvm. The 'data' member contains the written data if 'is_write' is | 958 | by kvm. The 'data' member contains the written data if 'is_write' is |
959 | true, and should be filled by application code otherwise. | 959 | true, and should be filled by application code otherwise. |
960 | 960 | ||
961 | NOTE: For KVM_EXIT_IO and KVM_EXIT_MMIO, the corresponding operations | 961 | NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO and KVM_EXIT_OSI, the corresponding |
962 | are complete (and guest state is consistent) only after userspace has | 962 | operations are complete (and guest state is consistent) only after userspace |
963 | re-entered the kernel with KVM_RUN. The kernel side will first finish | 963 | has re-entered the kernel with KVM_RUN. The kernel side will first finish |
964 | incomplete operations and then check for pending signals. Userspace | 964 | incomplete operations and then check for pending signals. Userspace |
965 | can re-enter the guest with an unmasked signal pending to complete | 965 | can re-enter the guest with an unmasked signal pending to complete |
966 | pending operations. | 966 | pending operations. |
@@ -1015,6 +1015,19 @@ s390 specific. | |||
1015 | 1015 | ||
1016 | powerpc specific. | 1016 | powerpc specific. |
1017 | 1017 | ||
1018 | /* KVM_EXIT_OSI */ | ||
1019 | struct { | ||
1020 | __u64 gprs[32]; | ||
1021 | } osi; | ||
1022 | |||
1023 | MOL uses a special hypercall interface it calls 'OSI'. To enable it, we catch | ||
1024 | hypercalls and exit with this exit struct that contains all the guest gprs. | ||
1025 | |||
1026 | If exit_reason is KVM_EXIT_OSI, then the vcpu has triggered such a hypercall. | ||
1027 | Userspace can now handle the hypercall and when it's done modify the gprs as | ||
1028 | necessary. Upon guest entry all guest GPRs will then be replaced by the values | ||
1029 | in this struct. | ||
1030 | |||
1018 | /* Fix the size of the union. */ | 1031 | /* Fix the size of the union. */ |
1019 | char padding[256]; | 1032 | char padding[256]; |
1020 | }; | 1033 | }; |
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index bea76371dbe1..7e243b2cac72 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h | |||
@@ -148,6 +148,11 @@ static inline ulong dsisr(void) | |||
148 | 148 | ||
149 | extern void kvm_return_point(void); | 149 | extern void kvm_return_point(void); |
150 | 150 | ||
151 | /* Magic register values loaded into r3 and r4 before the 'sc' assembly | ||
152 | * instruction for the OSI hypercalls */ | ||
153 | #define OSI_SC_MAGIC_R3 0x113724FA | ||
154 | #define OSI_SC_MAGIC_R4 0x77810F9B | ||
155 | |||
151 | #define INS_DCBZ 0x7c0007ec | 156 | #define INS_DCBZ 0x7c0007ec |
152 | 157 | ||
153 | #endif /* __ASM_KVM_BOOK3S_H__ */ | 158 | #endif /* __ASM_KVM_BOOK3S_H__ */ |
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 0ebda67ad6a8..486f1cafd5f7 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
@@ -273,6 +273,8 @@ struct kvm_vcpu_arch { | |||
273 | u8 mmio_sign_extend; | 273 | u8 mmio_sign_extend; |
274 | u8 dcr_needed; | 274 | u8 dcr_needed; |
275 | u8 dcr_is_write; | 275 | u8 dcr_is_write; |
276 | u8 osi_needed; | ||
277 | u8 osi_enabled; | ||
276 | 278 | ||
277 | u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */ | 279 | u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */ |
278 | 280 | ||
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index de12202fe1c6..7696d0f547e3 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c | |||
@@ -872,12 +872,24 @@ program_interrupt: | |||
872 | break; | 872 | break; |
873 | } | 873 | } |
874 | case BOOK3S_INTERRUPT_SYSCALL: | 874 | case BOOK3S_INTERRUPT_SYSCALL: |
875 | #ifdef EXIT_DEBUG | 875 | // XXX make user settable |
876 | printk(KERN_INFO "Syscall Nr %d\n", (int)kvmppc_get_gpr(vcpu, 0)); | 876 | if (vcpu->arch.osi_enabled && |
877 | #endif | 877 | (((u32)kvmppc_get_gpr(vcpu, 3)) == OSI_SC_MAGIC_R3) && |
878 | vcpu->stat.syscall_exits++; | 878 | (((u32)kvmppc_get_gpr(vcpu, 4)) == OSI_SC_MAGIC_R4)) { |
879 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | 879 | u64 *gprs = run->osi.gprs; |
880 | r = RESUME_GUEST; | 880 | int i; |
881 | |||
882 | run->exit_reason = KVM_EXIT_OSI; | ||
883 | for (i = 0; i < 32; i++) | ||
884 | gprs[i] = kvmppc_get_gpr(vcpu, i); | ||
885 | vcpu->arch.osi_needed = 1; | ||
886 | r = RESUME_HOST_NV; | ||
887 | |||
888 | } else { | ||
889 | vcpu->stat.syscall_exits++; | ||
890 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | ||
891 | r = RESUME_GUEST; | ||
892 | } | ||
881 | break; | 893 | break; |
882 | case BOOK3S_INTERRUPT_FP_UNAVAIL: | 894 | case BOOK3S_INTERRUPT_FP_UNAVAIL: |
883 | case BOOK3S_INTERRUPT_ALTIVEC: | 895 | case BOOK3S_INTERRUPT_ALTIVEC: |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 646bfd256e5d..9a4dd8146d39 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -151,6 +151,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
151 | case KVM_CAP_PPC_PAIRED_SINGLES: | 151 | case KVM_CAP_PPC_PAIRED_SINGLES: |
152 | case KVM_CAP_PPC_UNSET_IRQ: | 152 | case KVM_CAP_PPC_UNSET_IRQ: |
153 | case KVM_CAP_ENABLE_CAP: | 153 | case KVM_CAP_ENABLE_CAP: |
154 | case KVM_CAP_PPC_OSI: | ||
154 | r = 1; | 155 | r = 1; |
155 | break; | 156 | break; |
156 | case KVM_CAP_COALESCED_MMIO: | 157 | case KVM_CAP_COALESCED_MMIO: |
@@ -433,6 +434,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
433 | if (!vcpu->arch.dcr_is_write) | 434 | if (!vcpu->arch.dcr_is_write) |
434 | kvmppc_complete_dcr_load(vcpu, run); | 435 | kvmppc_complete_dcr_load(vcpu, run); |
435 | vcpu->arch.dcr_needed = 0; | 436 | vcpu->arch.dcr_needed = 0; |
437 | } else if (vcpu->arch.osi_needed) { | ||
438 | u64 *gprs = run->osi.gprs; | ||
439 | int i; | ||
440 | |||
441 | for (i = 0; i < 32; i++) | ||
442 | kvmppc_set_gpr(vcpu, i, gprs[i]); | ||
443 | vcpu->arch.osi_needed = 0; | ||
436 | } | 444 | } |
437 | 445 | ||
438 | kvmppc_core_deliver_interrupts(vcpu); | 446 | kvmppc_core_deliver_interrupts(vcpu); |
@@ -475,6 +483,10 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, | |||
475 | return -EINVAL; | 483 | return -EINVAL; |
476 | 484 | ||
477 | switch (cap->cap) { | 485 | switch (cap->cap) { |
486 | case KVM_CAP_PPC_OSI: | ||
487 | r = 0; | ||
488 | vcpu->arch.osi_enabled = true; | ||
489 | break; | ||
478 | default: | 490 | default: |
479 | r = -EINVAL; | 491 | r = -EINVAL; |
480 | break; | 492 | break; |
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index ecb68e433558..23ea02253900 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -160,6 +160,7 @@ struct kvm_pit_config { | |||
160 | #define KVM_EXIT_DCR 15 | 160 | #define KVM_EXIT_DCR 15 |
161 | #define KVM_EXIT_NMI 16 | 161 | #define KVM_EXIT_NMI 16 |
162 | #define KVM_EXIT_INTERNAL_ERROR 17 | 162 | #define KVM_EXIT_INTERNAL_ERROR 17 |
163 | #define KVM_EXIT_OSI 18 | ||
163 | 164 | ||
164 | /* For KVM_EXIT_INTERNAL_ERROR */ | 165 | /* For KVM_EXIT_INTERNAL_ERROR */ |
165 | #define KVM_INTERNAL_ERROR_EMULATION 1 | 166 | #define KVM_INTERNAL_ERROR_EMULATION 1 |
@@ -259,6 +260,10 @@ struct kvm_run { | |||
259 | __u32 ndata; | 260 | __u32 ndata; |
260 | __u64 data[16]; | 261 | __u64 data[16]; |
261 | } internal; | 262 | } internal; |
263 | /* KVM_EXIT_OSI */ | ||
264 | struct { | ||
265 | __u64 gprs[32]; | ||
266 | } osi; | ||
262 | /* Fix the size of the union. */ | 267 | /* Fix the size of the union. */ |
263 | char padding[256]; | 268 | char padding[256]; |
264 | }; | 269 | }; |
@@ -516,6 +521,7 @@ struct kvm_enable_cap { | |||
516 | #define KVM_CAP_DEBUGREGS 50 | 521 | #define KVM_CAP_DEBUGREGS 50 |
517 | #endif | 522 | #endif |
518 | #define KVM_CAP_X86_ROBUST_SINGLESTEP 51 | 523 | #define KVM_CAP_X86_ROBUST_SINGLESTEP 51 |
524 | #define KVM_CAP_PPC_OSI 52 | ||
519 | #define KVM_CAP_PPC_UNSET_IRQ 53 | 525 | #define KVM_CAP_PPC_UNSET_IRQ 53 |
520 | #define KVM_CAP_ENABLE_CAP 54 | 526 | #define KVM_CAP_ENABLE_CAP 54 |
521 | 527 | ||