1 /* 2 * Hypercall helpers 3 * 4 * broken_sc1 probing/patching inspired by SLOF, see 5 * SLOF:lib/libhvcall/brokensc1.c 6 * 7 * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU LGPL, version 2. 10 */ 11 #include <asm/hcall.h> 12 #include <libcflat.h> 13 #include "io.h" 14 15 int hcall_have_broken_sc1(void) 16 { 17 register unsigned long r3 asm("r3") = H_SET_DABR; 18 register unsigned long r4 asm("r4") = 0; 19 20 asm volatile("sc 1" 21 : "=r" (r3) 22 : "r" (r3), "r" (r4) 23 : "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"); 24 25 return r3 == (unsigned long)H_PRIVILEGE; 26 } 27 28 void putchar(int c) 29 { 30 unsigned long vty = 0; /* 0 == default */ 31 unsigned long nr_chars = 1; 32 unsigned long chars = (unsigned long)c << 56; 33 34 hcall(H_PUT_TERM_CHAR, vty, nr_chars, chars); 35 } 36 37 int __getchar(void) 38 { 39 register unsigned long r3 asm("r3") = H_GET_TERM_CHAR; 40 register unsigned long r4 asm("r4") = 0; /* 0 == default vty */ 41 register unsigned long r5 asm("r5"); 42 43 asm volatile (" sc 1 " : "+r"(r3), "+r"(r4), "=r"(r5) 44 : "r"(r3), "r"(r4)); 45 46 return r3 == H_SUCCESS && r4 > 0 ? r5 >> 48 : -1; 47 } 48