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)11static 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)22static 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)36static 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)42void 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)54void hyp_putx64(u64 x) 55 { 56 if (hyp_serial_enabled()) 57 __hyp_putx4n(x, 64); 58 } 59 hyp_putc(char c)60void hyp_putc(char c) 61 { 62 if (hyp_serial_enabled()) 63 __hyp_putc(c); 64 } 65 __pkvm_register_serial_driver(void (* cb)(char))66int __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