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