ANDROID: KVM: arm64: Add serial framework for pKVM

Debugging a hypervisor tends to be trickier than normal system code
such as the kernel. The lack of availability of a UART framework is a
significant contributor to that. In order to address this, introduce a
framework allowing to load serial drivers into the hypervisor.

Bug: 244543039
Bug: 244373730
Change-Id: I2e7a1fd9abc9d5aa9d95f1d271a997d54a8fd582
Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
Quentin Perret
2022-09-19 13:35:54 +00:00
parent c3db83c87f
commit b21ae4963d
6 changed files with 85 additions and 1 deletions

View File

@@ -10,6 +10,7 @@ struct pkvm_module_ops {
int (*create_private_mapping)(phys_addr_t phys, size_t size,
enum kvm_pgtable_prot prot,
unsigned long *haddr);
int (*register_serial_driver)(void (*hyp_putc_cb)(char));
};
struct pkvm_module_section {

View File

@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __ARM64_KVM_NVHE_SERIAL_H__
#define __ARM64_KVM_NVHE_SERIAL_H__
void hyp_puts(const char *s);
void hyp_putx64(u64 x);
void hyp_putc(char c);
int __pkvm_register_serial_driver(void (*driver_cb)(char));
#endif

View File

@@ -5,7 +5,8 @@ lib-objs := $(addprefix ../../../lib/, $(lib-objs))
hyp-obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o host.o \
hyp-main.o hyp-smp.o psci-relay.o early_alloc.o page_alloc.o \
cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o ffa.o iommu.o
cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o ffa.o iommu.o \
serial.o
hyp-obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \
../fpsimd.o ../hyp-entry.o ../exception.o ../pgtable.o
hyp-obj-$(CONFIG_DEBUG_LIST) += list_debug.o

View File

@@ -7,9 +7,11 @@
#include <nvhe/modules.h>
#include <nvhe/mm.h>
#include <nvhe/serial.h>
const struct pkvm_module_ops module_ops = {
.create_private_mapping = __pkvm_create_private_mapping,
.register_serial_driver = __pkvm_register_serial_driver,
};
int __pkvm_init_module(void *module_init)

View File

@@ -0,0 +1,68 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2022 - Google LLC
*/
#include <nvhe/pkvm.h>
#include <nvhe/spinlock.h>
static void (*__hyp_putc)(char c);
static inline void __hyp_putx4(unsigned int x)
{
x &= 0xf;
if (x <= 9)
x += '0';
else
x += ('a' - 0xa);
__hyp_putc(x);
}
static inline void __hyp_putx4n(unsigned long x, int n)
{
int i = n >> 2;
__hyp_putc('0');
__hyp_putc('x');
while (i--)
__hyp_putx4(x >> (4 * i));
__hyp_putc('\n');
__hyp_putc('\r');
}
static inline bool hyp_serial_enabled(void)
{
return !!READ_ONCE(__hyp_putc);
}
void hyp_puts(const char *s)
{
if (!hyp_serial_enabled())
return;
while (*s)
__hyp_putc(*s++);
__hyp_putc('\n');
__hyp_putc('\r');
}
void hyp_putx64(u64 x)
{
if (hyp_serial_enabled())
__hyp_putx4n(x, 64);
}
void hyp_putc(char c)
{
if (hyp_serial_enabled())
__hyp_putc(c);
}
int __pkvm_register_serial_driver(void (*cb)(char))
{
return cmpxchg(&__hyp_putc, NULL, cb) ? -EBUSY : 0;
}

View File

@@ -18,6 +18,7 @@
#include <nvhe/mem_protect.h>
#include <nvhe/mm.h>
#include <nvhe/pkvm.h>
#include <nvhe/serial.h>
#include <nvhe/trap_handler.h>
unsigned long hyp_nr_cpus;