]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
core/driver: Add support for mapping the debug UART from the driver
authorJan Kiszka <jan.kiszka@siemens.com>
Sun, 12 Oct 2014 14:52:31 +0000 (16:52 +0200)
committerJan Kiszka <jan.kiszka@siemens.com>
Thu, 8 Jan 2015 12:01:23 +0000 (13:01 +0100)
If the debug UART is memory-mapped, we can only access prior to
switching to hypervisor mappings if the driver supports us in this. By
adding a debug_uart memory region to the system configuration, we tell
the driver about the mapping need. In turn, the driver reports the
virtual address via an additional header field. The mapping can be
released on Linux side right after enabling the hypervisor

Provided the virtual address of the UART mapping as chosen by Linux does
not conflict with our remapping region, this mapping can safely be
replicated into the hypervisor address space so that we don't need to
adjust the UART access after enabling our own mapping.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
driver.c
hypervisor/include/jailhouse/cell-config.h
hypervisor/include/jailhouse/header.h
hypervisor/paging.c

index 9948959eec4fc98b5039fc93f182bb84c531c45f..a675e12d63bdccbccef128a6d50dc5213e2ad26c 100644 (file)
--- a/driver.c
+++ b/driver.c
@@ -523,6 +523,7 @@ static int jailhouse_enable(struct jailhouse_system __user *arg)
        struct jailhouse_system *config;
        struct jailhouse_memory *hv_mem = &config_header.hypervisor_memory;
        struct jailhouse_header *header;
+       void __iomem *uart = NULL;
        unsigned long config_size;
        const char *fw_name;
        long max_cpus;
@@ -592,6 +593,19 @@ static int jailhouse_enable(struct jailhouse_system __user *arg)
                goto error_unmap;
        }
 
+       if (config->debug_uart.flags & JAILHOUSE_MEM_IO) {
+               uart = ioremap(config->debug_uart.phys_start,
+                              config->debug_uart.size);
+               if (!uart) {
+                       err = -EINVAL;
+                       pr_err("jailhouse: Unable to map hypervisor UART at "
+                              "%08lx\n",
+                              (unsigned long)config->debug_uart.phys_start);
+                       goto error_unmap;
+               }
+               header->debug_uart_base = (void *)uart;
+       }
+
        root_cell = create_cell(&config->root_cell);
        if (IS_ERR(root_cell)) {
                err = PTR_ERR(root_cell);
@@ -622,6 +636,9 @@ static int jailhouse_enable(struct jailhouse_system __user *arg)
        jailhouse_pci_do_all_devices(root_cell, JAILHOUSE_PCI_TYPE_IVSHMEM,
                                     JAILHOUSE_PCI_ACTION_ADD);
 
+       if (uart)
+               iounmap(uart);
+
        release_firmware(hypervisor);
 
        enabled = true;
@@ -639,6 +656,8 @@ error_free_cell:
 
 error_unmap:
        vunmap(hypervisor_mem);
+       if (uart)
+               iounmap(uart);
 
 error_release_fw:
        release_firmware(hypervisor);
index c4ad5d865a2d4dde4ffd00f9c05dbe0e8e9bfaf1..1d6034598a6a876e43baea210d7264a69b332632 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Jailhouse, a Linux-based partitioning hypervisor
  *
- * Copyright (c) Siemens AG, 2013
+ * Copyright (c) Siemens AG, 2014
  *
  * Authors:
  *  Jan Kiszka <jan.kiszka@siemens.com>
@@ -93,6 +93,7 @@ struct jailhouse_pci_capability {
 
 struct jailhouse_system {
        struct jailhouse_memory hypervisor_memory;
+       struct jailhouse_memory debug_uart;
        union {
                struct {
                        __u64 mmconfig_base;
index f5931fefe58146e9cae710d864695bd8eaa5dbfd..15054049680f275c397edda89f06631675a35ce5 100644 (file)
@@ -45,4 +45,7 @@ struct jailhouse_header {
        /** Number of online CPUs that will call the entry function.
         * @note Filled by Linux loader driver before entry. */
        unsigned int online_cpus;
+       /** Virtual base address of debug UART (if used).
+        * @note Filled by Linux loader driver before entry. */
+       void *debug_uart_base;
 };
index da615f1c87f7cabd863be376aaae75ff1f867c60..fee26394a9035013a6325fb77426164919c3da10 100644 (file)
@@ -460,7 +460,7 @@ void *paging_get_guest_pages(const struct guest_paging_structures *pg_structs,
  */
 int paging_init(void)
 {
-       unsigned long n, per_cpu_pages, config_pages, bitmap_pages;
+       unsigned long n, per_cpu_pages, config_pages, bitmap_pages, vaddr;
        int err;
 
        per_cpu_pages = hypervisor_header.max_cpus *
@@ -511,6 +511,22 @@ int paging_init(void)
        if (err)
                goto error_nomem;
 
+       if (system_config->debug_uart.flags & JAILHOUSE_MEM_IO) {
+               vaddr = (unsigned long)hypervisor_header.debug_uart_base;
+               if (vaddr + system_config->debug_uart.size >= REMAP_BASE &&
+                   vaddr < REMAP_BASE + remap_pool.pages * PAGE_SIZE) {
+                       printk("FATAL: UART overlaps remapping region\n");
+                       return -EINVAL;
+               }
+               err = paging_create(&hv_paging_structs,
+                                   system_config->debug_uart.phys_start,
+                                   system_config->debug_uart.size, vaddr,
+                                   PAGE_DEFAULT_FLAGS | PAGE_FLAG_DEVICE,
+                                   PAGING_NON_COHERENT);
+               if (err)
+                       goto error_nomem;
+       }
+
        /* Make sure any remappings to the temporary regions can be performed
         * without allocations of page table pages. */
        err = paging_create(&hv_paging_structs, 0,