hv: support for pci uart with high mmio
to enable early print output by pci uart, which has mmio address above 4G, add the early pagetable map for the MMIO range. we make an assumption that only map it with 2MB page, since platform with 39bit memory width have no 1G huge page feature and we cannot get the capacity at runtime, since it is a very early code stage. v2->v1: 1. add hva2hpa_early 2. add process when *pdpte is not present Signed-off-by: hangliu1 <hang1.liu@linux.intel.com> Reviewed-by: fei1.li <fei1.li@intel.com> Tracked-On: #6690
This commit is contained in:
parent
b17b5992c8
commit
bb2118d98b
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue