]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
arm: setup stage 2 MMU for the cells
authorJean-Philippe Brucker <jean-philippe.brucker@arm.com>
Fri, 25 Jul 2014 17:41:38 +0000 (18:41 +0100)
committerJan Kiszka <jan.kiszka@siemens.com>
Fri, 19 Dec 2014 10:04:07 +0000 (11:04 +0100)
This patch adds the necessary MMU setup code for the cells. They use the
same paging functions as the hypervisor, but their flags are slightly
different.

As an improvement, it would be good to use only two levels of page
tables on 32bit instead of three. This would limit the memory accessible
from EL1 to 16GB instead of the current 256.
This doesn't really matter for the moment: since the core handles virtual
addresses with unsigned longs, LPAE cannot be used.

Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
[Jan: adjustments to recent paging subsystem changes]
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
hypervisor/arch/arm/Makefile
hypervisor/arch/arm/include/asm/cell.h
hypervisor/arch/arm/include/asm/control.h [new file with mode: 0644]
hypervisor/arch/arm/include/asm/paging.h
hypervisor/arch/arm/include/asm/processor.h
hypervisor/arch/arm/include/asm/sysregs.h
hypervisor/arch/arm/mmu_cell.c [new file with mode: 0644]
hypervisor/arch/arm/setup.c

index 3b32401ff96bdaaefa874f89e517b828b4a6bb15..1957436fb37e5e95208052fb044d311bcee79736 100644 (file)
@@ -17,5 +17,5 @@ KBUILD_AFLAGS := $(filter-out -include asm/unified.h,$(KBUILD_AFLAGS))
 always := built-in.o
 
 obj-y := entry.o dbg-write.o exception.o setup.o lib.o
-obj-y += paging.o mmu_hyp.o
+obj-y += paging.o mmu_hyp.o mmu_cell.o
 obj-$(CONFIG_SERIAL_AMBA_PL011) += dbg-write-pl011.o
index 616553cdb28b61a4cdb0077c0cb79a6b2b029536..dba6f2d8660203fb57053205fbfcf0ac93c01bf8 100644 (file)
 #define _JAILHOUSE_ASM_CELL_H
 
 #include <jailhouse/types.h>
-#include <asm/paging.h>
+
+#ifndef __ASSEMBLY__
 
 #include <jailhouse/cell-config.h>
+#include <jailhouse/paging.h>
 #include <jailhouse/hypercall.h>
 
