[PATCH] hv: support for pci uart with high mmio


hangliu1
 

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.

Signed-off-by: hangliu1 <hang1.liu@...>
---
hypervisor/debug/uart16550.c | 45 +++++++++++++++++++++++++++---------
1 file changed, 34 insertions(+), 11 deletions(-)

diff --git a/hypervisor/debug/uart16550.c b/hypervisor/debug/uart16550.c
index 1d56ec190..9dad8152f 100644
--- a/hypervisor/debug/uart16550.c
+++ b/hypervisor/debug/uart16550.c
@@ -121,6 +121,30 @@ 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);
+ if(!(*pml4e & PAGE_PRESENT)) {
+ *pml4e = (uint64_t)uart_pdpte_page + (PAGE_PRESENT|PAGE_RW);
+ }
+ pdpte = pdpte_offset(pml4e, addr);
+ /*make assumption here that *pdpte is not present since not setup
+ in assemble code except adress below 4G, which must be ensured not to
+ passed to this function*/
+ *(pdpte) = (uint64_t)uart_pde_page+ (PAGE_PRESENT|PAGE_RW);
+ pde = pde_offset(pdpte, addr);
+ *pde = (addr & PDE_MASK) + (PAGE_PRESENT|PAGE_RW|PAGE_PSE);
+}
+
void uart16550_init(bool early_boot)
{
void *mmio_base_va = NULL;
@@ -154,19 +178,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;
}
}
}
--
2.25.1


Li, Fei1
 

+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
align
+ 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 = (uint64_t)uart_pdpte_page + (PAGE_PRESENT|PAGE_RW);
hva2hpa_early(uart_pdpte_page) + (PAGE_PRESENT | PAGE_RW);
+ }
+ pdpte = pdpte_offset(pml4e, addr);
align
+ /*make assumption here that *pdpte is not present since not setup
+ in assemble code except adress below 4G, which must be ensured not to
+ passed to this function*/
Add ASSERT here or add check whether pdpte is present here.
+ *(pdpte) = (uint64_t)uart_pde_page+ (PAGE_PRESENT|PAGE_RW);
hva2hpa_early(uart_pde_page)
+ pde = pde_offset(pdpte, addr);
+ *pde = (addr & PDE_MASK) + (PAGE_PRESENT|PAGE_RW|PAGE_PSE); }
+


Eddie Dong
 

-----Original Message-----
From: acrn-dev@... <acrn-dev@...> On
Behalf Of hangliu1
Sent: Thursday, November 17, 2022 5:42 PM
To: Li, Fei1 <fei1.li@...>; acrn-dev@...
Cc: hangliu1 <hang1.liu@...>
Subject: [acrn-dev] [PATCH] 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.

Signed-off-by: hangliu1 <hang1.liu@...>
---
hypervisor/debug/uart16550.c | 45 +++++++++++++++++++++++++++---------
1 file changed, 34 insertions(+), 11 deletions(-)

diff --git a/hypervisor/debug/uart16550.c b/hypervisor/debug/uart16550.c
index 1d56ec190..9dad8152f 100644
--- a/hypervisor/debug/uart16550.c
+++ b/hypervisor/debug/uart16550.c
@@ -121,6 +121,30 @@ 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);
+ if(!(*pml4e & PAGE_PRESENT)) {
+ *pml4e = (uint64_t)uart_pdpte_page +
(PAGE_PRESENT|PAGE_RW);
+ }
+ pdpte = pdpte_offset(pml4e, addr);
+ /*make assumption here that *pdpte is not present since not setup
+ in assemble code except adress below 4G, which must be ensured
not to
+ passed to this function*/
+ *(pdpte) = (uint64_t)uart_pde_page+ (PAGE_PRESENT|PAGE_RW);
+ pde = pde_offset(pdpte, addr);
+ *pde = (addr & PDE_MASK) +
(PAGE_PRESENT|PAGE_RW|PAGE_PSE); }
+
void uart16550_init(bool early_boot)
{
void *mmio_base_va = NULL;
@@ -154,19 +178,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);
We only do this for 64 bit MMIO BAR. Not for 32 bit MMIO BAR though bar_hi is likely 0 for this case.

+ 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;
}
}
}
--
2.25.1





hangliu1
 

On Mon, Nov 21, 2022 at 06:18:39PM +0000, Eddie Dong wrote:


-----Original Message-----
From: acrn-dev@... <acrn-dev@...> On
Behalf Of hangliu1
Sent: Thursday, November 17, 2022 5:42 PM
To: Li, Fei1 <fei1.li@...>; acrn-dev@...
Cc: hangliu1 <hang1.liu@...>
Subject: [acrn-dev] [PATCH] 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.

Signed-off-by: hangliu1 <hang1.liu@...>
---
hypervisor/debug/uart16550.c | 45 +++++++++++++++++++++++++++---------
1 file changed, 34 insertions(+), 11 deletions(-)

diff --git a/hypervisor/debug/uart16550.c b/hypervisor/debug/uart16550.c
index 1d56ec190..9dad8152f 100644
--- a/hypervisor/debug/uart16550.c
+++ b/hypervisor/debug/uart16550.c
@@ -121,6 +121,30 @@ 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);
+ if(!(*pml4e & PAGE_PRESENT)) {
+ *pml4e = (uint64_t)uart_pdpte_page +
(PAGE_PRESENT|PAGE_RW);
+ }
+ pdpte = pdpte_offset(pml4e, addr);
+ /*make assumption here that *pdpte is not present since not setup
+ in assemble code except adress below 4G, which must be ensured
not to
+ passed to this function*/
+ *(pdpte) = (uint64_t)uart_pde_page+ (PAGE_PRESENT|PAGE_RW);
+ pde = pde_offset(pdpte, addr);
+ *pde = (addr & PDE_MASK) +
(PAGE_PRESENT|PAGE_RW|PAGE_PSE); }
+
void uart16550_init(bool early_boot)
{
void *mmio_base_va = NULL;
@@ -154,19 +178,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);
We only do this for 64 bit MMIO BAR. Not for 32 bit MMIO BAR though bar_hi is likely 0 for this case.
yes, but this patch is merged, it will be soon be modified by later patches regarding other uart
changes.

+ 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;
}
}
}
--
2.25.1