HV: vuart: enable vuart console for VM

In previous code, only for pre-launched VM, hypervisor would create
vuart console for each VM. But for post-launched VM, no vuart is
created.
In this patch, create vuart according to configuration in structure
acrn_vm_config. As the new configuration is set for pre-launched VM and
post-launched VM, and the vuart initialize process is common for each
VM, so, remove CONFIG_PARTITION_MODE from vuart related code.

Tracked-On: #2987
Signed-off-by: Conghui Chen <conghui.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Conghui Chen 2019-04-20 06:30:15 +08:00 committed by ACRN System Integration
parent 3c92d7bbc7
commit 235d886103
12 changed files with 141 additions and 104 deletions

View File

@ -688,8 +688,8 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_pin, uint32_t vpi
* entry already be held by others, return error.
*/
/* no remap for hypervisor owned intx */
if (is_sos_vm(vm) && hv_used_dbg_intx(virt_sid.intx_id.pin)) {
/* no remap for vuart intx */
if (is_vuart_intx(vm, virt_sid.intx_id.pin)) {
status = -ENODEV;
}

View File

@ -398,20 +398,12 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
if (vm_load_pm_s_state(vm) == 0) {
register_pm1ab_handler(vm);
}
/* Create virtual uart; just when uart enabled, vuart can work */
if (is_dbg_uart_enabled()) {
vuart_init(vm);
}
}
vpic_init(vm);
#ifdef CONFIG_PARTITION_MODE
/* Create virtual uart; just when uart enabled, vuart can work */
if (vm_config->vm_vuart && is_dbg_uart_enabled()) {
vuart_init(vm);
}
#endif
/* Create virtual uart;*/
vuart_init(vm, vm_config->vuart);
vrtc_init(vm);
vpci_init(vm);

View File

