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 <conghui.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Conghui Chen 2019-04-20 06:42:44 +08:00 committed by ACRN System Integration
parent 235d886103
commit bed57dd242
2 changed files with 72 additions and 0 deletions

View File

@ -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]);
}
}

View File

@ -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 */
};