xref: /kvmtool/powerpc/spapr_hvcons.c (revision 7295767d4dbdb04136ba6cfbf1150cdad0745165)
1*7295767dSMatt Evans /*
2*7295767dSMatt Evans  * SPAPR HV console
3*7295767dSMatt Evans  *
4*7295767dSMatt Evans  * Borrowed lightly from QEMU's spapr_vty.c, Copyright (c) 2010 David Gibson,
5*7295767dSMatt Evans  * IBM Corporation.
6*7295767dSMatt Evans  *
7*7295767dSMatt Evans  * Copyright (c) 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
8*7295767dSMatt Evans  *
9*7295767dSMatt Evans  * This program is free software; you can redistribute it and/or modify it
10*7295767dSMatt Evans  * under the terms of the GNU General Public License version 2 as published
11*7295767dSMatt Evans  * by the Free Software Foundation.
12*7295767dSMatt Evans  */
13*7295767dSMatt Evans 
14*7295767dSMatt Evans #include "kvm/term.h"
15*7295767dSMatt Evans #include "kvm/kvm.h"
16*7295767dSMatt Evans #include "kvm/kvm-cpu.h"
17*7295767dSMatt Evans #include "kvm/util.h"
18*7295767dSMatt Evans #include "spapr.h"
19*7295767dSMatt Evans #include "spapr_hvcons.h"
20*7295767dSMatt Evans 
21*7295767dSMatt Evans #include <stdio.h>
22*7295767dSMatt Evans #include <sys/uio.h>
23*7295767dSMatt Evans #include <errno.h>
24*7295767dSMatt Evans 
25*7295767dSMatt Evans #include <linux/byteorder.h>
26*7295767dSMatt Evans 
27*7295767dSMatt Evans union hv_chario {
28*7295767dSMatt Evans 	struct {
29*7295767dSMatt Evans 		uint64_t char0_7;
30*7295767dSMatt Evans 		uint64_t char8_15;
31*7295767dSMatt Evans 	} a;
32*7295767dSMatt Evans 	uint8_t buf[16];
33*7295767dSMatt Evans };
34*7295767dSMatt Evans 
35*7295767dSMatt Evans static unsigned long h_put_term_char(struct kvm_cpu *vcpu, unsigned long opcode, unsigned long *args)
36*7295767dSMatt Evans {
37*7295767dSMatt Evans 	/* To do: Read register from args[0], and check it. */
38*7295767dSMatt Evans 	unsigned long len = args[1];
39*7295767dSMatt Evans 	union hv_chario data;
40*7295767dSMatt Evans 	struct iovec iov;
41*7295767dSMatt Evans 
42*7295767dSMatt Evans 	if (len > 16) {
43*7295767dSMatt Evans 		return H_PARAMETER;
44*7295767dSMatt Evans 	}
45*7295767dSMatt Evans 	data.a.char0_7 = cpu_to_be64(args[2]);
46*7295767dSMatt Evans 	data.a.char8_15 = cpu_to_be64(args[3]);
47*7295767dSMatt Evans 
48*7295767dSMatt Evans 	iov.iov_base = data.buf;
49*7295767dSMatt Evans 	iov.iov_len = len;
50*7295767dSMatt Evans 	do {
51*7295767dSMatt Evans 		int ret;
52*7295767dSMatt Evans 
53*7295767dSMatt Evans 		ret = term_putc_iov(CONSOLE_HV, &iov, 1, 0);
54*7295767dSMatt Evans 		if (ret < 0) {
55*7295767dSMatt Evans 			die("term_putc_iov error %d!\n", errno);
56*7295767dSMatt Evans 		}
57*7295767dSMatt Evans 		iov.iov_base += ret;
58*7295767dSMatt Evans 		iov.iov_len -= ret;
59*7295767dSMatt Evans 	} while (iov.iov_len > 0);
60*7295767dSMatt Evans 
61*7295767dSMatt Evans 	return H_SUCCESS;
62*7295767dSMatt Evans }
63*7295767dSMatt Evans 
64*7295767dSMatt Evans 
65*7295767dSMatt Evans static unsigned long h_get_term_char(struct kvm_cpu *vcpu, unsigned long opcode, unsigned long *args)
66*7295767dSMatt Evans {
67*7295767dSMatt Evans 	/* To do: Read register from args[0], and check it. */
68*7295767dSMatt Evans 	unsigned long *len = args + 0;
69*7295767dSMatt Evans 	unsigned long *char0_7 = args + 1;
70*7295767dSMatt Evans 	unsigned long *char8_15 = args + 2;
71*7295767dSMatt Evans 	union hv_chario data;
72*7295767dSMatt Evans 	struct iovec iov;
73*7295767dSMatt Evans 
74*7295767dSMatt Evans 	if (term_readable(CONSOLE_HV, 0)) {
75*7295767dSMatt Evans 		iov.iov_base = data.buf;
76*7295767dSMatt Evans 		iov.iov_len = 16;
77*7295767dSMatt Evans 
78*7295767dSMatt Evans 		*len = term_getc_iov(CONSOLE_HV, &iov, 1, 0);
79*7295767dSMatt Evans 		*char0_7 = be64_to_cpu(data.a.char0_7);
80*7295767dSMatt Evans 		*char8_15 = be64_to_cpu(data.a.char8_15);
81*7295767dSMatt Evans 	} else {
82*7295767dSMatt Evans 		*len = 0;
83*7295767dSMatt Evans 	}
84*7295767dSMatt Evans 
85*7295767dSMatt Evans 	return H_SUCCESS;
86*7295767dSMatt Evans }
87*7295767dSMatt Evans 
88*7295767dSMatt Evans void spapr_hvcons_poll(struct kvm *kvm)
89*7295767dSMatt Evans {
90*7295767dSMatt Evans 	if (term_readable(CONSOLE_HV, 0)) {
91*7295767dSMatt Evans 		/*
92*7295767dSMatt Evans 		 * We can inject an IRQ to guest here if we want.  The guest
93*7295767dSMatt Evans 		 * will happily poll, though, so not required.
94*7295767dSMatt Evans 		 */
95*7295767dSMatt Evans 	}
96*7295767dSMatt Evans }
97*7295767dSMatt Evans 
98*7295767dSMatt Evans void spapr_hvcons_init(void)
99*7295767dSMatt Evans {
100*7295767dSMatt Evans 	spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char);
101*7295767dSMatt Evans 	spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char);
102*7295767dSMatt Evans }
103