/* * Hypercall helpers * * broken_sc1 probing/patching inspired by SLOF, see * SLOF:lib/libhvcall/brokensc1.c * * Copyright (C) 2016, Red Hat Inc, Andrew Jones * * This work is licensed under the terms of the GNU LGPL, version 2. */ #include #include #include "io.h" int hcall_have_broken_sc1(void) { register unsigned long r3 asm("r3") = H_SET_DABR; register unsigned long r4 asm("r4") = 0; asm volatile("sc 1" : "=r" (r3) : "r" (r3), "r" (r4) : "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"); return r3 == (unsigned long)H_PRIVILEGE; } void papr_putchar(int c) { unsigned long vty = 0; /* 0 == default */ unsigned long nr_chars = 1; unsigned long chars = (unsigned long)c << 56; hcall(H_PUT_TERM_CHAR, vty, nr_chars, chars); } int __papr_getchar(void) { register unsigned long r3 asm("r3") = H_GET_TERM_CHAR; register unsigned long r4 asm("r4") = 0; /* 0 == default vty */ register unsigned long r5 asm("r5"); asm volatile (" sc 1 " : "+r"(r3), "+r"(r4), "=r"(r5) : "r"(r3), "r"(r4)); return r3 == H_SUCCESS && r4 > 0 ? r5 >> 56 : -1; }