1 /* 2 * Each architecture must implement puts() and exit(). 3 * 4 * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com> 5 * 6 * This work is licensed under the terms of the GNU LGPL, version 2. 7 */ 8 #include <libcflat.h> 9 #include <asm/spinlock.h> 10 #include <asm/rtas.h> 11 #include <asm/setup.h> 12 #include <asm/processor.h> 13 #include <asm/atomic.h> 14 #include <asm/smp.h> 15 #include "io.h" 16 17 static struct spinlock print_lock; 18 putchar(int c)19void putchar(int c) 20 { 21 if (machine_is_powernv()) 22 opal_putchar(c); 23 else 24 papr_putchar(c); 25 } 26 __getchar(void)27int __getchar(void) 28 { 29 if (machine_is_powernv()) 30 return __opal_getchar(); 31 else 32 return __papr_getchar(); 33 } 34 io_init(void)35void io_init(void) 36 { 37 if (machine_is_powernv()) 38 assert(!opal_init()); 39 else 40 rtas_init(); 41 } 42 puts(const char * s)43void puts(const char *s) 44 { 45 bool user = in_usermode(); 46 47 if (user) 48 exit_usermode(); 49 spin_lock(&print_lock); 50 while (*s) 51 putchar(*s++); 52 spin_unlock(&print_lock); 53 if (user) 54 enter_usermode(); 55 } 56 57 /* 58 * Defining halt to take 'code' as an argument guarantees that it will 59 * be in r3 when we halt. That gives us a final chance to see the exit 60 * status while inspecting the halted unit test state. 61 */ 62 extern void halt(int code); 63 exit(int code)64void exit(int code) 65 { 66 static int exited = 0; 67 68 // FIXME: change this print-exit/rtas-poweroff to chr_testdev_exit(), 69 // maybe by plugging chr-testdev into a spapr-vty. 70 if (atomic_fetch_inc(&exited) == 0) { 71 printf("\nEXIT: STATUS=%d\n", ((code) << 1) | 1); 72 if (machine_is_powernv()) 73 opal_power_off(); 74 else 75 rtas_power_off(); 76 } 77 halt(code); 78 __builtin_unreachable(); 79 } 80