@ -842,44 +842,32 @@ static int32_t shell_dumpmem(int32_t argc, char **argv)
return 0;
}
static int32_t shell_to_vm_console(__unused int32_t argc, __unused char **argv)
static int32_t shell_to_vm_console(int32_t argc, char **argv)
{
char temp_str[TEMP_STR_SIZE];
uint16_t vm_id = 0U;
struct acrn_vm *vm;
struct acrn_vuart *vu;
#ifdef CONFIG_PARTITION_MODE
struct acrn_vm_config *vm_config;
if (argc == 2U) {
vm_id = sanitize_vmid(strtol_deci(argv[1]));
}
vuart_vmid = vm_id;
#endif
/* Get the virtual device node */
vm = get_vm_from_vmid(vm_id);
if (!is_valid_vm(vm)) {
shell_puts("VM is not valid \n");
return -EINVAL;
}
#ifdef CONFIG_PARTITION_MODE
vm_config = get_vm_config(vm_id);
if (!vm_config->vm_vuart) {
snprintf(temp_str, TEMP_STR_SIZE, "No vUART configured for vm%d\n", vm_id);
shell_puts(temp_str);
vu = vm_console_vuart(vm);
if (!vu->active) {
shell_puts("vuart console is not active \n");
return 0;
}
#endif
vu = vm_vuart(vm);
/* UART is now owned by the SOS.
* Indicate by toggling the flag.
*/
vu->active = true;
console_vmid = vm_id;
/* Output that switching to SOS shell */
snprintf(temp_str, TEMP_STR_SIZE, "\r\n----- Entering Guest %d Shell -----\r\n", vm_id);
snprintf(temp_str, TEMP_STR_SIZE, "\r\n----- Entering VM %d Shell -----\r\n", vm_id);
shell_puts(temp_str);

View File

@ -12,6 +12,8 @@
#define SHELL_CMD_MAX_LEN 100U
#define SHELL_STRING_MAX_LEN (PAGE_SIZE << 2U)
extern int16_t console_vmid;
/* Shell Command Function */
typedef int32_t (*shell_cmd_fn_t)(int32_t argc, char **argv);

View File

@ -39,18 +39,11 @@
static uint32_t vuart_com_irq = CONFIG_COM_IRQ;
static uint16_t vuart_com_base = CONFIG_COM_BASE;
#ifndef CONFIG_PARTITION_MODE
static char vuart_rx_buf[RX_BUF_SIZE];
static char vuart_tx_buf[TX_BUF_SIZE];
#endif
#define vuart_lock_init(vu) spinlock_init(&((vu)->lock))
#define vuart_lock(vu) spinlock_obtain(&((vu)->lock))
#define vuart_unlock(vu) spinlock_release(&((vu)->lock))
#ifdef CONFIG_PARTITION_MODE
uint16_t vuart_vmid = 0xFFFFU;
#endif
uint16_t console_vmid = ACRN_INVALID_VMID;
static inline void fifo_reset(struct fifo *fifo)
{
@ -92,13 +85,8 @@ static inline uint32_t fifo_numchars(const struct fifo *fifo)
static inline void vuart_fifo_init(struct acrn_vuart *vu)
{
#ifdef CONFIG_PARTITION_MODE
vu->txfifo.buf = vu->vuart_tx_buf;
vu->rxfifo.buf = vu->vuart_rx_buf;
#else
vu->txfifo.buf = vuart_tx_buf;
vu->rxfifo.buf = vuart_rx_buf;
#endif
vu->txfifo.size = TX_BUF_SIZE;
vu->rxfifo.size = RX_BUF_SIZE;
fifo_reset(&(vu->txfifo));
@ -125,9 +113,28 @@ static uint8_t vuart_intr_reason(const struct acrn_vuart *vu)
}
}
struct acrn_vuart *vm_vuart(struct acrn_vm *vm)
struct acrn_vuart *find_vuart_by_port(struct acrn_vm *vm, uint16_t offset)
{
return &(vm->vuart);
uint8_t i;
struct acrn_vuart *vu, *ret_vu = NULL;
/* TODO: support pci vuart find */
for (i = 0; i < MAX_VUART_NUM_PER_VM; i++) {
vu = &vm->vuart[i];
if (vu->active == true && vu->port_base == (offset & ~0x7U)) {
ret_vu = vu;
break;
}
}
return ret_vu;
}
/*
* @post return != NULL
*/
struct acrn_vuart *vm_console_vuart(struct acrn_vm *vm)
{
return &vm->vuart[0];
}
/*
@ -141,7 +148,7 @@ static void vuart_toggle_intr(const struct acrn_vuart *vu)
uint32_t operation;
intr_reason = vuart_intr_reason(vu);
vioapic_get_rte(vu->vm, vuart_com_irq, &rte);
vioapic_get_rte(vu->vm, vu->irq, &rte);
/* TODO:
* Here should assert vuart irq according to CONFIG_COM_IRQ polarity.
@ -157,18 +164,18 @@ static void vuart_toggle_intr(const struct acrn_vuart *vu)
operation = (intr_reason != IIR_NOPEND) ? GSI_SET_HIGH : GSI_SET_LOW;
}
vpic_set_irqline(vu->vm, vuart_com_irq, operation);
vioapic_set_irqline_lock(vu->vm, vuart_com_irq, operation);
vpic_set_irqline(vu->vm, vu->irq, operation);
vioapic_set_irqline_lock(vu->vm, vu->irq, operation);
}
static bool vuart_write(struct acrn_vm *vm, uint16_t offset_arg,
__unused size_t width, uint32_t value)
{
uint16_t offset = offset_arg;
struct acrn_vuart *vu = vm_vuart(vm);
struct acrn_vuart *vu = find_vuart_by_port(vm, offset);
uint8_t value_u8 = (uint8_t)value;
offset -= vu->base;
offset -= vu->port_base;
vuart_lock(vu);
/*
* Take care of the special case DLAB accesses first
@ -253,10 +260,10 @@ static bool vuart_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t offs
{
uint16_t offset = offset_arg;
uint8_t iir, reg, intr_reason;
struct acrn_vuart *vu = vm_vuart(vm);
struct acrn_vuart *vu = find_vuart_by_port(vm, offset);
struct pio_request *pio_req = &vcpu->req.reqs.pio;
offset -= vu->base;
offset -= vu->port_base;
vuart_lock(vu);
/*
* Take care of the special case DLAB accesses first
@ -330,15 +337,33 @@ done:
return true;
}
static void vuart_register_io_handler(struct acrn_vm *vm)
/*
* @pre: vuart_idx = 0 or 1
*/
static bool vuart_register_io_handler(struct acrn_vm *vm, uint16_t port_base, uint32_t vuart_idx)
{
uint32_t pio_idx;
bool ret = true;
struct vm_io_range range = {
.flags = IO_ATTR_RW,
.base = vuart_com_base,
.base = port_base,
.len = 8U
};
register_pio_emulation_handler(vm, UART_PIO_IDX, &range, vuart_read, vuart_write);
switch (vuart_idx) {
case 0:
pio_idx = UART_PIO_IDX0;
break;
case 1:
pio_idx = UART_PIO_IDX1;
break;
default:
printf("Not support vuart index %d, will not register \n");
ret = false;
}
if (ret)
register_pio_emulation_handler(vm, pio_idx, &range, vuart_read, vuart_write);
return ret;
}
/**
@ -367,7 +392,7 @@ void vuart_console_rx_chars(struct acrn_vuart *vu)
if (ch == GUEST_CONSOLE_TO_HV_SWITCH_KEY) {
/* Switch the console */
vu->active = false;
console_vmid = ACRN_INVALID_VMID;
printf("\r\n\r\n ---Entering ACRN SHELL---\r\n");
}
if (ch != -1) {
@ -381,46 +406,79 @@ void vuart_console_rx_chars(struct acrn_vuart *vu)
struct acrn_vuart *vuart_console_active(void)
{
struct acrn_vm *vm = NULL;
struct acrn_vuart *vu = NULL;
#ifdef CONFIG_PARTITION_MODE
if (vuart_vmid < CONFIG_MAX_VM_NUM) {
vm = get_vm_from_vmid(vuart_vmid);
if (console_vmid < CONFIG_MAX_VM_NUM) {
vm = get_vm_from_vmid(console_vmid);
}
#else
vm = get_sos_vm();
#endif
if (is_valid_vm(vm)) {
struct acrn_vuart *vu = vm_vuart(vm);
if (vu->active) {
return vu;
}
vu = vm_console_vuart(vm);
}
return NULL;
return (vu && vu->active) ? vu : NULL;
}
void vuart_init(struct acrn_vm *vm)
static void vuart_setup(struct acrn_vm *vm,
struct vuart_config *vu_config, uint16_t vuart_idx)
{
uint32_t divisor;
struct acrn_vuart *vu = vm_vuart(vm);
struct acrn_vuart *vu = &vm->vuart[vuart_idx];
/* Set baud rate*/
divisor = (UART_CLOCK_RATE / BAUD_9600) >> 4U;
vm->vuart.dll = (uint8_t)divisor;
vm->vuart.dlh = (uint8_t)(divisor >> 8U);
vm->vuart.active = false;
vm->vuart.base = vuart_com_base;
vm->vuart.vm = vm;
divisor = (UART_CLOCK_RATE / BAUD_115200) >> 4U;
vu->dll = (uint8_t)divisor;
vu->dlh = (uint8_t)(divisor >> 8U);
vu->vm = vm;
vuart_fifo_init(vu);
vuart_lock_init(vu);
vuart_register_io_handler(vm);
if (vu_config->type == VUART_LEGACY_PIO) {
vu->port_base = vu_config->addr.port_base;
vu->irq = vu_config->irq;
if (vuart_register_io_handler(vm, vu->port_base, vuart_idx)) {
vu->active = true;
}
} else {
/*TODO: add pci vuart support here*/
printf("PCI vuart is not support\n");
}
}
bool hv_used_dbg_intx(uint32_t intx_pin)
bool is_vuart_intx(struct acrn_vm *vm, uint32_t intx_pin)
{
return is_dbg_uart_enabled() && (intx_pin == vuart_com_irq);
uint8_t i;
bool ret = false;
for (i = 0; i < MAX_VUART_NUM_PER_VM; i++)
if (vm->vuart[i].active && vm->vuart[i].irq == intx_pin)
ret = true;
return ret;
}
void vuart_init(struct acrn_vm *vm, struct vuart_config *vu_config)
{
uint8_t i;
for (i = 0; i < MAX_VUART_NUM_PER_VM; i++) {
vm->vuart[i].active = false;
/* This vuart is not exist */
if (vu_config[i].type == VUART_LEGACY_PIO &&
vu_config[i].addr.port_base == INVALID_COM_BASE)
continue;
vuart_setup(vm, &vu_config[i], i);
}
}
void vuart_deinit(struct acrn_vm *vm)
{
uint8_t i;
/* reset console_vmid to switch back to hypervisor console */
if (console_vmid == vm->vm_id)
console_vmid = ACRN_INVALID_VMID;
for (i = 0; i < MAX_VUART_NUM_PER_VM; i++) {
vm->vuart[i].active = false;
}
}
/* vuart=ttySx@irqN, like vuart=ttyS1@irq6 head "vuart=ttyS" is parsed */

View File

@ -120,7 +120,7 @@ struct acrn_vm {
struct e820_entry *e820_entries;
uint16_t vm_id; /* Virtual machine identifier */
enum vm_state state; /* VM state */
struct acrn_vuart vuart; /* Virtual UART */
struct acrn_vuart vuart[MAX_VUART_NUM_PER_VM]; /* Virtual UART */
enum vpic_wire_mode wire_mode;
struct iommu_domain *iommu; /* iommu domain of this VM */
spinlock_t spinlock; /* Spin-lock used to protect VM modifications */

View File

@ -15,8 +15,10 @@
#define PIC_ELC_PIO_IDX (PIC_SLAVE_PIO_IDX + 1U)
#define PCI_CFGADDR_PIO_IDX (PIC_ELC_PIO_IDX + 1U)
#define PCI_CFGDATA_PIO_IDX (PCI_CFGADDR_PIO_IDX + 1U)
#define UART_PIO_IDX (PCI_CFGDATA_PIO_IDX + 1U)
#define PM1A_EVT_PIO_IDX (UART_PIO_IDX + 1U)
/* When MAX_VUART_NUM_PER_VM is larger than 2, UART_PIO_IDXn should also be added here */
#define UART_PIO_IDX0 (PCI_CFGDATA_PIO_IDX + 1U)
#define UART_PIO_IDX1 (UART_PIO_IDX0 + 1U)
#define PM1A_EVT_PIO_IDX (UART_PIO_IDX1 + 1U)
#define PM1A_CNT_PIO_IDX (PM1A_EVT_PIO_IDX + 1U)
#define PM1B_EVT_PIO_IDX (PM1A_CNT_PIO_IDX + 1U)
#define PM1B_CNT_PIO_IDX (PM1B_EVT_PIO_IDX + 1U)

View File

@ -88,7 +88,6 @@ struct acrn_vm_config {
struct acrn_vm_os_config os_config; /* OS information the VM */
uint16_t clos; /* if guest_flags has GUEST_FLAG_CLOS_REQUIRED, then VM use this CLOS */
bool vm_vuart;
struct vuart_config vuart[MAX_VUART_NUM_PER_VM];/* vuart configuration for VM */
struct mptable_info *mptable; /* Pointer to mptable struct if VM type is pre-launched */
} __aligned(8);

View File

@ -31,9 +31,11 @@
#define VUART_H
#include <types.h>
#include <spinlock.h>
#include <vm_config.h>
#define RX_BUF_SIZE 256U
#define TX_BUF_SIZE 8192U
#define INVAILD_VUART_IDX 0xFFU
#define COM1_BASE 0x3F8U
#define COM2_BASE 0x2F8U
@ -68,27 +70,23 @@ struct acrn_vuart {
struct fifo rxfifo;
struct fifo txfifo;
uint16_t base;
#ifdef CONFIG_PARTITION_MODE
uint16_t port_base;
uint32_t irq;
char vuart_rx_buf[RX_BUF_SIZE];
char vuart_tx_buf[TX_BUF_SIZE];
#endif
bool thre_int_pending; /* THRE interrupt pending */
bool active;
struct acrn_vm *vm;
spinlock_t lock; /* protects all softc elements */
};
#ifdef CONFIG_PARTITION_MODE
extern uint16_t vuart_vmid;
#endif /* CONFIG_PARTITION_MODE */
struct acrn_vuart *vm_vuart(struct acrn_vm *vm);
void vuart_init(struct acrn_vm *vm);
struct acrn_vuart *vm_console_vuart(struct acrn_vm *vm);
void vuart_init(struct acrn_vm *vm, struct vuart_config *vu_config);
void vuart_deinit(struct acrn_vm *vm);
struct acrn_vuart *vuart_console_active(void);
void vuart_console_tx_chars(struct acrn_vuart *vu);
void vuart_console_rx_chars(struct acrn_vuart *vu);
bool hv_used_dbg_intx(uint32_t intx_pin);
bool is_vuart_intx(struct acrn_vm *vm, uint32_t intx_pin);
void vuart_set_property(const char *vuart_info);
#endif /* VUART_H */

View File

@ -7,8 +7,8 @@
#include <types.h>
#include <vm.h>
void vuart_init(__unused struct acrn_vm *vm) {}
void vuart_init(__unused struct acrn_vm *vm, __unused struct vuart_config *vu_config) {}
void vuart_deinit(__unused struct acrn_vm *vm) {}
struct acrn_vuart *vuart_console_active(void)
{
return NULL;
@ -17,7 +17,7 @@ struct acrn_vuart *vuart_console_active(void)
void vuart_console_tx_chars(__unused struct acrn_vuart *vu) {}
void vuart_console_rx_chars(__unused struct acrn_vuart *vu) {}
bool hv_used_dbg_intx(__unused uint32_t intx_pin)
bool is_vuart_intx(__unused struct acrn_vm *vm, __unused uint32_t intx_pin)
{
return false;
}

View File

@ -37,7 +37,6 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
no_timer_check ignore_loglevel log_buf_len=16M \
consoleblank=0 tsc=reliable xapic_phys"
},
.vm_vuart = true,
.vuart[0] = {
.type = VUART_LEGACY_PIO,
.addr.port_base = COM1_BASE,
@ -77,7 +76,6 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
no_timer_check ignore_loglevel log_buf_len=16M \
consoleblank=0 tsc=reliable xapic_phys"
},
.vm_vuart = true,
.vuart[0] = {
.type = VUART_LEGACY_PIO,
.addr.port_base = COM1_BASE,

View File

@ -28,7 +28,7 @@
#define VM0_CONFIG_MEM_SIZE 0x20000000UL
#define VM0_CONFIG_OS_BOOTARG_ROOT "root=/dev/sda3 "
#define VM0_CONFIG_OS_BOOTARG_MAXCPUS "maxcpus=2 "
#define VM0_CONFIG_OS_BOOTARG_CONSOLE "console=ttyS2 "
#define VM0_CONFIG_OS_BOOTARG_CONSOLE "console=ttyS0 "
#define VM0_CONFIG_PCI_PTDEV_NUM 3U
#define VM1_CONFIG_PCPU_BITMAP (PLUG_CPU(1) | PLUG_CPU(3))
@ -37,7 +37,7 @@
#define VM1_CONFIG_MEM_SIZE 0x20000000UL
#define VM1_CONFIG_OS_BOOTARG_ROOT "root=/dev/sda3 "
#define VM1_CONFIG_OS_BOOTARG_MAXCPUS "maxcpus=2 "
#define VM1_CONFIG_OS_BOOTARG_CONSOLE "console=ttyS2 "
#define VM1_CONFIG_OS_BOOTARG_CONSOLE "console=ttyS0 "
#define VM1_CONFIG_PCI_PTDEV_NUM 3U
#endif /* VM_CONFIGURATIONS_H */