• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2022 - Google LLC
4  */
5 
6 #include <nvhe/pkvm.h>
7 #include <nvhe/spinlock.h>
8 
9 static void (*__hyp_putc)(char c);
10 
__hyp_putx4(unsigned int x)11 static inline void __hyp_putx4(unsigned int x)
12 {
13 	x &= 0xf;
14 	if (x <= 9)
15 		x += '0';
16 	else
17 		x += ('a' - 0xa);
18 
19 	__hyp_putc(x);
20 }
21 
__hyp_putx4n(unsigned long x,int n)22 static inline void __hyp_putx4n(unsigned long x, int n)
23 {
24 	int i = n >> 2;
25 
26 	__hyp_putc('0');
27 	__hyp_putc('x');
28 
29 	while (i--)
30 		__hyp_putx4(x >> (4 * i));
31 
32 	__hyp_putc('\n');
33 	__hyp_putc('\r');
34 }
35 
hyp_serial_enabled(void)36 static inline bool hyp_serial_enabled(void)
37 {
38 	/* Paired with __pkvm_register_serial_driver()'s cmpxchg */
39 	return !!smp_load_acquire(&__hyp_putc);
40 }
41 
hyp_puts(const char * s)42 void hyp_puts(const char *s)
43 {
44 	if (!hyp_serial_enabled())
45 		return;
46 
47 	while (*s)
48 		__hyp_putc(*s++);
49 
50 	__hyp_putc('\n');
51 	__hyp_putc('\r');
52 }
53 
hyp_putx64(u64 x)54 void hyp_putx64(u64 x)
55 {
56 	if (hyp_serial_enabled())
57 		__hyp_putx4n(x, 64);
58 }
59 
hyp_putc(char c)60 void hyp_putc(char c)
61 {
62 	if (hyp_serial_enabled())
63 		__hyp_putc(c);
64 }
65 
__pkvm_register_serial_driver(void (* cb)(char))66 int __pkvm_register_serial_driver(void (*cb)(char))
67 {
68 	/*
69 	 * Paired with smp_load_acquire(&__hyp_putc) in
70 	 * hyp_serial_enabled(). Ensure memory stores hapenning during a pKVM
71 	 * module init are observed before executing the callback.
72 	 */
73 	return cmpxchg_release(&__hyp_putc, NULL, cb) ? -EBUSY : 0;
74 }
75