Skip to content

Commit 235d886

Browse files
conghuic23acrnsi
authored andcommitted
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>
1 parent 3c92d7b commit 235d886

File tree

12 files changed

+141
-104
lines changed

12 files changed

+141
-104
lines changed

hypervisor/arch/x86/guest/assign.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -688,8 +688,8 @@ int32_t ptirq_intx_pin_remap(struct acrn_vm *vm, uint32_t virt_pin, uint32_t vpi
688688
* entry already be held by others, return error.
689689
*/
690690

691-
/* no remap for hypervisor owned intx */
692-
if (is_sos_vm(vm) && hv_used_dbg_intx(virt_sid.intx_id.pin)) {
691+
/* no remap for vuart intx */
692+
if (is_vuart_intx(vm, virt_sid.intx_id.pin)) {
693693
status = -ENODEV;
694694
}
695695

hypervisor/arch/x86/guest/vm.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -398,20 +398,12 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
398398
if (vm_load_pm_s_state(vm) == 0) {
399399
register_pm1ab_handler(vm);
400400
}
401-
402-
/* Create virtual uart; just when uart enabled, vuart can work */
403-
if (is_dbg_uart_enabled()) {
404-
vuart_init(vm);
405-
}
406401
}
407402
vpic_init(vm);
408403

409-
#ifdef CONFIG_PARTITION_MODE
410-
/* Create virtual uart; just when uart enabled, vuart can work */
411-
if (vm_config->vm_vuart && is_dbg_uart_enabled()) {
412-
vuart_init(vm);
413-
}
414-
#endif
404+
/* Create virtual uart;*/
405+
vuart_init(vm, vm_config->vuart);
406+
415407
vrtc_init(vm);
416408

417409
vpci_init(vm);

hypervisor/debug/shell.c

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -842,44 +842,32 @@ static int32_t shell_dumpmem(int32_t argc, char **argv)
842842
return 0;
843843
}
844844

