diff --git a/hypervisor/debug/uart16550.c b/hypervisor/debug/uart16550.c index 1d56ec190..c917acd6b 100644 --- a/hypervisor/debug/uart16550.c +++ b/hypervisor/debug/uart16550.c @@ -121,6 +121,35 @@ static void uart16550_set_baud_rate(uint32_t baud_rate) uart16550_write_reg(uart, temp_reg, UART16550_LCR); } +static uint8_t uart_pde_page[PAGE_SIZE]__aligned(PAGE_SIZE); +static uint8_t uart_pdpte_page[PAGE_SIZE]__aligned(PAGE_SIZE); + +static void early_pgtable_map_uart(uint64_t addr) +{ + uint64_t *pml4e, *pdpte, *pde; + uint64_t value; + + CPU_CR_READ(cr3, &value); + /*assumpiton for map high mmio in early pagetable is that it is only used for + 2MB page since 1G page may not available when memory width is 39bit */ + pml4e = pml4e_offset((uint64_t *)value, addr); + /* address is above 512G */ + if(!(*pml4e & PAGE_PRESENT)) { + *pml4e = hva2hpa_early(uart_pdpte_page) + (PAGE_PRESENT|PAGE_RW); + } + pdpte = pdpte_offset(pml4e, addr); + if(!(*pdpte & PAGE_PRESENT)) { + *(pdpte) = hva2hpa_early(uart_pde_page) + (PAGE_PRESENT|PAGE_RW); + pde = pde_offset(pdpte, addr); + *pde = (addr & PDE_MASK) + (PAGE_PRESENT|PAGE_RW|PAGE_PSE); + } else if(!(*pdpte & PAGE_PSE)) { + pde = pde_offset(pdpte, addr); + if(!(*pde & PAGE_PRESENT)) { + *pde = (addr & PDE_MASK) + (PAGE_PRESENT|PAGE_RW|PAGE_PSE); + } + } +} + void uart16550_init(bool early_boot) { void *mmio_base_va = NULL; @@ -154,19 +183,18 @@ void uart16550_init(bool early_boot) uart.port_address = (uint16_t)(bar0 & PCI_BASE_ADDRESS_IO_MASK); uart.reg_width = 1; pci_pdev_write_cfg(uart.bdf, PCIR_COMMAND, 2U, cmd | PCIM_CMD_PORTEN); - } else { - uint32_t bar_hi = pci_pdev_read_cfg(uart.bdf, pci_bar_offset(1), 4U); - - /* Enable the PCI UART if the BAR is 32bit, or 64bit with 4GB- mmio space. */ - if (((bar0 & 0x7U) == 0U) || (((bar0 & 0x7U) == 4U) && (bar_hi == 0U))) { + } else if (((bar0 & 0x7U) == 0U) || ((bar0 & 0x7U) == 4U)) { uart.type = MMIO; - uart.mmio_base_vaddr = hpa2hva_early((bar0 & PCI_BASE_ADDRESS_MEM_MASK)); + uint32_t bar_hi = pci_pdev_read_cfg(uart.bdf, pci_bar_offset(1), 4U); + uint64_t addr = (bar0 & PCI_BASE_ADDRESS_MEM_MASK)|(((uint64_t)bar_hi) << 32U); + if (bar_hi != 0U) { + early_pgtable_map_uart(addr); + } + uart.mmio_base_vaddr = hpa2hva_early(addr); pci_pdev_write_cfg(uart.bdf, PCIR_COMMAND, 2U, cmd | PCIM_CMD_MEMEN); - } else { - /* TODO: enable 64bit BAR with 4GB+ mmio space */ - uart.enabled = false; - return; - } + } else { + uart.enabled = false; + return; } } }