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