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 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 53*dc4fc6b6SMichael Ellerman if (vcpu->kvm->cfg.active_console == CONSOLE_HV) 542651ea58SSasha Levin ret = term_putc_iov(&iov, 1, 0); 552651ea58SSasha Levin else 562651ea58SSasha Levin ret = 0; 577295767dSMatt Evans if (ret < 0) { 587295767dSMatt Evans die("term_putc_iov error %d!\n", errno); 597295767dSMatt Evans } 607295767dSMatt Evans iov.iov_base += ret; 617295767dSMatt Evans iov.iov_len -= ret; 627295767dSMatt Evans } while (iov.iov_len > 0); 637295767dSMatt Evans 647295767dSMatt Evans return H_SUCCESS; 657295767dSMatt Evans } 667295767dSMatt Evans 677295767dSMatt Evans 687295767dSMatt Evans static unsigned long h_get_term_char(struct kvm_cpu *vcpu, unsigned long opcode, unsigned long *args) 697295767dSMatt Evans { 707295767dSMatt Evans /* To do: Read register from args[0], and check it. */ 717295767dSMatt Evans unsigned long *len = args + 0; 727295767dSMatt Evans unsigned long *char0_7 = args + 1; 737295767dSMatt Evans unsigned long *char8_15 = args + 2; 747295767dSMatt Evans union hv_chario data; 757295767dSMatt Evans struct iovec iov; 767295767dSMatt Evans 77*dc4fc6b6SMichael Ellerman if (vcpu->kvm->cfg.active_console != CONSOLE_HV) 782651ea58SSasha Levin return H_SUCCESS; 792651ea58SSasha Levin 802651ea58SSasha Levin if (term_readable(0)) { 817295767dSMatt Evans iov.iov_base = data.buf; 827295767dSMatt Evans iov.iov_len = 16; 837295767dSMatt Evans 84*dc4fc6b6SMichael Ellerman *len = term_getc_iov(vcpu->kvm, &iov, 1, 0); 857295767dSMatt Evans *char0_7 = be64_to_cpu(data.a.char0_7); 867295767dSMatt Evans *char8_15 = be64_to_cpu(data.a.char8_15); 877295767dSMatt Evans } else { 887295767dSMatt Evans *len = 0; 897295767dSMatt Evans } 907295767dSMatt Evans 917295767dSMatt Evans return H_SUCCESS; 927295767dSMatt Evans } 937295767dSMatt Evans 947295767dSMatt Evans void spapr_hvcons_poll(struct kvm *kvm) 957295767dSMatt Evans { 962651ea58SSasha Levin if (term_readable(0)) { 977295767dSMatt Evans /* 987295767dSMatt Evans * We can inject an IRQ to guest here if we want. The guest 997295767dSMatt Evans * will happily poll, though, so not required. 1007295767dSMatt Evans */ 1017295767dSMatt Evans } 1027295767dSMatt Evans } 1037295767dSMatt Evans 1047295767dSMatt Evans void spapr_hvcons_init(void) 1057295767dSMatt Evans { 1067295767dSMatt Evans spapr_register_hypercall(H_PUT_TERM_CHAR, h_put_term_char); 1077295767dSMatt Evans spapr_register_hypercall(H_GET_TERM_CHAR, h_get_term_char); 1087295767dSMatt Evans } 109