845-
static int32_t shell_to_vm_console(__unused int32_t argc, __unused char **argv)
845+
static int32_t shell_to_vm_console(int32_t argc, char **argv)
846846
{
847847
char temp_str[TEMP_STR_SIZE];
848848
uint16_t vm_id = 0U;
849849

850850
struct acrn_vm *vm;
851851
struct acrn_vuart *vu;
852-
#ifdef CONFIG_PARTITION_MODE
853-
struct acrn_vm_config *vm_config;
854852

855853
if (argc == 2U) {
856854
vm_id = sanitize_vmid(strtol_deci(argv[1]));
857855
}
858856

859-
vuart_vmid = vm_id;
860-
#endif
861857
/* Get the virtual device node */
862858
vm = get_vm_from_vmid(vm_id);
863859
if (!is_valid_vm(vm)) {
860+
shell_puts("VM is not valid \n");
864861
return -EINVAL;
865862
}
866-
867-
#ifdef CONFIG_PARTITION_MODE
868-
vm_config = get_vm_config(vm_id);
869-
if (!vm_config->vm_vuart) {
870-
snprintf(temp_str, TEMP_STR_SIZE, "No vUART configured for vm%d\n", vm_id);
871-
shell_puts(temp_str);
863+
vu = vm_console_vuart(vm);
864+
if (!vu->active) {
865+
shell_puts("vuart console is not active \n");
872866
return 0;
873867
}
874-
#endif
875-
876-
vu = vm_vuart(vm);
877-
/* UART is now owned by the SOS.
878-
* Indicate by toggling the flag.
879-
*/
880-
vu->active = true;
868+
console_vmid = vm_id;
881869
/* Output that switching to SOS shell */
882-
snprintf(temp_str, TEMP_STR_SIZE, "\r\n----- Entering Guest %d Shell -----\r\n", vm_id);
870+
snprintf(temp_str, TEMP_STR_SIZE, "\r\n----- Entering VM %d Shell -----\r\n", vm_id);
883871

884872
shell_puts(temp_str);
885873

hypervisor/debug/shell_priv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#define SHELL_CMD_MAX_LEN 100U
1313
#define SHELL_STRING_MAX_LEN (PAGE_SIZE << 2U)
1414

15+
extern int16_t console_vmid;
16+
1517
/* Shell Command Function */
1618
typedef int32_t (*shell_cmd_fn_t)(int32_t argc, char **argv);
1719

hypervisor/debug/vuart.c

Lines changed: 109 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,11 @@
3939
static uint32_t vuart_com_irq = CONFIG_COM_IRQ;
4040
static uint16_t vuart_com_base = CONFIG_COM_BASE;
4141

42-
#ifndef CONFIG_PARTITION_MODE
43-
static char vuart_rx_buf[RX_BUF_SIZE];
44-
static char vuart_tx_buf[TX_BUF_SIZE];
45-
#endif
46-
4742
#define vuart_lock_init(vu) spinlock_init(&((vu)->lock))
4843
#define vuart_lock(vu) spinlock_obtain(&((vu)->lock))
4944
#define vuart_unlock(vu) spinlock_release(&((vu)->lock))
5045

51-
#ifdef CONFIG_PARTITION_MODE
52-
uint16_t vuart_vmid = 0xFFFFU;
53-
#endif
46+
uint16_t console_vmid = ACRN_INVALID_VMID;
5447

5548
static inline void fifo_reset(struct fifo *fifo)
5649
{
@@ -92,13 +85,8 @@ static inline uint32_t fifo_numchars(const struct fifo *fifo)
9285

9386
static inline void vuart_fifo_init(struct acrn_vuart *vu)
9487
{
95-
#ifdef CONFIG_PARTITION_MODE
9688
vu->txfifo.buf = vu->vuart_tx_buf;
9789
vu->rxfifo.buf = vu->vuart_rx_buf;
98-
#else
99-
vu->txfifo.buf = vuart_tx_buf;
100-
vu->rxfifo.buf = vuart_rx_buf;
101-
#endif
10290
vu->txfifo.size = TX_BUF_SIZE;
10391
vu->rxfifo.size = RX_BUF_SIZE;
10492
fifo_reset(&(vu->txfifo));
@@ -125,9 +113,28 @@ static uint8_t vuart_intr_reason(const struct acrn_vuart *vu)
125113
}
126114
}
127115

128-
struct acrn_vuart *vm_vuart(struct acrn_vm *vm)
116+
struct acrn_vuart *find_vuart_by_port(struct acrn_vm *vm, uint16_t offset)
117+
{
118+
uint8_t i;
119+
struct acrn_vuart *vu, *ret_vu = NULL;
120+
121+
/* TODO: support pci vuart find */
122+
for (i = 0; i < MAX_VUART_NUM_PER_VM; i++) {
123+
vu = &vm->vuart[i];
124+
if (vu->active == true && vu->port_base == (offset & ~0x7U)) {
125+
ret_vu = vu;
126+
break;
127+
}
128+
}
129+
return ret_vu;
130+
}
131+
132+
/*
133+
* @post return != NULL
134+
*/
135+
struct acrn_vuart *vm_console_vuart(struct acrn_vm *vm)
129136
{
130-
return &(vm->vuart);
137+
return &vm->vuart[0];
131138
}
132139

133140
/*
@@ -141,7 +148,7 @@ static void vuart_toggle_intr(const struct acrn_vuart *vu)
141148
uint32_t operation;
142149

143150
intr_reason = vuart_intr_reason(vu);
144-
vioapic_get_rte(vu->vm, vuart_com_irq, &rte);
151+
vioapic_get_rte(vu->vm, vu->irq, &rte);
145152

146153
/* TODO:
147154
* 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)
157164
operation = (intr_reason != IIR_NOPEND) ? GSI_SET_HIGH : GSI_SET_LOW;
158165
}
159166

160-
vpic_set_irqline(vu->vm, vuart_com_irq, operation);
161-
vioapic_set_irqline_lock(vu->vm, vuart_com_irq, operation);
167+
vpic_set_irqline(vu->vm, vu->irq, operation);
168+
vioapic_set_irqline_lock(vu->vm, vu->irq, operation);
162169
}
163170

164171
static bool vuart_write(struct acrn_vm *vm, uint16_t offset_arg,
165172
__unused size_t width, uint32_t value)
166173
{
167174
uint16_t offset = offset_arg;
168-
struct acrn_vuart *vu = vm_vuart(vm);
175+
struct acrn_vuart *vu = find_vuart_by_port(vm, offset);
169176
uint8_t value_u8 = (uint8_t)value;
170177

171-
offset -= vu->base;
178+
offset -= vu->port_base;
172179
vuart_lock(vu);
173180
/*
174181
* 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
253260
{
254261
uint16_t offset = offset_arg;
255262
uint8_t iir, reg, intr_reason;
256-
struct acrn_vuart *vu = vm_vuart(vm);
263+
struct acrn_vuart *vu = find_vuart_by_port(vm, offset);
257264
struct pio_request *pio_req = &vcpu->req.reqs.pio;
258265

259-
offset -= vu->base;
266+
offset -= vu->port_base;
260267
vuart_lock(vu);
261268
/*
262269
* Take care of the special case DLAB accesses first
@@ -330,15 +337,33 @@ static bool vuart_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t offs
330337
return true;
331338
}
332339

333-
static void vuart_register_io_handler(struct acrn_vm *vm)
340+
/*
341+
* @pre: vuart_idx = 0 or 1
342+
*/
343+
static bool vuart_register_io_handler(struct acrn_vm *vm, uint16_t port_base, uint32_t vuart_idx)
334344
{
345+
uint32_t pio_idx;
346+
bool ret = true;
347+
335348
struct vm_io_range range = {
336349
.flags = IO_ATTR_RW,
337-
.base = vuart_com_base,
350+
.base = port_base,
338351
.len = 8U
339352
};
340-
341-
register_pio_emulation_handler(vm, UART_PIO_IDX, &range, vuart_read, vuart_write);
353+
switch (vuart_idx) {
354+
case 0:
355+
pio_idx = UART_PIO_IDX0;
356+
break;
357+
case 1:
358+
pio_idx = UART_PIO_IDX1;
359+
break;
360+
default:
361+
printf("Not support vuart index %d, will not register \n");
362+
ret = false;
363+
}
364+
if (ret)
365+
register_pio_emulation_handler(vm, pio_idx, &range, vuart_read, vuart_write);
366+
return ret;
342367
}
343368

344369
/**
@@ -367,7 +392,7 @@ void vuart_console_rx_chars(struct acrn_vuart *vu)
367392

368393
if (ch == GUEST_CONSOLE_TO_HV_SWITCH_KEY) {
369394
/* Switch the console */
370-
vu->active = false;
395+
console_vmid = ACRN_INVALID_VMID;
371396
printf("\r\n\r\n ---Entering ACRN SHELL---\r\n");
372397
}
373398
if (ch != -1) {
@@ -381,46 +406,79 @@ void vuart_console_rx_chars(struct acrn_vuart *vu)
381406
struct acrn_vuart *vuart_console_active(void)
382407
{
383408
struct acrn_vm *vm = NULL;
409+
struct acrn_vuart *vu = NULL;
384410

385-
#ifdef CONFIG_PARTITION_MODE
386-
if (vuart_vmid < CONFIG_MAX_VM_NUM) {
387-
vm = get_vm_from_vmid(vuart_vmid);
411+
if (console_vmid < CONFIG_MAX_VM_NUM) {
412+
vm = get_vm_from_vmid(console_vmid);
388413
}
389-
#else
390-
vm = get_sos_vm();
391-
#endif
392414

393415
if (is_valid_vm(vm)) {
394-
struct acrn_vuart *vu = vm_vuart(vm);
395-
396-
if (vu->active) {
397-
return vu;
398-
}
416+
vu = vm_console_vuart(vm);
399417
}
400-
return NULL;
418+
return (vu && vu->active) ? vu : NULL;
401419
}
402420

403-
void vuart_init(struct acrn_vm *vm)
421+
static void vuart_setup(struct acrn_vm *vm,
422+
struct vuart_config *vu_config, uint16_t vuart_idx)
404423
{
405424
uint32_t divisor;
406-
struct acrn_vuart *vu = vm_vuart(vm);
425+
struct acrn_vuart *vu = &vm->vuart[vuart_idx];
407426

408427
/* Set baud rate*/
409-
divisor = (UART_CLOCK_RATE / BAUD_9600) >> 4U;
410-
vm->vuart.dll = (uint8_t)divisor;
411-
vm->vuart.dlh = (uint8_t)(divisor >> 8U);
412-
413-
vm->vuart.active = false;
414-
vm->vuart.base = vuart_com_base;
415-
vm->vuart.vm = vm;
428+
divisor = (UART_CLOCK_RATE / BAUD_115200) >> 4U;
429+
vu->dll = (uint8_t)divisor;
430+
vu->dlh = (uint8_t)(divisor >> 8U);
431+
vu->vm = vm;
416432
vuart_fifo_init(vu);
417433
vuart_lock_init(vu);
418-
vuart_register_io_handler(vm);
434+
if (vu_config->type == VUART_LEGACY_PIO) {
435+
vu->port_base = vu_config->addr.port_base;
436+
vu->irq = vu_config->irq;
437+
if (vuart_register_io_handler(vm, vu->port_base, vuart_idx)) {
438+
vu->active = true;
439+
}
440+
} else {
441+
/*TODO: add pci vuart support here*/
442+
printf("PCI vuart is not support\n");
443+
}
444+
}
445+
446+
bool is_vuart_intx(struct acrn_vm *vm, uint32_t intx_pin)
447+
{
448+
uint8_t i;
449+
bool ret = false;
450+
451+
for (i = 0; i < MAX_VUART_NUM_PER_VM; i++)
452+
if (vm->vuart[i].active && vm->vuart[i].irq == intx_pin)
453+
ret = true;
454+
return ret;
455+
}
456+
457+
void vuart_init(struct acrn_vm *vm, struct vuart_config *vu_config)
458+
{
459+
uint8_t i;
460+
461+
for (i = 0; i < MAX_VUART_NUM_PER_VM; i++) {
462+
vm->vuart[i].active = false;
463+
/* This vuart is not exist */
464+
if (vu_config[i].type == VUART_LEGACY_PIO &&
465+
vu_config[i].addr.port_base == INVALID_COM_BASE)
466+
continue;
467+
vuart_setup(vm, &vu_config[i], i);
468+
}
419469
}
420470

421-
bool hv_used_dbg_intx(uint32_t intx_pin)
471+
void vuart_deinit(struct acrn_vm *vm)
422472
{
423-
return is_dbg_uart_enabled() && (intx_pin == vuart_com_irq);
473+
uint8_t i;
474+
475+
/* reset console_vmid to switch back to hypervisor console */
476+
if (console_vmid == vm->vm_id)
477+
console_vmid = ACRN_INVALID_VMID;
478+
479+
for (i = 0; i < MAX_VUART_NUM_PER_VM; i++) {
480+
vm->vuart[i].active = false;
481+
}
424482
}
425483

426484
/* vuart=ttySx@irqN, like vuart=ttyS1@irq6 head "vuart=ttyS" is parsed */

hypervisor/include/arch/x86/guest/vm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ struct acrn_vm {
120120
struct e820_entry *e820_entries;
121121
uint16_t vm_id; /* Virtual machine identifier */
122122
enum vm_state state; /* VM state */
123-
struct acrn_vuart vuart; /* Virtual UART */
123+
struct acrn_vuart vuart[MAX_VUART_NUM_PER_VM]; /* Virtual UART */
124124
enum vpic_wire_mode wire_mode;
125125
struct iommu_domain *iommu; /* iommu domain of this VM */
126126
spinlock_t spinlock; /* Spin-lock used to protect VM modifications */

hypervisor/include/arch/x86/guest/vmx_io.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
#define PIC_ELC_PIO_IDX (PIC_SLAVE_PIO_IDX + 1U)
1616
#define PCI_CFGADDR_PIO_IDX (PIC_ELC_PIO_IDX + 1U)
1717
#define PCI_CFGDATA_PIO_IDX (PCI_CFGADDR_PIO_IDX + 1U)
18-
#define UART_PIO_IDX (PCI_CFGDATA_PIO_IDX + 1U)
19-
#define PM1A_EVT_PIO_IDX (UART_PIO_IDX + 1U)
18+
/* When MAX_VUART_NUM_PER_VM is larger than 2, UART_PIO_IDXn should also be added here */
19+
#define UART_PIO_IDX0 (PCI_CFGDATA_PIO_IDX + 1U)
20+
#define UART_PIO_IDX1 (UART_PIO_IDX0 + 1U)
21+
#define PM1A_EVT_PIO_IDX (UART_PIO_IDX1 + 1U)
2022
#define PM1A_CNT_PIO_IDX (PM1A_EVT_PIO_IDX + 1U)
2123
#define PM1B_EVT_PIO_IDX (PM1A_CNT_PIO_IDX + 1U)
2224
#define PM1B_CNT_PIO_IDX (PM1B_EVT_PIO_IDX + 1U)

hypervisor/include/arch/x86/vm_config.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ struct acrn_vm_config {
8888
struct acrn_vm_os_config os_config; /* OS information the VM */
8989
uint16_t clos; /* if guest_flags has GUEST_FLAG_CLOS_REQUIRED, then VM use this CLOS */
9090

91-
bool vm_vuart;
9291
struct vuart_config vuart[MAX_VUART_NUM_PER_VM];/* vuart configuration for VM */
9392
struct mptable_info *mptable; /* Pointer to mptable struct if VM type is pre-launched */
9493
} __aligned(8);

0 commit comments

Comments
 (0)