xref: /kvm-unit-tests/lib/powerpc/io.c (revision 610c5a9c11fc1e8fe936925b8a4975015ffe4b5e)
11e95c7ccSAndrew Jones /*
21e95c7ccSAndrew Jones  * Each architecture must implement puts() and exit().
31e95c7ccSAndrew Jones  *
41e95c7ccSAndrew Jones  * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
51e95c7ccSAndrew Jones  *
61e95c7ccSAndrew Jones  * This work is licensed under the terms of the GNU LGPL, version 2.
71e95c7ccSAndrew Jones  */
81e95c7ccSAndrew Jones #include <libcflat.h>
9e65bcc62SAndrew Jones #include <asm/spinlock.h>
102f9ce69eSAndrew Jones #include <asm/rtas.h>
114ff26ec5SThomas Huth #include <asm/setup.h>
12*610c5a9cSNicholas Piggin #include <asm/processor.h>
134ff26ec5SThomas Huth #include "io.h"
14e65bcc62SAndrew Jones 
15e65bcc62SAndrew Jones static struct spinlock print_lock;
161e95c7ccSAndrew Jones 
17*610c5a9cSNicholas Piggin void putchar(int c)
18*610c5a9cSNicholas Piggin {
19*610c5a9cSNicholas Piggin 	if (machine_is_powernv())
20*610c5a9cSNicholas Piggin 		opal_putchar(c);
21*610c5a9cSNicholas Piggin 	else
22*610c5a9cSNicholas Piggin 		papr_putchar(c);
23*610c5a9cSNicholas Piggin }
24*610c5a9cSNicholas Piggin 
25*610c5a9cSNicholas Piggin int __getchar(void)
26*610c5a9cSNicholas Piggin {
27*610c5a9cSNicholas Piggin 	if (machine_is_powernv())
28*610c5a9cSNicholas Piggin 		return __opal_getchar();
29*610c5a9cSNicholas Piggin 	else
30*610c5a9cSNicholas Piggin 		return __papr_getchar();
31*610c5a9cSNicholas Piggin }
32*610c5a9cSNicholas Piggin 
331e95c7ccSAndrew Jones void io_init(void)
341e95c7ccSAndrew Jones {
35*610c5a9cSNicholas Piggin 	if (machine_is_powernv())
36*610c5a9cSNicholas Piggin 		assert(!opal_init());
37*610c5a9cSNicholas Piggin 	else
382f9ce69eSAndrew Jones 		rtas_init();
391e95c7ccSAndrew Jones }
401e95c7ccSAndrew Jones 
41e65bcc62SAndrew Jones void puts(const char *s)
421e95c7ccSAndrew Jones {
43e65bcc62SAndrew Jones 	spin_lock(&print_lock);
44e65bcc62SAndrew Jones 	while (*s)
45e65bcc62SAndrew Jones 		putchar(*s++);
46e65bcc62SAndrew Jones 	spin_unlock(&print_lock);
471e95c7ccSAndrew Jones }
481e95c7ccSAndrew Jones 
49764aa0b8SAndrew Jones /*
50764aa0b8SAndrew Jones  * Defining halt to take 'code' as an argument guarantees that it will
51764aa0b8SAndrew Jones  * be in r3 when we halt. That gives us a final chance to see the exit
52764aa0b8SAndrew Jones  * status while inspecting the halted unit test state.
53764aa0b8SAndrew Jones  */
54764aa0b8SAndrew Jones extern void halt(int code);
55764aa0b8SAndrew Jones 
56e65bcc62SAndrew Jones void exit(int code)
571e95c7ccSAndrew Jones {
58f5a87330SAndrew Jones // FIXME: change this print-exit/rtas-poweroff to chr_testdev_exit(),
59f5a87330SAndrew Jones //        maybe by plugging chr-testdev into a spapr-vty.
60f5a87330SAndrew Jones 	printf("\nEXIT: STATUS=%d\n", ((code) << 1) | 1);
61*610c5a9cSNicholas Piggin 	if (machine_is_powernv())
62*610c5a9cSNicholas Piggin 		opal_power_off();
63*610c5a9cSNicholas Piggin 	else
64f5a87330SAndrew Jones 		rtas_power_off();
65e65bcc62SAndrew Jones 	halt(code);
6696d79976SAndre Przywara 	__builtin_unreachable();
671e95c7ccSAndrew Jones }
68