diff --git a/hypervisor/debug/console.c b/hypervisor/debug/console.c index 65aa2b20e..f944f46ef 100644 --- a/hypervisor/debug/console.c +++ b/hypervisor/debug/console.c @@ -22,7 +22,8 @@ struct hv_timer console_timer; #define CONSOLE_KICK_TIMER_TIMEOUT 40UL /* timeout is 40ms*/ /* Switching key combinations for shell and uart console */ -#define GUEST_CONSOLE_TO_HV_SWITCH_KEY 0 /* CTRL + SPACE */ +#define GUEST_CONSOLE_ESCAPE_KEY 0x0 /* the "break", put twice to send "break" to guest */ +#define GUEST_CONSOLE_TO_HV_SWITCH_KEY 'e' /* escape + e to switch back to hv console */ uint16_t console_vmid = CONFIG_CONSOLE_DEFAULT_VM; /* if use INIT to kick pcpu only, if not notification IPI still is used for sharing CPU */ @@ -112,16 +113,35 @@ static void vuart_console_rx_chars(struct acrn_vuart *vu) if (ch == -1) break; - if (ch == GUEST_CONSOLE_TO_HV_SWITCH_KEY) { - /* Switch the console */ - console_vmid = ACRN_INVALID_VMID; - printf("\r\n\r\n ---Entering ACRN SHELL---\r\n"); - break; + if (vu->escaping) { + vu->escaping = false; + switch (ch) { + case GUEST_CONSOLE_ESCAPE_KEY: + vuart_putchar(vu, ch); + vu->lsr |= LSR_BI; + recv = true; + break; + case GUEST_CONSOLE_TO_HV_SWITCH_KEY: + /* Switch the console */ + console_vmid = ACRN_INVALID_VMID; + printf("\r\n\r\n ---Entering ACRN SHELL---\r\n"); + /* following inputs are for hv, don't handle in this loop */ + goto exit; + default: + printf("Unknown escaping key: '%c'\r\n", ch); + break; + } + } else { + if (ch == GUEST_CONSOLE_ESCAPE_KEY) { + vu->escaping = true; + } else { + vuart_putchar(vu, ch); + recv = true; + } } - - vuart_putchar(vu, ch); - recv = true; } + +exit: if (recv) { vuart_toggle_intr(vu); } diff --git a/hypervisor/dm/vuart.c b/hypervisor/dm/vuart.c index c266f4850..8e4ebf06c 100644 --- a/hypervisor/dm/vuart.c +++ b/hypervisor/dm/vuart.c @@ -135,7 +135,7 @@ static uint8_t vuart_intr_reason(const struct acrn_vuart *vu) { uint8_t ret; - if (((vu->lsr & LSR_OE) != 0U) && ((vu->ier & IER_ELSI) != 0U)) { + if (((vu->lsr & (LSR_OE | LSR_BI)) != 0U) && ((vu->ier & IER_ELSI) != 0U)) { ret = IIR_RLS; } else if ((fifo_numchars(&vu->rxfifo) > 0U) && ((vu->ier & IER_ERBFI) != 0U)) { ret = IIR_RXTOUT; @@ -499,7 +499,7 @@ uint8_t vuart_read_reg(struct acrn_vuart *vu, uint16_t offset) } reg = vu->lsr; /* The LSR_OE bit is cleared on LSR read */ - vu->lsr &= ~LSR_OE; + vu->lsr &= ~(LSR_OE | LSR_BI); break; case UART16550_MSR: /* @@ -655,6 +655,7 @@ void init_legacy_vuarts(struct acrn_vm *vm, const struct vuart_config *vu_config vu->irq = vu_config[i].irq; if (vuart_register_io_handler(vm, vu->port_base, i) != 0U) { vu->active = true; + vu->escaping = false; } /* * The first vuart is used for VM console. @@ -674,6 +675,7 @@ void deinit_legacy_vuarts(struct acrn_vm *vm) for (i = 0U; i < MAX_VUART_NUM_PER_VM; i++) { if (vm->vuart[i].port_base != INVALID_COM_BASE) { vm->vuart[i].active = false; + vm->vuart[i].escaping = false; if (vm->vuart[i].target_vu != NULL) { vuart_deinit_connection(&vm->vuart[i]); } @@ -696,6 +698,7 @@ void init_pci_vuart(struct pci_vdev *vdev) vm_cfg->vuart[idx].t_vuart.vuart_id = pci_cfg->t_vuart.vuart_id; vu->active = true; + vu->escaping = false; if (pci_cfg->vuart_idx != 0U) { vuart_setup_connection(vm, &vm_cfg->vuart[idx], idx); } @@ -707,6 +710,7 @@ void deinit_pci_vuart(struct pci_vdev *vdev) struct acrn_vuart *vu = vdev->priv_data; vu->active = false; + vu->escaping = false; if (vu->target_vu != NULL) { vuart_deinit_connection(vu); } diff --git a/hypervisor/include/dm/vuart.h b/hypervisor/include/dm/vuart.h index ea3828556..49d9f85f7 100644 --- a/hypervisor/include/dm/vuart.h +++ b/hypervisor/include/dm/vuart.h @@ -75,6 +75,7 @@ struct acrn_vuart { char vuart_tx_buf[TX_BUF_SIZE]; bool thre_int_pending; /* THRE interrupt pending */ bool active; + bool escaping; /* in escaping sequence, for console vuarts */ struct acrn_vuart *target_vu; /* Pointer to target vuart */ struct acrn_vm *vm; struct pci_vdev *vdev; /* pci vuart */