diff mbox

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

Message ID 7ae3d49bf9ce153a5460a393bfa513a585930487.1486377433.git-series.james.hogan@imgtec.com (mailing list archive)
State New, archived
Headers show

Commit Message

James Hogan Feb. 6, 2017, 10:46 a.m. UTC
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@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Andreas Herrmann <andreas.herrmann@caviumnetworks.com>
Cc: David Daney <david.daney@cavium.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Cc: linux-doc@vger.kernel.org
---
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(-)

Comments

Paolo Bonzini Feb. 6, 2017, 1:25 p.m. UTC | #1
On 06/02/2017 11:46, James Hogan wrote:
> 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?

The former.

But there are cases when using hypercalls is unavoidable.  In that case
the trend is to use other exit reasons than KVM_EXIT_HYPERCALL, such as
KVM_EXIT_PAPR_HCALL in PowerPC.  Feel free to add KVM_EXIT_MIPS_CONOUT
or something like that.

How would you find the character device to write to in QEMU?

Paolo
James Hogan Feb. 6, 2017, 2:06 p.m. UTC | #2
On Mon, Feb 06, 2017 at 02:25:59PM +0100, Paolo Bonzini wrote:
> 
> 
> On 06/02/2017 11:46, James Hogan wrote:
> > 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?
> 
> The former.

Okay, thanks.

> 
> But there are cases when using hypercalls is unavoidable.  In that case
> the trend is to use other exit reasons than KVM_EXIT_HYPERCALL, such as
> KVM_EXIT_PAPR_HCALL in PowerPC.  Feel free to add KVM_EXIT_MIPS_CONOUT
> or something like that.

Okay, that sounds sensible. The existing mips_paravirt_defconfig does
contain CONFIG_VIRTIO_CONSOLE=y though, so I'm thinking we may be able
to get away without this hypercall and without old paravirt guest
kernels becoming unusable.

David/Andreas: would you agree, or do you feel strongly that this
hypercall API should be kept? (with a different KVM exit reason)

> 
> How would you find the character device to write to in QEMU?

I imagine it'd need a custom character device driver in QEMU so it could
be wired up to stdio/pty or whatever using QEMU arguments. I've only
tested it with a test case in my own MIPS KVM test suite so far though.

Cheers
James
diff mbox

Patch

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();