xref: /kvmtool/powerpc/spapr_hvcons.c (revision 7652598814f70e0d25a2fab04d6cc9199a1cc797)
17295767dSMatt Evans /*
27295767dSMatt Evans  * SPAPR HV console
37295767dSMatt Evans  *
47295767dSMatt Evans  * Borrowed lightly from QEMU's spapr_vty.c, Copyright (c) 2010 David Gibson,
57295767dSMatt Evans  * IBM Corporation.
67295767dSMatt Evans  *
77295767dSMatt Evans  * Copyright (c) 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
87295767dSMatt Evans  *
97295767dSMatt Evans  * This program is free software; you can redistribute it and/or modify it
107295767dSMatt Evans  * under the terms of the GNU General Public License version 2 as published
117295767dSMatt Evans  * by the Free Software Foundation.
127295767dSMatt Evans  */
137295767dSMatt Evans 
147295767dSMatt Evans #include "kvm/term.h"
157295767dSMatt Evans #include "kvm/kvm.h"
167295767dSMatt Evans #include "kvm/kvm-cpu.h"
177295767dSMatt Evans #include "kvm/util.h"
187295767dSMatt Evans #include "spapr.h"
197295767dSMatt Evans #include "spapr_hvcons.h"
207295767dSMatt Evans 
217295767dSMatt Evans #include <stdio.h>
227295767dSMatt Evans #include <sys/uio.h>
237295767dSMatt Evans #include <errno.h>
247295767dSMatt Evans 
257295767dSMatt Evans #include <linux/byteorder.h>
267295767dSMatt Evans 
277295767dSMatt Evans union hv_chario {
287295767dSMatt Evans 	struct {
297295767dSMatt Evans 		uint64_t char0_7;
307295767dSMatt Evans 		uint64_t char8_15;
317295767dSMatt Evans 	} a;
327295767dSMatt Evans 	uint8_t buf[16];
337295767dSMatt Evans };
347295767dSMatt Evans 
h_put_term_char(struct kvm_cpu * vcpu,unsigned long opcode,unsigned long * args)357295767dSMatt Evans static unsigned long h_put_term_char(struct kvm_cpu *vcpu, unsigned long opcode, unsigned long *args)
367295767dSMatt Evans {
377295767dSMatt Evans 	/* To do: Read register from args[0], and check it. */
387295767dSMatt Evans 	unsigned long len = args[1];
397295767dSMatt Evans 	union hv_chario data;
407295767dSMatt Evans 	struct iovec iov;
417295767dSMatt Evans 
427295767dSMatt Evans 	if (len > 16) {
437295767dSMatt Evans 		return H_PARAMETER;
447295767dSMatt Evans 	}
457295767dSMatt Evans 	data.a.char0_7 = cpu_to_be64(args[2]);
467295767dSMatt Evans 	data.a.char8_15 = cpu_to_be64(args[3]);
477295767dSMatt Evans 
487295767dSMatt Evans 	iov.iov_base = data.buf;
497295767dSMatt Evans 	iov.iov_len = len;
507295767dSMatt Evans 	do {
517295767dSMatt Evans 		int ret;
527295767dSMatt Evans 
532651ea58SSasha Levin 		ret = term_putc_iov(&iov, 1, 0);
547295767dSMatt Evans 		if (ret < 0) {
557295767dSMatt Evans 			die("term_putc_iov error %d!\n", errno);
567295767dSMatt Evans 		}
577295767dSMatt Evans 		iov.iov_base += ret;
587295767dSMatt Evans 		iov.iov_len -= ret;
597295767dSMatt Evans 	} while (iov.iov_len > 0);
607295767dSMatt Evans 
617295767dSMatt Evans 	return H_SUCCESS;
627295767dSMatt Evans }
637295767dSMatt Evans 
647295767dSMatt Evans 
h_get_term_char(struct kvm_cpu * vcpu,unsigned long opcode,unsigned long * args)657295767dSMatt Evans static unsigned long h_get_term_char(struct kvm_cpu *vcpu, unsigned long opcode, unsigned long *args)
667295767dSMatt Evans {
677295767dSMatt Evans 	/* To do: Read register from args[0], and check it. */
687295767dSMatt Evans 	unsigned long *len = args + 0;
697295767dSMatt Evans 	unsigned long *char0_7 = args + 1;
707295767dSMatt Evans 	unsigned long *char8_15 = args + 2;
717295767dSMatt Evans 	union hv_chario data;
727295767dSMatt Evans 	struct iovec iov;
737295767dSMatt Evans 
74*dc4fc6b6SMichael Ellerman 	if (vcpu->kvm->cfg.active_console != CONSOLE_HV)
752651ea58SSasha Levin 		return H_SUCCESS;
762651ea58SSasha Levin 
772651ea58SSasha Levin 	if (term_readable(0)) {
787295767dSMatt Evans 		iov.iov_base = data.buf;
797295767dSMatt Evans 		iov.iov_len = 16;
807295767dSMatt Evans 
81*dc4fc6b6SMichael Ellerman 		*len = term_getc_iov(vcpu->kvm, &iov, 1, 0);
827295767dSMatt Evans 		*char0_7 = be64_to_cpu(data.a.char0_7);
837295767dSMatt Evans 		*char8_15 = be64_to_cpu(data.a.char8_15);
847295767dSMatt Evans 	} else {
857295767dSMatt Evans 		*len = 0;
867295767dSMatt Evans 	}
877295767dSMatt Evans 
887295767dSMatt Evans 	return H_SUCCESS;
897295767dSMatt Evans }
907295767dSMatt Evans 
spapr_hvcons_poll(struct kvm * kvm)917295767dSMatt Evans void spapr_hvcons_poll(struct kvm *kvm)
927295767dSMatt Evans {
932651ea58SSasha Levin 	if (term_readable(0)) {
947295767dSMatt Evans 		/*
957295767dSMatt Evans 		 * We can inject an IRQ to guest here if we want.  The guest
967295767dSMatt Evans 		 * will happily poll, though, so not required.
977295767dSMatt Evans 		 */
987295767dSMatt Evans 	}
997295767dSMatt Evans }
1007295767dSMatt Evans 
spapr_hvcons_init(void)1017295767dSMatt Evans void spapr_hvcons_init(void)
1027295767dSMatt Evans {
1037295767dSMatt Evans 	spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
1047295767dSMatt Evans 	spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
1057295767dSMatt Evans }
106