aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-03-24 16:48:30 -0400
committerAvi Kivity <avi@redhat.com>2010-05-17 05:17:10 -0400
commitad0a048b096ac819f28667602285453468a8d8f9 (patch)
tree491128ccab48eb277a5cf5919a798b0507da9859
parent71fbfd5f38f73515f1516a68fbe04dba198b70f0 (diff)
KVM: PPC: Add OSI hypercall interface
MOL uses its own hypercall interface to call back into userspace when the guest wants to do something. So let's implement that as an exit reason, specify it with a CAP and only really use it when userspace wants us to. The only user of it so far is MOL. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Documentation/kvm/api.txt19
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h5
-rw-r--r--arch/powerpc/include/asm/kvm_host.h2
-rw-r--r--arch/powerpc/kvm/book3s.c24
-rw-r--r--arch/powerpc/kvm/powerpc.c12
-rw-r--r--include/linux/kvm.h6
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
958by kvm. The 'data' member contains the written data if 'is_write' is 958by kvm. The 'data' member contains the written data if 'is_write' is
959true, and should be filled by application code otherwise. 959true, and should be filled by application code otherwise.
960 960
961NOTE: For KVM_EXIT_IO and KVM_EXIT_MMIO, the corresponding operations 961NOTE: For KVM_EXIT_IO, KVM_EXIT_MMIO and KVM_EXIT_OSI, the corresponding
962are complete (and guest state is consistent) only after userspace has 962operations are complete (and guest state is consistent) only after userspace
963re-entered the kernel with KVM_RUN. The kernel side will first finish 963has re-entered the kernel with KVM_RUN. The kernel side will first finish
964incomplete operations and then check for pending signals. Userspace 964incomplete operations and then check for pending signals. Userspace
965can re-enter the guest with an unmasked signal pending to complete 965can re-enter the guest with an unmasked signal pending to complete
966pending operations. 966pending operations.
@@ -1015,6 +1015,19 @@ s390 specific.
1015 1015
1016powerpc specific. 1016powerpc specific.
1017 1017
1018 /* KVM_EXIT_OSI */
1019 struct {
1020 __u64 gprs[32];
1021 } osi;
1022
1023MOL uses a special hypercall interface it calls 'OSI'. To enable it, we catch
1024hypercalls and exit with this exit struct that contains all the guest gprs.
1025
1026If exit_reason is KVM_EXIT_OSI, then the vcpu has triggered such a hypercall.
1027Userspace can now handle the hypercall and when it's done modify the gprs as
1028necessary. Upon guest entry all guest GPRs will then be replaced by the values
1029in 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
149extern void kvm_return_point(void); 149extern 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