From owner-svn-soc-all@freebsd.org Thu Jul 23 17:52:57 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 D28BF9A9CC6 for ; Thu, 23 Jul 2015 17:52:57 +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 C227512BC for ; Thu, 23 Jul 2015 17:52:57 +0000 (UTC) (envelope-from mihai@FreeBSD.org) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.15.2/8.15.2) with ESMTP id t6NHqvmJ035002 for ; Thu, 23 Jul 2015 17:52:57 GMT (envelope-from mihai@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.15.2/8.15.2/Submit) id t6NHqtdn034983 for svn-soc-all@FreeBSD.org; Thu, 23 Jul 2015 17:52:55 GMT (envelope-from mihai@FreeBSD.org) Date: Thu, 23 Jul 2015 17:52:55 GMT Message-Id: <201507231752.t6NHqtdn034983@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: r288695 - in soc2015/mihai/bhyve-on-arm-head/sys/arm: include vmm 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: Thu, 23 Jul 2015 17:52:58 -0000 Author: mihai Date: Thu Jul 23 17:52:55 2015 New Revision: 288695 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=288695 Log: soc2015: mihai: bhyve: sys: arm: arm.c: handle stub exception and implement emulation for MMIO accesses Modified: soc2015/mihai/bhyve-on-arm-head/sys/arm/include/vmm.h soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/arm.c soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/hyp.h soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/mmu.h soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/vmm.c Modified: soc2015/mihai/bhyve-on-arm-head/sys/arm/include/vmm.h ============================================================================== --- soc2015/mihai/bhyve-on-arm-head/sys/arm/include/vmm.h Thu Jul 23 15:50:39 2015 (r288694) +++ soc2015/mihai/bhyve-on-arm-head/sys/arm/include/vmm.h Thu Jul 23 17:52:55 2015 (r288695) @@ -32,6 +32,21 @@ VM_REG_GUEST_LR, VM_REG_GUEST_PC, VM_REG_GUEST_CPSR, + VM_REG_GUEST_SP_SVC, + VM_REG_GUEST_LR_SVC, + VM_REG_GUEST_SP_ABT, + VM_REG_GUEST_LR_ABT, + VM_REG_GUEST_SP_UND, + VM_REG_GUEST_LR_UND, + VM_REG_GUEST_SP_IRQ, + VM_REG_GUEST_LR_IRQ, + VM_REG_GUEST_R8_FIQ, + VM_REG_GUEST_R9_FIQ, + VM_REG_GUEST_R10_FIQ, + VM_REG_GUEST_R11_FIQ, + VM_REG_GUEST_R12_FIQ, + VM_REG_GUEST_SP_FIQ, + VM_REG_GUEST_LR_FIQ, VM_REG_LAST }; @@ -229,6 +244,11 @@ #define VM_MAXCPU 16 /* maximum virtual cpus */ +struct vie { + uint8_t access_size:4, sign_extend:1, dir:1, unused:2; + enum vm_reg_name reg; +}; + /* * Identifiers for optional vmm capabilities */ @@ -240,16 +260,8 @@ VM_CAP_MAX }; enum vm_exitcode { - VM_EXITCODE_INOUT, - VM_EXITCODE_VMX, VM_EXITCODE_BOGUS, - VM_EXITCODE_RDMSR, - VM_EXITCODE_WRMSR, - VM_EXITCODE_HLT, - VM_EXITCODE_MTRAP, - VM_EXITCODE_PAUSE, - VM_EXITCODE_PAGING, - VM_EXITCODE_SPINUP_AP, + VM_EXITCODE_INST_EMUL, VM_EXITCODE_HYP, VM_EXITCODE_MAX }; @@ -271,7 +283,7 @@ struct vm_exit { enum vm_exitcode exitcode; - int inst_length; /* 0 means unknown */ + int inst_length; uint64_t pc; union { /* @@ -283,6 +295,7 @@ uint32_t hdfar; /* VA at a Data Abort exception */ uint32_t hifar; /* VA at a Prefetch Abort exception */ uint32_t hpfar; /* IPA[39:12] at aborts on stage 2 address translations */ + uint32_t mode; } hyp; struct { @@ -291,7 +304,7 @@ } paging; struct { uint64_t gpa; - uint64_t gla; + struct vie vie; } inst_emul; /* * VMX specific payload. Used when there is no "better" Modified: soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/arm.c ============================================================================== --- soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/arm.c Thu Jul 23 15:50:39 2015 (r288694) +++ soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/arm.c Thu Jul 23 17:52:55 2015 (r288695) @@ -214,6 +214,189 @@ return (hyp); } +static enum vm_reg_name +get_vm_reg_name(uint32_t reg_nr, uint32_t mode) +{ + switch(reg_nr) { + case 0: + return VM_REG_GUEST_R0; + case 1: + return VM_REG_GUEST_R1; + case 2: + return VM_REG_GUEST_R2; + case 3: + return VM_REG_GUEST_R3; + case 4: + return VM_REG_GUEST_R4; + case 5: + return VM_REG_GUEST_R5; + case 6: + return VM_REG_GUEST_R6; + case 7: + return VM_REG_GUEST_R7; + case 8: + if (mode == PSR_FIQ32_MODE) + return VM_REG_GUEST_R8_FIQ; + else + return VM_REG_GUEST_R8; + case 9: + if (mode == PSR_FIQ32_MODE) + return VM_REG_GUEST_R9_FIQ; + else + return VM_REG_GUEST_R9; + case 10: + if (mode == PSR_FIQ32_MODE) + return VM_REG_GUEST_R10_FIQ; + else + return VM_REG_GUEST_R10; + case 11: + if (mode == PSR_FIQ32_MODE) + return VM_REG_GUEST_R11_FIQ; + else + return VM_REG_GUEST_R11; + case 12: + if (mode == PSR_FIQ32_MODE) + return VM_REG_GUEST_R12_FIQ; + else + return VM_REG_GUEST_R12; + case 13: + if (mode == PSR_FIQ32_MODE) + return VM_REG_GUEST_SP_FIQ; + else if (mode == PSR_SVC32_MODE) + return VM_REG_GUEST_SP_SVC; + else if (mode == PSR_ABT32_MODE) + return VM_REG_GUEST_SP_ABT; + else if (mode == PSR_UND32_MODE) + return VM_REG_GUEST_SP_UND; + else if (mode == PSR_IRQ32_MODE) + return VM_REG_GUEST_SP_IRQ; + else + return VM_REG_GUEST_SP; + case 14: + if (mode == PSR_FIQ32_MODE) + return VM_REG_GUEST_LR_FIQ; + else if (mode == PSR_SVC32_MODE) + return VM_REG_GUEST_LR_SVC; + else if (mode == PSR_ABT32_MODE) + return VM_REG_GUEST_LR_ABT; + else if (mode == PSR_UND32_MODE) + return VM_REG_GUEST_LR_UND; + else if (mode == PSR_IRQ32_MODE) + return VM_REG_GUEST_LR_IRQ; + else + return VM_REG_GUEST_LR; + } + return VM_REG_LAST; +} + +static int hyp_handle_exception(struct vm_exit *vmexit) +{ + int handled; + int hsr_ec, hsr_il, hsr_iss; + + handled = UNHANDLED; + hsr_ec = HSR_EC(vmexit->u.hyp.hsr); + hsr_il = HSR_IL(vmexit->u.hyp.hsr); + hsr_iss = HSR_ISS(vmexit->u.hyp.hsr); + + switch(hsr_ec) { + case HSR_EC_UNKN: + printf("%s:%d Unknown exception\n",__func__, __LINE__); + break; + case HSR_EC_WFI_WFE: + printf("%s:%d WFI/WFE exception - unimplemented\n", + __func__, __LINE__); + break; + case HSR_EC_MCR_MRC_CP15: + printf("%s:%d MCR/MRC CP15 - unimplemented\n", + __func__, __LINE__); + break; + case HSR_EC_MCRR_MRRC_CP15: + printf("%s:%d MCRR/MRRC CP15 - unimplemented\n", + __func__, __LINE__); + break; + case HSR_EC_MCR_MRC_CP14: + printf("%s:%d MCR/MRC CP14 - unimplemented\n", + __func__, __LINE__); + break; + case HSR_EC_LDC_STC_CP14: + printf("%s:%d LDC/STC CP14 - unimplemented\n", + __func__, __LINE__); + break; + case HSR_EC_HCPTR_CP0_CP13: + printf("%s:%d MCR/MRC CP14 - unimplemented\n", + __func__, __LINE__); + break; + case HSR_EC_MRC_VMRS_CP10: + printf("%s:%d MCR/VMRS CP14 - unimplemented\n", + __func__, __LINE__); + break; + case HSR_EC_BXJ: + printf("%s:%d BXJ - unimplemented\n", + __func__, __LINE__); + break; + case HSR_EC_MRRC_CP14: + printf("%s:%d MRRC CP14 - unimplemented\n", + __func__, __LINE__); + break; + case HSR_EC_SVC: + panic("%s:%d SVC called from hyp-mode\n", + __func__, __LINE__); + break; + case HSR_EC_HVC: + printf("%s:%d HVC called from hyp-mode - unsupported\n", + __func__, __LINE__); + break; + case HSR_EC_SMC: + printf("%s:%d SMC called from hyp-mode - unsupported\n", + __func__, __LINE__); + break; + case HSR_EC_PABT: + printf("%s:%d PABT from guest at address %x - unimplemented\n", + __func__, __LINE__, vmexit->u.hyp.hifar); + break; + case HSR_EC_PABT_HYP: + printf("%s:%d PABT taken from HYP mode at %x with HSR: %x\n", + __func__, __LINE__, vmexit->u.hyp.hifar, vmexit->u.hyp.hsr); + break; + case HSR_EC_DABT: + if (HSR_ISS_ISV(hsr_iss)) { + if (LPAE_TRANSLATION_FAULT(HSR_ISS_DFSC(hsr_iss))) { + /* + * The page is not mapped and a possible MMIO access + * Build the instruction info and return to user to emulate + */ + vmexit->exitcode = VM_EXITCODE_INST_EMUL; + vmexit->u.inst_emul.gpa = vmexit->u.hyp.hdfar; + vmexit->u.inst_emul.vie.access_size = HSR_ISS_ACCESS_SIZE(HSR_ISS_SAS(hsr_iss)); + vmexit->u.inst_emul.vie.sign_extend = HSR_ISS_SSE(hsr_iss); + vmexit->u.inst_emul.vie.dir = HSR_ISS_WnR(hsr_iss); + vmexit->u.inst_emul.vie.reg = get_vm_reg_name(HSR_ISS_SRT(hsr_iss), + vmexit->u.hyp.mode); + printf("%s:%d gpa: %llx, as: %d, se: %d, dir: %d, reg: %d\n",__func__, __LINE__, + vmexit->u.inst_emul.gpa, vmexit->u.inst_emul.vie.access_size, vmexit->u.inst_emul.vie.sign_extend, + vmexit->u.inst_emul.vie.dir, vmexit->u.inst_emul.vie.reg); + + } else { + printf("%s:%d DABT from guest at address %x witho a stage-2 fault != translation\n", + __func__, __LINE__, vmexit->u.hyp.hdfar); + } + } else { + printf("%s:%d DABT from guest at address %x without a stage-2 fault translation\n", + __func__, __LINE__, vmexit->u.hyp.hdfar); + } + break; + case HSR_EC_DABT_HYP: + printf("%s:%d DABT taken from HYP mode at %x with HSR: %x\n", + __func__, __LINE__, vmexit->u.hyp.hdfar, vmexit->u.hyp.hsr); + break; + default: + printf("%s:%d Unknown HSR_EC code: %x\n",__func__, __LINE__, hsr_ec); + break; + } + return handled; +} + static int hyp_exit_process(struct hyp *hyp, int vcpu, struct vm_exit *vmexit) { @@ -237,8 +420,14 @@ case EXCEPTION_PABT: case EXCEPTION_DABT: case EXCEPTION_HVC: - printf("%s PABT/DABT/HYP unimplemented exception\n",__func__); + printf("%s PABT/DABT/HYP exception\n",__func__); + printf("%s HSR: %x, HIFAR: %x, HDFAR: %x, HPFAR: %x\n", __func__, + vmexit->u.hyp.hsr, vmexit->u.hyp.hifar, + vmexit->u.hyp.hdfar, vmexit->u.hyp.hpfar); + vmexit->exitcode = VM_EXITCODE_HYP; + handled = hyp_handle_exception(vmexit); + break; case EXCEPTION_FIQ: printf("%s FIQ unsupported exception\n",__func__); @@ -272,19 +461,26 @@ vm = hyp->vm; vmexit = vm_exitinfo(vm, vcpu); + hypctx->regs.r_pc = (uint32_t) pc; + do { handled = UNHANDLED; rc = vmm_call_hyp((void *)hyp_enter_guest, hypctx); - printf("%s rc: %d\n",__func__, rc); vmexit->pc = hypctx->regs.r_pc; - vmexit->inst_length = 4; /* TODO -> HSR[25] */ + vmexit->u.hyp.exception_nr = rc; vmexit->u.hyp.hsr = hypctx->exit_info.hsr; vmexit->u.hyp.hifar = hypctx->exit_info.hifar; vmexit->u.hyp.hdfar = hypctx->exit_info.hdfar; vmexit->u.hyp.hpfar = hypctx->exit_info.hpfar; + vmexit->u.hyp.mode = hypctx->regs.r_cpsr & PSR_MODE; + + if (HSR_IL(vmexit->u.hyp.hsr)) + vmexit->inst_length = 4; + else + vmexit->inst_length = 2; handled = hyp_exit_process(hyp, vcpu, vmexit); @@ -345,11 +541,42 @@ return (&hypctx->regs.r_pc); case VM_REG_GUEST_CPSR: return (&hypctx->regs.r_cpsr); + case VM_REG_GUEST_SP_SVC: + return (&hypctx->sp_svc); + case VM_REG_GUEST_LR_SVC: + return (&hypctx->lr_svc); + case VM_REG_GUEST_SP_ABT: + return (&hypctx->sp_abt); + case VM_REG_GUEST_LR_ABT: + return (&hypctx->lr_abt); + case VM_REG_GUEST_SP_UND: + return (&hypctx->sp_und); + case VM_REG_GUEST_LR_UND: + return (&hypctx->lr_und); + case VM_REG_GUEST_SP_IRQ: + return (&hypctx->sp_irq); + case VM_REG_GUEST_LR_IRQ: + return (&hypctx->lr_irq); + case VM_REG_GUEST_R8_FIQ: + return (&hypctx->r8_fiq); + case VM_REG_GUEST_R9_FIQ: + return (&hypctx->r9_fiq); + case VM_REG_GUEST_R10_FIQ: + return (&hypctx->r10_fiq); + case VM_REG_GUEST_R11_FIQ: + return (&hypctx->r11_fiq); + case VM_REG_GUEST_R12_FIQ: + return (&hypctx->r12_fiq); + case VM_REG_GUEST_SP_FIQ: + return (&hypctx->sp_fiq); + case VM_REG_GUEST_LR_FIQ: + return (&hypctx->lr_fiq); default: break; } return (NULL); } + static int arm_getreg(void *arg, int vcpu, int reg, uint64_t *retval) { Modified: soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/hyp.h ============================================================================== --- soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/hyp.h Thu Jul 23 15:50:39 2015 (r288694) +++ soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/hyp.h Thu Jul 23 17:52:55 2015 (r288695) @@ -11,8 +11,49 @@ #define EXCEPTION_FIQ 6 #define EXCEPTION_IRQ 7 + + #define HSR_EC_SHIFT 26 +#define HSR_IL_SHIFT 25 +#define HSR_IL_MASK (1 << HSR_IL_SHIFT) +#define HSR_ISS_MASK ((1 << 25) - 1) + +#define HSR_EC(x) (x >> HSR_EC_SHIFT) +#define HSR_IL(x) ((x & HSR_IL_MASK) >> HSR_IL_SHIFT) +#define HSR_ISS(x) (x & HSR_ISS_MASK) + +#define HSR_EC_UNKN 0x00 +#define HSR_EC_WFI_WFE 0x01 +#define HSR_EC_MCR_MRC_CP15 0x03 +#define HSR_EC_MCRR_MRRC_CP15 0x04 +#define HSR_EC_MCR_MRC_CP14 0x05 +#define HSR_EC_LDC_STC_CP14 0x06 +#define HSR_EC_HCPTR_CP0_CP13 0x07 +#define HSR_EC_MRC_VMRS_CP10 0x08 +#define HSR_EC_BXJ 0x0A +#define HSR_EC_MRRC_CP14 0x0C + +#define HSR_EC_SVC 0x11 #define HSR_EC_HVC 0x12 +#define HSR_EC_SMC 0x13 +#define HSR_EC_PABT 0x20 +#define HSR_EC_PABT_HYP 0x21 +#define HSR_EC_DABT 0x24 +#define HSR_EC_DABT_HYP 0x25 + +#define HSR_ISS_ISV(x) ((x >> 24) & 1) +#define HSR_ISS_SAS(x) ((x >> 22) & 3) +#define HSR_ISS_SSE(x) ((x >> 21) & 1) +#define HSR_ISS_SRT(x) ((x >> 16) & 0xf) +#define HSR_ISS_EA(x) ((x >> 9) & 1) +#define HSR_ISS_CM(x) ((x >> 8) & 1) +#define HSR_ISS_S1PTW(x) ((x >> 7) & 1) +#define HSR_ISS_WnR(x) ((x >> 6) & 1) +#define HSR_ISS_DFSC(x) ((x >> 0) & 0x3f) + +#define HSR_ISS_ACCESS_SIZE(x) ((x == 0) ? 1 : (x == 1) ? 2 : 4) + + #define VTTBR_VMID_SHIFT 16 #define VTTBR_VMID_MASK 0xff Modified: soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/mmu.h ============================================================================== --- soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/mmu.h Thu Jul 23 15:50:39 2015 (r288694) +++ soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/mmu.h Thu Jul 23 17:52:55 2015 (r288695) @@ -60,4 +60,9 @@ #define LPAE_AF (0x1 << 10) /* Access Flag */ +/* Table B3-24 Long-descriptor format FSR encodings */ +#define LPAE_TRANSLATION_FAULT(x) ((0b000111) & x) +#define LPAE_ACCESS_FLAG_FAULT(x) ((0b001011) & x) +#define LPAE_PERMISSION_FAULT(x) ((0b001111) & x) +#define LPAE_FAULT_LEVEL(x) (0x3 & x) #endif Modified: soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/vmm.c ============================================================================== --- soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/vmm.c Thu Jul 23 15:50:39 2015 (r288694) +++ soc2015/mihai/bhyve-on-arm-head/sys/arm/vmm/vmm.c Thu Jul 23 17:52:55 2015 (r288695) @@ -269,12 +269,15 @@ vm_run(struct vm *vm, struct vm_run *vmrun) { int error, vcpuid; + uint32_t pc; struct vcpu *vcpu; struct vm_exit *vme; bool retu; void *rptr = NULL, *sptr = NULL; vcpuid = vmrun->cpuid; + pc = vmrun->pc; + if (vcpuid < 0 || vcpuid >= VM_MAXCPU) return (EINVAL); @@ -284,12 +287,12 @@ vcpu = &vm->vcpu[vcpuid]; vme = &vcpu->exitinfo; - printf("%s vcpuid: %d, nextpc: %llx\n",__func__, vcpuid, vcpu->nextpc); + printf("%s vcpuid: %d, nextpc: %x\n",__func__, vcpuid, pc); restart: critical_enter(); - error = VMRUN(vm->cookie, vcpuid, vcpu->nextpc, NULL, rptr, sptr); + error = VMRUN(vm->cookie, vcpuid, pc, NULL, rptr, sptr); printf("%s VMRUN error: %d\n",__func__, error); @@ -297,6 +300,10 @@ if (error == 0) { switch (vme->exitcode) { + case VM_EXITCODE_INST_EMUL: + /* TODO there is no in-kernel emulation yet */ + retu = true; + break; default: retu = true; /* handled in userland */ break; @@ -305,10 +312,9 @@ if (error == 0 && retu == false) goto restart; - printf("%s before bhcopy\n",__func__); + /* copy the exit information */ bcopy(vme, &vmrun->vm_exit, sizeof(struct vm_exit)); - printf("%s after bhcopy\n",__func__); return (error); }