+struct arch_cell {
+       struct paging_structures mm;
+};
+
 struct cell {
+       struct arch_cell arch;
+
        unsigned int id;
        unsigned int data_pages;
        struct jailhouse_cell_desc *config;
@@ -39,4 +47,5 @@ struct cell {
 
 extern struct cell root_cell;
 
+#endif /* !__ASSEMBLY__ */
 #endif /* !_JAILHOUSE_ASM_CELL_H */
diff --git a/hypervisor/arch/arm/include/asm/control.h b/hypervisor/arch/arm/include/asm/control.h
new file mode 100644 (file)
index 0000000..b569cba
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) ARM Limited, 2014
+ *
+ * Authors:
+ *  Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef _JAILHOUSE_ASM_CONTROL_H
+#define _JAILHOUSE_ASM_CONTROL_H
+
+#include <asm/cell.h>
+#include <asm/percpu.h>
+
+#ifndef __ASSEMBLY__
+
+int arch_mmu_cell_init(struct cell *cell);
+int arch_mmu_cpu_cell_init(struct per_cpu *cpu_data);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* !_JAILHOUSE_ASM_CONTROL_H */
index 401aff9d46442970bc83786c2166259e355d2501..3e32aae10b7fd0810b8773438e9ffefd31847a23 100644 (file)
@@ -98,6 +98,7 @@
 #define BLOCK_2M_VADDR_MASK    BIT_MASK(20, 0)
 
 #define TTBR_MASK              BIT_MASK(47, PADDR_OFF)
+#define VTTBR_VMID_SHIFT       48
 
 #define HTCR_RES1              ((1 << 31) | (1 << 23))
 #define VTCR_RES1              ((1 << 31))
index 170c87748276ef75b03b65da791410a8ef4cd8ac..6964830ca1a5c79cee043277c3ce453609a83c96 100644 (file)
 #define SCTLR_AFE_BIT  (1 << 29)
 #define SCTLR_TE_BIT   (1 << 30)
 
+#define HCR_TRVM_BIT   (1 << 30)
+#define HCR_TVM_BIT    (1 << 26)
+#define HCR_HDC_BIT    (1 << 29)
+#define HCR_TGE_BIT    (1 << 27)
+#define HCR_TTLB_BIT   (1 << 25)
+#define HCR_TPU_BIT    (1 << 24)
+#define HCR_TPC_BIT    (1 << 23)
+#define HCR_TSW_BIT    (1 << 22)
+#define HCR_TAC_BIT    (1 << 21)
+#define HCR_TIDCP_BIT  (1 << 20)
+#define HCR_TSC_BIT    (1 << 19)
+#define HCR_TID3_BIT   (1 << 18)
+#define HCR_TID2_BIT   (1 << 17)
+#define HCR_TID1_BIT   (1 << 16)
+#define HCR_TID0_BIT   (1 << 15)
+#define HCR_TWE_BIT    (1 << 14)
+#define HCR_TWI_BIT    (1 << 13)
+#define HCR_DC_BIT     (1 << 12)
+#define HCR_BSU_BITS   (3 << 10)
+#define HCR_BSU_INNER  (1 << 10)
+#define HCR_BSU_OUTER  (2 << 10)
+#define HCR_BSU_FULL   HCR_BSU_BITS
+#define HCR_FB_BIT     (1 << 9)
+#define HCR_VA_BIT     (1 << 8)
+#define HCR_VI_BIT     (1 << 7)
+#define HCR_VF_BIT     (1 << 6)
+#define HCR_AMO_BIT    (1 << 5)
+#define HCR_IMO_BIT    (1 << 4)
+#define HCR_FMO_BIT    (1 << 3)
+#define HCR_PTW_BIT    (1 << 2)
+#define HCR_SWIO_BIT   (1 << 1)
+#define HCR_VM_BIT     (1 << 0)
+
 #define PAR_F_BIT      0x1
 #define PAR_FST_SHIFT  1
 #define PAR_FST_MASK   0x3f
index 261d93488e4e3281f45d37159706a9aabe78040e..ea7bc7a57e6480afeeec6ee7541fb7b7a7341101 100644 (file)
@@ -40,6 +40,8 @@
 #define PAR_EL1                SYSREG_64(0, c7)
 
 /* AArch32-specific registers */
+#define HCR            SYSREG_32(4, c1, c1, 0)
+#define HCR2           SYSREG_32(4, c1, c1, 4)
 #define HMAIR0         SYSREG_32(4, c10, c2, 0)
 #define HMAIR1         SYSREG_32(4, c10, c2, 1)
 #define HVBAR          SYSREG_32(4, c12, c0, 0)
diff --git a/hypervisor/arch/arm/mmu_cell.c b/hypervisor/arch/arm/mmu_cell.c
new file mode 100644 (file)
index 0000000..bb54445
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) ARM Limited, 2014
+ *
+ * Authors:
+ *  Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <jailhouse/control.h>
+#include <jailhouse/paging.h>
+#include <jailhouse/printk.h>
+#include <asm/sysregs.h>
+#include <asm/control.h>
+
+int arch_map_memory_region(struct cell *cell,
+                          const struct jailhouse_memory *mem)
+{
+       u64 phys_start = mem->phys_start;
+       u32 flags = PTE_FLAG_VALID | PTE_ACCESS_FLAG;
+
+       if (mem->flags & JAILHOUSE_MEM_READ)
+               flags |= S2_PTE_ACCESS_RO;
+       if (mem->flags & JAILHOUSE_MEM_WRITE)
+               flags |= S2_PTE_ACCESS_WO;
+       /*
+        * `DMA' may be a bit misleading here: it is used to define MMIO regions
+        */
+       if (mem->flags & JAILHOUSE_MEM_DMA)
+               flags |= S2_PTE_FLAG_DEVICE;
+       else
+               flags |= S2_PTE_FLAG_NORMAL;
+       if (mem->flags & JAILHOUSE_MEM_COMM_REGION)
+               phys_start = paging_hvirt2phys(&cell->comm_page);
+       /*
+       if (!(mem->flags & JAILHOUSE_MEM_EXECUTE))
+               flags |= S2_PAGE_ACCESS_XN;
+       */
+
+       return paging_create(&cell->arch.mm, phys_start, mem->size,
+               mem->virt_start, flags, PAGING_NON_COHERENT);
+}
+
+int arch_unmap_memory_region(struct cell *cell,
+                            const struct jailhouse_memory *mem)
+{
+       return paging_destroy(&cell->arch.mm, mem->virt_start, mem->size,
+                       PAGING_NON_COHERENT);
+}
+
+unsigned long arch_paging_gphys2phys(struct per_cpu *cpu_data,
+                                    unsigned long gphys, unsigned long flags)
+{
+       /* Translate IPA->PA */
+       return paging_virt2phys(&cpu_data->cell->arch.mm, gphys, flags);
+}
+
+int arch_mmu_cell_init(struct cell *cell)
+{
+       cell->arch.mm.root_paging = hv_paging;
+       cell->arch.mm.root_table = page_alloc(&mem_pool, 1);
+       if (!cell->arch.mm.root_table)
+               return -ENOMEM;
+
+       return 0;
+}
+
+int arch_mmu_cpu_cell_init(struct per_cpu *cpu_data)
+{
+       struct cell *cell = cpu_data->cell;
+       unsigned long cell_table = paging_hvirt2phys(cell->arch.mm.root_table);
+       u64 vttbr = 0;
+       u32 vtcr = T0SZ
+               | SL0 << TCR_SL0_SHIFT
+               | (TCR_RGN_WB_WA << TCR_IRGN0_SHIFT)
+               | (TCR_RGN_WB_WA << TCR_ORGN0_SHIFT)
+               | (TCR_INNER_SHAREABLE << TCR_SH0_SHIFT)
+               | VTCR_RES1;
+
+       if (cell->id > 0xff) {
+               panic_printk("No cell ID available\n");
+               return -E2BIG;
+       }
+       vttbr |= (u64)cell->id << VTTBR_VMID_SHIFT;
+       vttbr |= (u64)(cell_table & TTBR_MASK);
+
+       arm_write_sysreg(VTTBR_EL2, vttbr);
+       arm_write_sysreg(VTCR_EL2, vtcr);
+
+       isb();
+       /*
+        * Invalidate all stage-1 and 2 TLB entries for the current VMID
+        * ERET will ensure completion of these ops
+        */
+       arm_write_sysreg(TLBIALL, 1);
+
+       return 0;
+}
index 540fb1015aa8890294f615659ab46557a60b3c2a..6b44a0341c1985a772c459ebf7599f90b3694e70 100644 (file)
  * the COPYING file in the top-level directory.
  */
 
