mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-08-14 14:25:14 +00:00
HV: fix uart hang issue caused by bdf overridden
On a PCI type HV uart, the bdf value is in a union together with mmio_base_vaddr, then the value would be overridden by mmio_base_addr in uart16550_init(), result in is_pci_dbg_uart() returns a wrong value and then uart hang. Tracked-On: #5288 Signed-off-by: Victor Sun <victor.sun@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
feb0772a53
commit
8b86714af8
@ -20,8 +20,13 @@ struct console_uart {
|
|||||||
enum serial_dev_type type;
|
enum serial_dev_type type;
|
||||||
union {
|
union {
|
||||||
uint16_t port_address;
|
uint16_t port_address;
|
||||||
union pci_bdf bdf;
|
union {
|
||||||
void *mmio_base_vaddr;
|
struct {
|
||||||
|
union pci_bdf bdf;
|
||||||
|
void *cached_mmio_base_va;
|
||||||
|
} pci;
|
||||||
|
void *mmio_base_vaddr;
|
||||||
|
} mmio;
|
||||||
};
|
};
|
||||||
|
|
||||||
spinlock_t rx_lock;
|
spinlock_t rx_lock;
|
||||||
@ -41,14 +46,14 @@ static struct console_uart uart = {
|
|||||||
static struct console_uart uart = {
|
static struct console_uart uart = {
|
||||||
.enabled = true,
|
.enabled = true,
|
||||||
.type = PCI,
|
.type = PCI,
|
||||||
.bdf.value = CONFIG_SERIAL_PCI_BDF,
|
.mmio.pci.bdf.value = CONFIG_SERIAL_PCI_BDF,
|
||||||
.reg_width = 4,
|
.reg_width = 4,
|
||||||
};
|
};
|
||||||
#elif defined(CONFIG_SERIAL_MMIO_BASE)
|
#elif defined(CONFIG_SERIAL_MMIO_BASE)
|
||||||
static struct console_uart uart = {
|
static struct console_uart uart = {
|
||||||
.enabled = true,
|
.enabled = true,
|
||||||
.type = MMIO,
|
.type = MMIO,
|
||||||
.mmio_base_vaddr = (void *)CONFIG_SERIAL_MMIO_BASE,
|
.mmio.mmio_base_vaddr = (void *)CONFIG_SERIAL_MMIO_BASE,
|
||||||
.reg_width = 1,
|
.reg_width = 1,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -63,9 +68,9 @@ static inline uint32_t uart16550_read_reg(struct console_uart uart, uint16_t reg
|
|||||||
if (uart.type == PIO) {
|
if (uart.type == PIO) {
|
||||||
return pio_read8(uart.port_address + (reg_idx * uart.reg_width));
|
return pio_read8(uart.port_address + (reg_idx * uart.reg_width));
|
||||||
} else if (uart.type == PCI) {
|
} else if (uart.type == PCI) {
|
||||||
return mmio_read32(uart.mmio_base_vaddr + (reg_idx * uart.reg_width));
|
return mmio_read32(uart.mmio.pci.cached_mmio_base_va + (reg_idx * uart.reg_width));
|
||||||
} else {
|
} else {
|
||||||
return mmio_read8(uart.mmio_base_vaddr + (reg_idx * uart.reg_width));
|
return mmio_read8(uart.mmio.mmio_base_vaddr + (reg_idx * uart.reg_width));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,9 +82,9 @@ static inline void uart16550_write_reg(struct console_uart uart, uint32_t val, u
|
|||||||
if (uart.type == PIO) {
|
if (uart.type == PIO) {
|
||||||
pio_write8(val, uart.port_address + (reg_idx * uart.reg_width));
|
pio_write8(val, uart.port_address + (reg_idx * uart.reg_width));
|
||||||
} else if (uart.type == PCI) {
|
} else if (uart.type == PCI) {
|
||||||
mmio_write32(val, uart.mmio_base_vaddr + (reg_idx * uart.reg_width));
|
mmio_write32(val, uart.mmio.pci.cached_mmio_base_va + (reg_idx * uart.reg_width));
|
||||||
} else {
|
} else {
|
||||||
mmio_write8(val, uart.mmio_base_vaddr + (reg_idx * uart.reg_width));
|
mmio_write8(val, uart.mmio.mmio_base_vaddr + (reg_idx * uart.reg_width));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,20 +126,33 @@ static void uart16550_set_baud_rate(uint32_t baud_rate)
|
|||||||
|
|
||||||
void uart16550_init(bool early_boot)
|
void uart16550_init(bool early_boot)
|
||||||
{
|
{
|
||||||
|
void *mmio_base_va = NULL;
|
||||||
|
|
||||||
if (!uart.enabled) {
|
if (!uart.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!early_boot && (uart.type != PIO)) {
|
if (!early_boot) {
|
||||||
uart.mmio_base_vaddr = hpa2hva(hva2hpa_early(uart.mmio_base_vaddr));
|
if (uart.type == MMIO) {
|
||||||
hv_access_memory_region_update((uint64_t)uart.mmio_base_vaddr, PDE_SIZE);
|
mmio_base_va = hpa2hva(hva2hpa_early(uart.mmio.mmio_base_vaddr));
|
||||||
|
} else if (uart.type == PCI) {
|
||||||
|
mmio_base_va = hpa2hva(hva2hpa_early(uart.mmio.pci.cached_mmio_base_va));
|
||||||
|
}
|
||||||
|
if (mmio_base_va != NULL) {
|
||||||
|
hv_access_memory_region_update((uint64_t)mmio_base_va, PDE_SIZE);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if configure serial PCI BDF, get its base MMIO address */
|
/* if configure serial PCI BDF, get its base MMIO address */
|
||||||
if (uart.type == PCI) {
|
if (uart.type == PCI) {
|
||||||
uart.mmio_base_vaddr =
|
uart.mmio.pci.cached_mmio_base_va =
|
||||||
hpa2hva_early(pci_pdev_read_cfg(uart.bdf, pci_bar_offset(0), 4U) & PCIM_BAR_MEM_BASE);
|
hpa2hva_early(pci_pdev_read_cfg(uart.mmio.pci.bdf, pci_bar_offset(0), 4U) & PCIM_BAR_MEM_BASE);
|
||||||
|
if (uart.mmio.pci.cached_mmio_base_va == NULL) {
|
||||||
|
/* in case the PCI UART BAR is reset to 0 after boot */
|
||||||
|
uart.enabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
spinlock_init(&uart.rx_lock);
|
spinlock_init(&uart.rx_lock);
|
||||||
spinlock_init(&uart.tx_lock);
|
spinlock_init(&uart.tx_lock);
|
||||||
@ -223,10 +241,10 @@ void uart16550_set_property(bool enabled, enum serial_dev_type uart_type, uint64
|
|||||||
if (uart_type == PIO) {
|
if (uart_type == PIO) {
|
||||||
uart.port_address = data;
|
uart.port_address = data;
|
||||||
} else if (uart_type == PCI) {
|
} else if (uart_type == PCI) {
|
||||||
uart.bdf.value = data;
|
uart.mmio.pci.bdf.value = data;
|
||||||
uart.reg_width = 4;
|
uart.reg_width = 4;
|
||||||
} else if (uart_type == MMIO) {
|
} else if (uart_type == MMIO) {
|
||||||
uart.mmio_base_vaddr = (void *)data;
|
uart.mmio.mmio_base_vaddr = (void *)data;
|
||||||
uart.reg_width = 1;
|
uart.reg_width = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,7 +254,7 @@ bool is_pci_dbg_uart(union pci_bdf bdf_value)
|
|||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
if (uart.enabled && (uart.type == PCI)) {
|
if (uart.enabled && (uart.type == PCI)) {
|
||||||
if (bdf_value.value == uart.bdf.value) {
|
if (bdf_value.value == uart.mmio.pci.bdf.value) {
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user