diff --git a/hypervisor/arch/x86/guest/assign.c b/hypervisor/arch/x86/guest/assign.c index c34ebf72b..f0139f19b 100644 --- a/hypervisor/arch/x86/guest/assign.c +++ b/hypervisor/arch/x86/guest/assign.c @@ -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; } diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 121327f26..631f4c8fd 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -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); diff --git a/hypervisor/debug/shell.c b/hypervisor/debug/shell.c index e73f39fa6..6954aaf41 100644 --- a/hypervisor/debug/shell.c +++ b/hypervisor/debug/shell.c @@ -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); diff --git a/hypervisor/debug/shell_priv.h b/hypervisor/debug/shell_priv.h index 002b5a68a..d4f31ab0e 100644 --- a/hypervisor/debug/shell_priv.h +++ b/hypervisor/debug/shell_priv.h @@ -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); diff --git a/hypervisor/debug/vuart.c b/hypervisor/debug/vuart.c index 948f23773..69f357041 100644 --- a/hypervisor/debug/vuart.c +++ b/hypervisor/debug/vuart.c @@ -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 */ diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index 20b6687b8..901b1fa2b 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -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 */ diff --git a/hypervisor/include/arch/x86/guest/vmx_io.h b/hypervisor/include/arch/x86/guest/vmx_io.h index 8205a4365..60679e913 100644 --- a/hypervisor/include/arch/x86/guest/vmx_io.h +++ b/hypervisor/include/arch/x86/guest/vmx_io.h @@ -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) diff --git a/hypervisor/include/arch/x86/vm_config.h b/hypervisor/include/arch/x86/vm_config.h index 47607015e..aeecbc1e9 100644 --- a/hypervisor/include/arch/x86/vm_config.h +++ b/hypervisor/include/arch/x86/vm_config.h @@ -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); diff --git a/hypervisor/include/debug/vuart.h b/hypervisor/include/debug/vuart.h index 8818881c4..6add1dbd8 100644 --- a/hypervisor/include/debug/vuart.h +++ b/hypervisor/include/debug/vuart.h @@ -31,9 +31,11 @@ #define VUART_H #include #include +#include #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 */ diff --git a/hypervisor/release/vuart.c b/hypervisor/release/vuart.c index dac88f18e..f35a090f1 100644 --- a/hypervisor/release/vuart.c +++ b/hypervisor/release/vuart.c @@ -7,8 +7,8 @@ #include #include -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; } diff --git a/hypervisor/scenarios/logical_partition/vm_configurations.c b/hypervisor/scenarios/logical_partition/vm_configurations.c index 40ec02e4c..5802d99b6 100644 --- a/hypervisor/scenarios/logical_partition/vm_configurations.c +++ b/hypervisor/scenarios/logical_partition/vm_configurations.c @@ -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, diff --git a/hypervisor/scenarios/logical_partition/vm_configurations.h b/hypervisor/scenarios/logical_partition/vm_configurations.h index 24b1c9309..657db7bd3 100644 --- a/hypervisor/scenarios/logical_partition/vm_configurations.h +++ b/hypervisor/scenarios/logical_partition/vm_configurations.h @@ -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 */