+#include <asm/control.h>
 #include <asm/percpu.h>
 #include <asm/platform.h>
 #include <asm/setup.h>
 #include <asm/sysregs.h>
+#include <jailhouse/control.h>
 #include <jailhouse/entry.h>
 #include <jailhouse/paging.h>
 #include <jailhouse/string.h>
 
 int arch_init_early(void)
 {
-       return arch_map_device(UART_BASE_PHYS, UART_BASE_VIRT, PAGE_SIZE);
+       int err = 0;
+
+       err = arch_mmu_cell_init(&root_cell);
+       if (err)
+               return err;
+
+       err = arch_map_device(UART_BASE_PHYS, UART_BASE_VIRT, PAGE_SIZE);
+
+       return err;
 }
 
 int arch_cpu_init(struct per_cpu *cpu_data)
 {
        int err = 0;
+       unsigned long hcr = HCR_VM_BIT;
 
        /*
         * Copy the registers to restore from the linux stack here, because we
@@ -35,6 +46,8 @@ int arch_cpu_init(struct per_cpu *cpu_data)
                        * sizeof(unsigned long));
 
        err = switch_exception_level(cpu_data);
+       if (err)
+               return err;
 
        /*
         * Save pointer in the thread local storage
@@ -43,6 +56,11 @@ int arch_cpu_init(struct per_cpu *cpu_data)
         */
        arm_write_sysreg(TPIDR_EL2, cpu_data);
 
+       /* Setup guest traps */
+       arm_write_sysreg(HCR, hcr);
+
+       err = arch_mmu_cpu_cell_init(cpu_data);
+
        return err;
 }
 
@@ -64,10 +82,6 @@ void arch_cpu_restore(struct per_cpu *cpu_data)
 }
 
 // catch missing symbols
-#include <jailhouse/printk.h>
-#include <jailhouse/processor.h>
-#include <jailhouse/control.h>
-#include <jailhouse/string.h>
 void arch_suspend_cpu(unsigned int cpu_id) {}
 void arch_resume_cpu(unsigned int cpu_id) {}
 void arch_reset_cpu(unsigned int cpu_id) {}
@@ -75,18 +89,9 @@ void arch_park_cpu(unsigned int cpu_id) {}
 void arch_shutdown_cpu(unsigned int cpu_id) {}
 int arch_cell_create(struct cell *new_cell)
 { return -ENOSYS; }
-int arch_map_memory_region(struct cell *cell,
-                          const struct jailhouse_memory *mem)
-{ return -ENOSYS; }
-int arch_unmap_memory_region(struct cell *cell,
-                            const struct jailhouse_memory *mem)
-{ return -ENOSYS; }
 void arch_flush_cell_vcpu_caches(struct cell *cell) {}
 void arch_cell_destroy(struct cell *new_cell) {}
 void arch_config_commit(struct cell *cell_added_removed) {}
 void arch_shutdown(void) {}
-unsigned long arch_paging_gphys2phys(struct per_cpu *cpu_data,
-                                    unsigned long gphys, unsigned long flags)
-{ return INVALID_PHYS_ADDR; }
 void arch_panic_stop(void) {__builtin_unreachable();}
 void arch_panic_park(void) {}