1 #include <asm/alternative-macros.h> 2 #include <asm/barrier.h> 3 #include <asm/kvm_mmu.h> 4 #include <asm/kvm_pkvm_module.h> 5 #include <asm/io.h> 6 7 static unsigned long uart_addr; 8 __hyp_readw(void * ioaddr)9static inline unsigned int __hyp_readw(void *ioaddr) 10 { 11 unsigned int val; 12 asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (ioaddr)); 13 return val; 14 } __hyp_writew(unsigned int val,void * ioaddr)15static inline void __hyp_writew(unsigned int val, void *ioaddr) 16 { 17 asm volatile("str %w0, [%1]" : : "r" (val), "r" (ioaddr)); 18 } 19 pl011_hyp_putc(char c)20static void pl011_hyp_putc(char c) 21 { 22 void *base = (void *)uart_addr; 23 unsigned int val; 24 25 do { 26 val = __hyp_readw(base + CONFIG_SERIAL_PKVM_PL011_UARTFR); 27 } while (val & (1U <<CONFIG_SERIAL_PKVM_PL011_FULL)); 28 dmb(sy); 29 30 __hyp_writew(c, base + CONFIG_SERIAL_PKVM_PL011_UARTTX); 31 32 do { 33 val = __hyp_readw(base + CONFIG_SERIAL_PKVM_PL011_UARTFR); 34 } while (val & (1U << CONFIG_SERIAL_PKVM_PL011_BUSY)); 35 dmb(sy); 36 } 37 pl011_hyp_init(const struct pkvm_module_ops * ops)38int pl011_hyp_init(const struct pkvm_module_ops *ops) 39 { 40 int ret; 41 42 ret = ops->create_private_mapping(CONFIG_SERIAL_PKVM_PL011_BASE_PHYS, PAGE_SIZE, 43 PAGE_HYP_DEVICE, &uart_addr); 44 if (ret) 45 return ret; 46 47 ret = ops->register_serial_driver(pl011_hyp_putc); 48 if (ret) 49 return ret; 50 51 ops->puts("pKVM pl011 UART driver loaded"); 52 53 return 0; 54 } 55