From owner-svn-soc-all@freebsd.org Wed Jun 24 17:31:22 2015 Return-Path: Delivered-To: svn-soc-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 6EDA9915B33 for ; Wed, 24 Jun 2015 17:31:22 +0000 (UTC) (envelope-from mihai@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 5E1B71E3B for ; Wed, 24 Jun 2015 17:31:22 +0000 (UTC) (envelope-from mihai@FreeBSD.org) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.9/8.14.9) with ESMTP id t5OHVMLt028991 for ; Wed, 24 Jun 2015 17:31:22 GMT (envelope-from mihai@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.9/8.14.9/Submit) id t5OHVJoU028966 for svn-soc-all@FreeBSD.org; Wed, 24 Jun 2015 17:31:19 GMT (envelope-from mihai@FreeBSD.org) Date: Wed, 24 Jun 2015 17:31:19 GMT Message-Id: <201506241731.t5OHVJoU028966@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to mihai@FreeBSD.org using -f From: mihai@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r287542 - in soc2015/mihai/bhyve-on-arm-head/sys: arm/vmm modules/vmm-arm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 Jun 2015 17:31:22 -0000 Author: mihai Date: Wed Jun 24 17:31:19 2015 New Revision: 287542 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=287542 Log: soc2015: mihai: bhyve-on-arm-head: sys: arm: vmm: add support for create HYP mappings and initialization code Added: soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/arm.h soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/init.S soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/mmu.c soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/mmu.h Modified: soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/arm.c soc2015/mihai/bhyve-on-arm-head/sys/modules/vmm-arm/Makefile Modified: soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/arm.c ============================================================================== --- soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/arm.c Wed Jun 24 17:17:53 2015 (r287541) +++ soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/arm.c Wed Jun 24 17:31:19 2015 (r287542) @@ -1,12 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "mmu.h" +#include "arm.h" + +static MALLOC_DEFINE(M_HYP, "ARM VMM HYP", "ARM VMM HYP"); + +lpae_pd_entry_t hyp_l1pd[2 * LPAE_L1_ENTRIES]; +extern void _hypervisor_stub_trap(void *vect_addr); +char *stack = NULL; + static int arm_init(int ipinum) { + char *stack_top, *hyp_code; + + stack = malloc(PAGE_SIZE, M_HYP); + stack_top = stack + PAGE_SIZE; + + lpae_vmmmap_set(NULL, stack, ptophys(stack), PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE); + + /* Allocate a PAGE for the HYP code to be sure it's PAGE_SIZE aligned and doesn't cross a page boundary */ + hyp_code = malloc(PAGE_SIZE, M_HYP); + memcpy(hyp_code, _hyp_code_start, _hyp_code_stop - _hyp_code_start); + + /* Create two mappings: + * - one identity - VA == PA + * - one normal mappings to HYP pagetable */ + lpae_vmmmap_set(NULL, hyp_code, ptophys(hyp_code), PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE); + lpae_vmmmap_set(NULL, ptophys(hyp_code), ptophys(hyp_code), PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE); + + vmm_call_hyp(NULL, stack_top, &hyp_l1pd[0], &hyp_l1pd[0]); return 0; } static void -arm_vmcleanup(void *arg) +arm_cleanup(void *arg) { + lpae_vmcleanup(NULL); } static void Added: soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/arm.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/arm.h Wed Jun 24 17:31:19 2015 (r287542) @@ -0,0 +1,9 @@ +#include "mmu.h" + +struct hyp { + lpae_pd_entry_t l1pd[2 * LPAE_L1_ENTRIES]; + struct vm *vm; +}; + +uint64_t vmm_call_hyp(void *hyp_func_addr, ...); + Added: soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/init.S ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/init.S Wed Jun 24 17:31:19 2015 (r287542) @@ -0,0 +1,134 @@ +#include "assym.s" +#include +#include +#include +#include +#include +#include + +#define SYS_WRITE0 4 + +.text + .globl _hyp_code_start + .globl _hyp_code_end + .globl _hyp_vector + .globl _init_hyp_vector + +_hyp_code_start: + +__semi_call: + svc 0x123456 + mov pc, lr + +ASENTRY_NP(kvm_call_hyp) + hvc #0 + bx lr +END(kvm_call_hyp) + + .align 5 +_init_hyp_vector: + .word 0 /* Reset */ + .word 0 /* undev */ + .word 0 /* SVC */ + .word 0 /* PABT */ + .word 0 /* DABT */ + b hyp_init_hvc /* HYP-Mode */ + .word 0 /* FIQ */ + .word 0 /* IRQ */ + +hyp_init_hvc: + mov sp, r1 /* r1 contains the stack pointer */ + + /* Find the offset between the two vectors */ + adr r0, _init_hyp_vector + adr r1, _hyp_vector + sub r1, r1, r0 + + mrc p15, 4, r0, c12, c0, 0 @ get current HVBAR + add r0, r0, r1 @ find the address of the _hyp_vector + mcr p15, 4, r0, c12, c0, 0 @ set HVBAR to the new vector + + mcrr p15, 4, r2, r3, c2 @ set the HTTBR (r2 is the low word, r3 is the low word) + isb + + @ Flush the TLB of this page + adr r1, _hyp_code_start + mcr p15, 4, r0, c8, c7, 0 @ TLBIALLH + dsb ish + + eret + + .align 5 +_hyp_vector: + b hyp_reset /* Reset */ + b hyp_undef /* undef */ + b hyp_svc /* SVC */ + b hyp_pabt /* PABT */ + b hyp_dabt /* DABT */ + b hyp_hvc /* HYP-Mode */ + b hyp_fiq /* FIQ */ + b hyp_irq /* IRQ */ + + .align +hyp_reset: + b loop + + .align +hyp_undef: + mov r0, #SYS_WRITE0 + adr r1, und_die_str + bl __semi_call + mrs r0, ELR_hyp + b loop + + .align +hyp_svc: + mov r0, #SYS_WRITE0 + adr r1, svc_die_str + bl __semi_call + mrs r0, ELR_hyp + b loop + .align + +hyp_pabt: + mov r0, #SYS_WRITE0 + adr r1, pabt_die_str + bl __semi_call + mrs r0, ELR_hyp + mrc p15, 4, r1, c5, c2, 0 @ HSR (syndrome register) + mrc p15, 4, r2, c6, c0, 2 @ HIFAR (hyp instruction fault address) + b loop + + .align +hyp_dabt: + mov r0, #SYS_WRITE0 + adr r1, dabt_die_str + bl __semi_call + mrs r0, ELR_hyp + mrc p15, 4, r1, c5, c2, 0 @ HSR (syndrome register) + mrc p15, 4, r2, c6, c0, 0 @ HDFAR (hyp data fault address) + b loop + + .align +hyp_hvc: + + .align +hyp_fiq: + b loop + .align +hyp_irq: + b loop + .align +loop: + b loop + +und_die_str: + .ascii "unexpected undefined exception in Hyp mode at r0: %#08x\n" +pabt_die_str: + .ascii "unexpected prefetch abort in Hyp mode at r0: %#08x\n" +dabt_die_str: + .ascii "unexpected data abort in Hyp mode at r0: %#08x\n" +svc_die_str: + .ascii "unexpected HVC/SVC trap in Hyp mode at r0: %#08x\n" + +_hyp_code_end: Added: soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/mmu.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/mmu.c Wed Jun 24 17:31:19 2015 (r287542) @@ -0,0 +1,191 @@ +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include "mmu.h" +#include "arm.h" + +MALLOC_DECLARE(M_HYP); +extern lpae_pd_entry_t hyp_l1pd[]; +/* + * create_lpae_mapping + * - l1pd - the level 1 address of the PD (NULL for the HYP mode PD) + * - virt_start - a 32 bit virtual address to be mapped + * - phys_start - a 64 bit physical address to map to + * - len - the desired length mapping, but it will be truncated to the virt_start + * alignment + * - prot - the FreeBSD mapping permissions + * - returns the actual length of the mapping + * + * An l1pd or l2pd will have a size of 8K (2 * LPAE_Lx_ENTRIES * sizeof(lpae_pd_entry_t)). + * The first 4K will include the bits for the MMU (physical addresses and bit permissions) + * and the second 4K will be a mirror of the first one but will include the virtual + * addresses of allocated page tables needed for walking and clean-up. + * + */ +static int create_lpae_mapping(lpae_pd_entry_t *l1pd, + lpae_vm_vaddr_t virt_start, + lpae_vm_paddr_t phys_start, + size_t len, + vm_prot_t prot) +{ + lpae_pd_entry_t *l2pd, *l3pd, *l1pd_shadow, *l2pd_shadow, *pd; + int l1_index, l2_index, l3_index; + int mapped_size = 0; + bool is_hyp_pd = false; + + if (l1pd == NULL) { + l1pd = &hyp_l1pd[0]; + is_hyp_pd = true; + } + + l1_index = (virt_start >> LPAE_L1_SHIFT) & LPAE_L1_INDEX_MASK; + l2_index = (virt_start >> LPAE_L2_SHIFT) & LPAE_L2_INDEX_MASK; + l3_index = (virt_start >> LPAE_L3_SHIFT) & LPAE_L3_INDEX_MASK; + + if ((virt_start & LPAE_L1_B_ADDR_MASK) == virt_start) { + if (len > LPAE_L1_SIZE) { + mapped_size = LPAE_L1_SIZE; + } + } + if(!mapped_size && (virt_start & LPAE_L2_B_ADDR_MASK) == virt_start) { + if (len > LPAE_L2_SIZE) { + mapped_size = LPAE_L2_SIZE; + } + } + if(!mapped_size) { + mapped_size = LPAE_L3_SIZE; + } + + if (mapped_size == LPAE_L1_SIZE) { + pd = &l1pd[l1_index]; + /* See if this PD is a link and fallback to the next level */ + if ((*pd & LPAE_TYPE_LINK) == LPAE_TYPE_LINK) + mapped_size = LPAE_L2_SIZE; + else + goto set_prot; + } + + l1pd_shadow = &l1pd[LPAE_L1_ENTRIES]; + + if (l1pd[l1_index] == 0) { + l2pd = malloc(2 * PAGE_SIZE, M_HYP, M_WAITOK | M_ZERO); + l2pd_shadow = &l2pd[LPAE_L2_ENTRIES]; + + l1pd[l1_index] = (lpae_pd_entry_t) vtophys(l2pd); + l1pd[l1_index] |= LPAE_TYPE_LINK; + + l1pd_shadow[l1_index] = (lpae_pd_entry_t) l2pd; + + } else { + l2pd = (lpae_pd_entry_t *) (l1pd_shadow[l1_index]); + l2pd_shadow = &l2pd[LPAE_L2_ENTRIES]; + } + + if (mapped_size == LPAE_L2_SIZE) { + pd = &l2pd[l2_index]; + /* See if this PD is a link and fallback to the next level */ + if ((*pd & LPAE_TYPE_LINK) == LPAE_TYPE_LINK) + mapped_size = LPAE_L3_SIZE; + else + goto set_prot; + } + + if (l2pd[l2_index] == 0) { + l3pd = malloc(PAGE_SIZE, M_HYP, M_WAITOK | M_ZERO); + l2pd[l2_index] = vtophys(l3pd); + l2pd[l2_index] |= LPAE_TYPE_LINK; + + l2pd_shadow[l2_index] = (lpae_pd_entry_t) l3pd; + } else { + l3pd = (lpae_pd_entry_t *) (l2pd_shadow[l2_index]); + } + + pd = &l3pd[l3_index]; + +set_prot: + if (prot != VM_PROT_NONE) { + *pd = phys_start; + *pd |= LPAE_TYPE_BLOCK; + + if (is_hyp_pd) { /* PL-2 stage-1 table */ + if (prot & (VM_PROT_READ | VM_PROT_WRITE)) + *pd |= LPAE_AP_HYP_RW; + else /* Map read-only*/ + *pd |= LPAE_AP_HYP_RDONLY; + } else { /* VM stage-2 page table */ + if (prot & VM_PROT_READ) + *pd |= LPAE_HAP_READ; + if (prot & VM_PROT_WRITE) + *pd |= LPAE_HAP_WRITE; + } + } else { + *pd = 0; + } + + return mapped_size; +} + +int lpae_vmmmap_set(void *arg, + lpae_vm_vaddr_t virt_start, + lpae_vm_paddr_t phys_start, + size_t len, + vm_prot_t prot) +{ + size_t n; + struct hyp *vm_hyp; + lpae_pd_entry_t *l1pd = NULL; + vm_hyp = arg; + if (arg) + l1pd = &vm_hyp->l1pd[0]; + + while (len > 0) { + n = create_lpae_mapping(l1pd, virt_start, phys_start, len, prot); + len -= n; + virt_start += n; + phys_start += n; + } + return (0); +} + +void lpae_vmcleanup(void *arg) +{ + int i, j; + struct hyp *vm_hyp; + lpae_pd_entry_t *l1pd, *l1pd_shadow, *l2pd, *l2pd_shadow; + + vm_hyp = arg; + + if (arg) + l1pd = &vm_hyp->l1pd[0]; + else + l1pd = &hyp_l1pd[0]; + + l1pd_shadow = &l1pd[LPAE_L1_ENTRIES]; + + for (i = 0; i < LPAE_L1_ENTRIES; i++) { + if(l1pd_shadow[i]) { + l2pd = (lpae_pd_entry_t *) l1pd_shadow[i]; + l2pd_shadow = &l2pd[LPAE_L2_ENTRIES]; + for (j = 0; j < LPAE_L2_ENTRIES; j++) { + if (l2pd_shadow[j]) { + free((void *) l2pd_shadow[j], M_HYP); + } + } + free((void *) l1pd_shadow[i], M_HYP); + } + } +} Added: soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/mmu.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/mmu.h Wed Jun 24 17:31:19 2015 (r287542) @@ -0,0 +1,54 @@ +#ifndef _VMM_MMU_H_ +#define _VMM_MMU_H_ + +typedef uint64_t lpae_pd_entry_t; /* LPAE page directory entry */ +typedef uint64_t lpae_pt_entry_t; /* LPAE page table entry */ + +typedef uint64_t lpae_vm_paddr_t; /* LPAE VM paddr */ +typedef uint32_t lpae_vm_vaddr_t; /* LPAE VM vaddr */ + +int lpae_vmmmap_set(void *arg, + lpae_vm_vaddr_t virt_start, + lpae_vm_paddr_t phys_start, + size_t len, + vm_prot_t prot); + +void lpae_vmcleanup(void *arg); + +#define LPAE_NLEVELS 3 + +#define LPAE_L1_TABLE_SIZE 0x1000 /* 4K */ +#define LPAE_L1_ENTRIES (LPAE_L1_TABLE_SIZE / 8) /* 512 */ + +#define LPAE_L2_TABLE_SIZE 0x1000 /* 4K */ +#define LPAE_L2_ENTRIES (LPAE_L2_TABLE_SIZE / 8) /* 512 */ + +#define LPAE_L3_TABLE_SIZE 0x1000 /* 4K */ +#define LPAE_L3_ENTRIES (LPAE_L3_TABLE_SIZE / 8) /* 512 */ + +#define LPAE_L1_SHIFT 30 +#define LPAE_L1_SIZE (1 << 30) +#define LPAE_L1_INDEX_MASK 0x3 +#define LPAE_L1_T_ADDR_MASK ((uint64_t)0xFFFFFFF000) /* phys address of L2 Table */ +#define LPAE_L1_B_ADDR_MASK ((uint64_t)0xFFC0000000) /* phys address of Phys Block */ + +#define LPAE_L2_SHIFT 21 +#define LPAE_L2_SIZE (1 << 21) +#define LPAE_L2_INDEX_MASK 0x1FF +#define LPAE_L2_T_ADDR_MASK ((uint64_t)0xFFFFFFF000)/* phys address of L3 Table */ +#define LPAE_L2_B_ADDR_MASK ((uint64_t)0xFFFFE00000)/* phys address of Phys Block */ + +#define LPAE_L3_SHIFT 12 +#define LPAE_L3_SIZE (1 << 12) +#define LPAE_L3_INDEX_MASK 0x1FF + +#define LPAE_TYPE_LINK 0x03 +#define LPAE_TYPE_BLOCK 0x01 +#define LPAE_TYPE_MASK 0x03 /* mask of type bits */ + +#define LPAE_AP_HYP_RW (0x01 << 6) /* RW permissions for PL-2 stage 1*/ +#define LPAE_AP_HYP_RDONLY (0x03 << 6) /* RD permissions for PL-2 stage 1 */ + +#define LPAE_HAP_READ (0x01 << 6) /* read permissions for stage 2 */ +#define LPAE_HAP_WRITE (0x02 << 6) /* write permissions for stage 2*/ +#endif Modified: soc2015/mihai/bhyve-on-arm-head/sys/modules/vmm-arm/Makefile ============================================================================== --- soc2015/mihai/bhyve-on-arm-head/sys/modules/vmm-arm/Makefile Wed Jun 24 17:17:53 2015 (r287541) +++ soc2015/mihai/bhyve-on-arm-head/sys/modules/vmm-arm/Makefile Wed Jun 24 17:31:19 2015 (r287542) @@ -9,7 +9,9 @@ .PATH: ${.CURDIR}/../../arm/vmm SRCS+= vmm.c \ vmm_dev.c \ - vmm_stat.c + mmu.c \ + vmm_stat.c \ + init.S .include