[PATCH 4/4] KVM: MIPS: Implement console output hypercall

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Implement console output hypercall by exiting back to userland with
KVM_EXIT_HYPERCALL, and setting the return value on next KVM_RUN.

We also document the hypercall along with the others as the
documentation was never added

Signed-off-by: James Hogan <james.hogan@xxxxxxxxxx>
Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx>
Cc: "Radim Krčmář" <rkrcmar@xxxxxxxxxx>
Cc: Ralf Baechle <ralf@xxxxxxxxxxxxxx>
Cc: Andreas Herrmann <andreas.herrmann@xxxxxxxxxxxxxxxxxx>
Cc: David Daney <david.daney@xxxxxxxxxx>
Cc: Jonathan Corbet <corbet@xxxxxxx>
Cc: linux-mips@xxxxxxxxxxxxxx
Cc: kvm@xxxxxxxxxxxxxxx
Cc: linux-doc@xxxxxxxxxxxxxxx
---
Documentation/virtual/kvm/api.txt seems to suggest that
KVM_EXIT_HYPERCALL is obsolete. When it suggests using KVM_EXIT_MMIO,
does it simply mean the guest should use MMIO to some virtio device of
some sort rather than using hypercalls, or that the hypercall should
somehow be munged into the mmio exit information?
---
 Documentation/virtual/kvm/hypercalls.txt | 10 ++++++++++
 arch/mips/include/asm/kvm_host.h         |  4 ++++
 arch/mips/kvm/hypcall.c                  | 20 ++++++++++++++++++++
 arch/mips/kvm/mips.c                     |  3 +++
 4 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/Documentation/virtual/kvm/hypercalls.txt b/Documentation/virtual/kvm/hypercalls.txt
index f8108c84c46b..4e6e57026bfe 100644
--- a/Documentation/virtual/kvm/hypercalls.txt
+++ b/Documentation/virtual/kvm/hypercalls.txt
@@ -98,3 +98,13 @@ Purpose: Return the frequency of CP0_Count in HZ.
 Architecture: mips
 Status: active
 Purpose: Shut down the virtual machine.
+
+8. KVM_HC_MIPS_CONSOLE_OUTPUT
+------------------------
+Architecture: mips
+Status: active
+Purpose: Output a string to a console.
+Argument 1 contains the virtual terminal number to write to.
+Argument 2 contains a guest virtual address pointer to the string, which must
+be in an unmapped virtual memory segment (e.g. KSeg0, KSeg1 or XKPhys).
+Argument 3 contains the number of bytes to write.
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index 0d308d4f2429..e0f1da0c35e9 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -309,6 +309,9 @@ struct kvm_vcpu_arch {
 	/* GPR used as IO source/target */
 	u32 io_gpr;
 
+	/* Whether a hypercall needs completing */
+	int hypercall_needed;
+
 	struct hrtimer comparecount_timer;
 	/* Count timer control KVM register */
 	u32 count_ctl;
@@ -838,6 +841,7 @@ unsigned int kvm_mips_config5_wrmask(struct kvm_vcpu *vcpu);
 enum emulation_result kvm_mips_emul_hypcall(struct kvm_vcpu *vcpu,
 					    union mips_instruction inst);
 int kvm_mips_handle_hypcall(struct kvm_vcpu *vcpu);
+void kvm_mips_complete_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run);
 
 /* Dynamic binary translation */
 extern int kvm_mips_trans_cache_index(union mips_instruction inst,
diff --git a/arch/mips/kvm/hypcall.c b/arch/mips/kvm/hypcall.c
index c3345e5eec02..9cb8f37ca43a 100644
--- a/arch/mips/kvm/hypcall.c
+++ b/arch/mips/kvm/hypcall.c
@@ -33,6 +33,7 @@ static int kvm_mips_hypercall(struct kvm_vcpu *vcpu, unsigned long num,
 			      const unsigned long *args, unsigned long *hret)
 {
 	int ret = RESUME_GUEST;
+	int i;
 
 	switch (num) {
 	case KVM_HC_MIPS_GET_CLOCK_FREQ:
@@ -49,6 +50,19 @@ static int kvm_mips_hypercall(struct kvm_vcpu *vcpu, unsigned long num,
 		ret = RESUME_HOST;
 		break;
 
+	/* Hypercalls passed to userland to handle */
+	case KVM_HC_MIPS_CONSOLE_OUTPUT:
+		/* Pass to userland via KVM_EXIT_HYPERCALL */
+		memset(&vcpu->run->hypercall, 0, sizeof(vcpu->run->hypercall));
+		vcpu->run->hypercall.nr = num;
+		for (i = 0; i < MAX_HYPCALL_ARGS; ++i)
+			vcpu->run->hypercall.args[i] = args[i];
+		vcpu->run->hypercall.ret = -KVM_ENOSYS; /* default */
+		vcpu->run->exit_reason = KVM_EXIT_HYPERCALL;
+		vcpu->arch.hypercall_needed = 1;
+		ret = RESUME_HOST;
+		break;
+
 	default:
 		/* Report unimplemented hypercall to guest */
 		*hret = -KVM_ENOSYS;
@@ -72,3 +86,9 @@ int kvm_mips_handle_hypcall(struct kvm_vcpu *vcpu)
 	return kvm_mips_hypercall(vcpu, num,
 				  args, &vcpu->arch.gprs[2] /* v0 */);
 }
+
+void kvm_mips_complete_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	vcpu->arch.gprs[2] = run->hypercall.ret;	/* v0 */
+	vcpu->arch.hypercall_needed = 0;
+}
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index 31ee5ee0010b..1c23dc29db5d 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -409,6 +409,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 		vcpu->mmio_needed = 0;
 	}
 
+	if (vcpu->arch.hypercall_needed)
+		kvm_mips_complete_hypercall(vcpu, run);
+
 	lose_fpu(1);
 
 	local_irq_disable();
-- 
git-series 0.8.10



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux