From bed57dd242e6e0077db50838b10757c2c57f598c Mon Sep 17 00:00:00 2001 From: Conghui Chen Date: Sat, 20 Apr 2019 06:42:44 +0800 Subject: [PATCH] HV: vuart: enable connect mode for VM Enable connection mode for vuart, so that vuart in different VMs can set up connection. In pre-launched VM's configuration file, ttyS1 is set to be the connection port. To enable it in post-launched VM, just add vuart configuration. Tracked-On: #2987 Signed-off-by: Conghui Chen Acked-by: Eddie Dong --- hypervisor/debug/vuart.c | 71 ++++++++++++++++++++++++++++++++ hypervisor/include/debug/vuart.h | 1 + 2 files changed, 72 insertions(+) diff --git a/hypervisor/debug/vuart.c b/hypervisor/debug/vuart.c index 69f357041..2328fd080 100644 --- a/hypervisor/debug/vuart.c +++ b/hypervisor/debug/vuart.c @@ -168,14 +168,32 @@ static void vuart_toggle_intr(const struct acrn_vuart *vu) vioapic_set_irqline_lock(vu->vm, vu->irq, operation); } +static void vuart_write_to_target(struct acrn_vuart *vu, uint8_t value_u8) +{ + vuart_lock(vu); + if (vu->active) { + fifo_putchar(&vu->rxfifo, (char)value_u8); + vu->thre_int_pending = true; + vuart_toggle_intr(vu); + } + vuart_unlock(vu); +} + 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 = find_vuart_by_port(vm, offset); uint8_t value_u8 = (uint8_t)value; + struct acrn_vuart *target_vu = NULL; offset -= vu->port_base; + target_vu = vu->target_vu; + if ((offset == UART16550_THR) && target_vu) { + vuart_write_to_target(target_vu, value_u8); + return true; + } + vuart_lock(vu); /* * Take care of the special case DLAB accesses first @@ -431,6 +449,7 @@ static void vuart_setup(struct acrn_vm *vm, vu->vm = vm; vuart_fifo_init(vu); vuart_lock_init(vu); + vu->target_vu = NULL; if (vu_config->type == VUART_LEGACY_PIO) { vu->port_base = vu_config->addr.port_base; vu->irq = vu_config->irq; @@ -443,6 +462,49 @@ static void vuart_setup(struct acrn_vm *vm, } } +static struct acrn_vuart *find_active_target_vuart(struct vuart_config *vu_config) +{ + struct acrn_vm *target_vm = NULL; + struct acrn_vuart *target_vu = NULL, *ret_vu = NULL; + uint16_t target_vmid, target_vuid; + + target_vmid = vu_config->t_vuart.vm_id; + target_vuid = vu_config->t_vuart.vuart_id; + if (target_vmid < CONFIG_MAX_VM_NUM) + target_vm = get_vm_from_vmid(target_vmid); + + if (target_vuid < MAX_VUART_NUM_PER_VM) + target_vu = &target_vm->vuart[target_vuid]; + + if (target_vu && target_vu->active) { + ret_vu = target_vu; + } + return ret_vu; +} + +static void vuart_setup_connection(struct acrn_vm *vm, + struct vuart_config *vu_config, uint16_t vuart_idx) +{ + struct acrn_vuart *vu, *t_vu; + + vu = &vm->vuart[vuart_idx]; + if (vu->active) { + t_vu = find_active_target_vuart(vu_config); + if (t_vu && (t_vu->target_vu == NULL)) { + vu->target_vu = t_vu; + t_vu->target_vu = vu; + } + } +} + +void vuart_deinit_connect(struct acrn_vuart *vu) +{ + struct acrn_vuart *t_vu = vu->target_vu; + + t_vu->target_vu = NULL; + vu->target_vu = NULL; +} + bool is_vuart_intx(struct acrn_vm *vm, uint32_t intx_pin) { uint8_t i; @@ -465,6 +527,13 @@ void vuart_init(struct acrn_vm *vm, struct vuart_config *vu_config) vu_config[i].addr.port_base == INVALID_COM_BASE) continue; vuart_setup(vm, &vu_config[i], i); + /* + * The first vuart is used for VM console. + * The rest of vuarts are used for connection. + */ + if (i != 0) { + vuart_setup_connection(vm, &vu_config[i], i); + } } } @@ -478,6 +547,8 @@ void vuart_deinit(struct acrn_vm *vm) for (i = 0; i < MAX_VUART_NUM_PER_VM; i++) { vm->vuart[i].active = false; + if (vm->vuart[i].target_vu) + vuart_deinit_connect(&vm->vuart[i]); } } diff --git a/hypervisor/include/debug/vuart.h b/hypervisor/include/debug/vuart.h index 6add1dbd8..2d5c62a02 100644 --- a/hypervisor/include/debug/vuart.h +++ b/hypervisor/include/debug/vuart.h @@ -76,6 +76,7 @@ struct acrn_vuart { char vuart_tx_buf[TX_BUF_SIZE]; bool thre_int_pending; /* THRE interrupt pending */ bool active; + struct acrn_vuart *target_vu; /* Pointer to target vuart */ struct acrn_vm *vm; spinlock_t lock; /* protects all softc elements */ };