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
#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;
extern struct cell root_cell;
+#endif /* !__ASSEMBLY__ */
#endif /* !_JAILHOUSE_ASM_CELL_H */
--- /dev/null
+/*
+ * 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 */
#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))
#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
#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)
--- /dev/null
+/*
+ * 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;
+}
* 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
* sizeof(unsigned long));
err = switch_exception_level(cpu_data);
+ if (err)
+ return err;
/*
* Save pointer in the thread local storage
*/
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;
}
}
// 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) {}
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) {}