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