1f4f1110eSRichard Henderson /* 2f4f1110eSRichard Henderson * x86 MPX helpers 3f4f1110eSRichard Henderson * 4f4f1110eSRichard Henderson * Copyright (c) 2015 Red Hat, Inc. 5f4f1110eSRichard Henderson * 6f4f1110eSRichard Henderson * This library is free software; you can redistribute it and/or 7f4f1110eSRichard Henderson * modify it under the terms of the GNU Lesser General Public 8f4f1110eSRichard Henderson * License as published by the Free Software Foundation; either 9d9ff33adSChetan Pant * version 2.1 of the License, or (at your option) any later version. 10f4f1110eSRichard Henderson * 11f4f1110eSRichard Henderson * This library is distributed in the hope that it will be useful, 12f4f1110eSRichard Henderson * but WITHOUT ANY WARRANTY; without even the implied warranty of 13f4f1110eSRichard Henderson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14f4f1110eSRichard Henderson * Lesser General Public License for more details. 15f4f1110eSRichard Henderson * 16f4f1110eSRichard Henderson * You should have received a copy of the GNU Lesser General Public 17f4f1110eSRichard Henderson * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18f4f1110eSRichard Henderson */ 19f4f1110eSRichard Henderson 2030456d5bSPeter Maydell #include "qemu/osdep.h" 21f4f1110eSRichard Henderson #include "cpu.h" 22f4f1110eSRichard Henderson #include "exec/helper-proto.h" 23f4f1110eSRichard Henderson #include "exec/cpu_ldst.h" 2463c91552SPaolo Bonzini #include "exec/exec-all.h" 25*ed69e831SClaudio Fontana #include "helper-tcg.h" 26f4f1110eSRichard Henderson 27f4f1110eSRichard Henderson 28523e28d7SRichard Henderson void helper_bndck(CPUX86State *env, uint32_t fail) 29523e28d7SRichard Henderson { 30523e28d7SRichard Henderson if (unlikely(fail)) { 31523e28d7SRichard Henderson env->bndcs_regs.sts = 1; 32523e28d7SRichard Henderson raise_exception_ra(env, EXCP05_BOUND, GETPC()); 33523e28d7SRichard Henderson } 34523e28d7SRichard Henderson } 35bdd87b3bSRichard Henderson 36bdd87b3bSRichard Henderson static uint64_t lookup_bte64(CPUX86State *env, uint64_t base, uintptr_t ra) 37bdd87b3bSRichard Henderson { 38bdd87b3bSRichard Henderson uint64_t bndcsr, bde, bt; 39bdd87b3bSRichard Henderson 40bdd87b3bSRichard Henderson if ((env->hflags & HF_CPL_MASK) == 3) { 41bdd87b3bSRichard Henderson bndcsr = env->bndcs_regs.cfgu; 42bdd87b3bSRichard Henderson } else { 43bdd87b3bSRichard Henderson bndcsr = env->msr_bndcfgs; 44bdd87b3bSRichard Henderson } 45bdd87b3bSRichard Henderson 46bdd87b3bSRichard Henderson bde = (extract64(base, 20, 28) << 3) + (extract64(bndcsr, 20, 44) << 12); 47bdd87b3bSRichard Henderson bt = cpu_ldq_data_ra(env, bde, ra); 48bdd87b3bSRichard Henderson if ((bt & 1) == 0) { 49bdd87b3bSRichard Henderson env->bndcs_regs.sts = bde | 2; 50bdd87b3bSRichard Henderson raise_exception_ra(env, EXCP05_BOUND, ra); 51bdd87b3bSRichard Henderson } 52bdd87b3bSRichard Henderson 53bdd87b3bSRichard Henderson return (extract64(base, 3, 17) << 5) + (bt & ~7); 54bdd87b3bSRichard Henderson } 55bdd87b3bSRichard Henderson 56bdd87b3bSRichard Henderson static uint32_t lookup_bte32(CPUX86State *env, uint32_t base, uintptr_t ra) 57bdd87b3bSRichard Henderson { 58bdd87b3bSRichard Henderson uint32_t bndcsr, bde, bt; 59bdd87b3bSRichard Henderson 60bdd87b3bSRichard Henderson if ((env->hflags & HF_CPL_MASK) == 3) { 61bdd87b3bSRichard Henderson bndcsr = env->bndcs_regs.cfgu; 62bdd87b3bSRichard Henderson } else { 63bdd87b3bSRichard Henderson bndcsr = env->msr_bndcfgs; 64bdd87b3bSRichard Henderson } 65bdd87b3bSRichard Henderson 66bdd87b3bSRichard Henderson bde = (extract32(base, 12, 20) << 2) + (bndcsr & TARGET_PAGE_MASK); 67bdd87b3bSRichard Henderson bt = cpu_ldl_data_ra(env, bde, ra); 68bdd87b3bSRichard Henderson if ((bt & 1) == 0) { 69bdd87b3bSRichard Henderson env->bndcs_regs.sts = bde | 2; 70bdd87b3bSRichard Henderson raise_exception_ra(env, EXCP05_BOUND, ra); 71bdd87b3bSRichard Henderson } 72bdd87b3bSRichard Henderson 73bdd87b3bSRichard Henderson return (extract32(base, 2, 10) << 4) + (bt & ~3); 74bdd87b3bSRichard Henderson } 75bdd87b3bSRichard Henderson 76bdd87b3bSRichard Henderson uint64_t helper_bndldx64(CPUX86State *env, target_ulong base, target_ulong ptr) 77bdd87b3bSRichard Henderson { 78bdd87b3bSRichard Henderson uintptr_t ra = GETPC(); 79bdd87b3bSRichard Henderson uint64_t bte, lb, ub, pt; 80bdd87b3bSRichard Henderson 81bdd87b3bSRichard Henderson bte = lookup_bte64(env, base, ra); 82bdd87b3bSRichard Henderson lb = cpu_ldq_data_ra(env, bte, ra); 83bdd87b3bSRichard Henderson ub = cpu_ldq_data_ra(env, bte + 8, ra); 84bdd87b3bSRichard Henderson pt = cpu_ldq_data_ra(env, bte + 16, ra); 85bdd87b3bSRichard Henderson 86bdd87b3bSRichard Henderson if (pt != ptr) { 87bdd87b3bSRichard Henderson lb = ub = 0; 88bdd87b3bSRichard Henderson } 89bdd87b3bSRichard Henderson env->mmx_t0.MMX_Q(0) = ub; 90bdd87b3bSRichard Henderson return lb; 91bdd87b3bSRichard Henderson } 92bdd87b3bSRichard Henderson 93bdd87b3bSRichard Henderson uint64_t helper_bndldx32(CPUX86State *env, target_ulong base, target_ulong ptr) 94bdd87b3bSRichard Henderson { 95bdd87b3bSRichard Henderson uintptr_t ra = GETPC(); 96bdd87b3bSRichard Henderson uint32_t bte, lb, ub, pt; 97bdd87b3bSRichard Henderson 98bdd87b3bSRichard Henderson bte = lookup_bte32(env, base, ra); 99bdd87b3bSRichard Henderson lb = cpu_ldl_data_ra(env, bte, ra); 100bdd87b3bSRichard Henderson ub = cpu_ldl_data_ra(env, bte + 4, ra); 101bdd87b3bSRichard Henderson pt = cpu_ldl_data_ra(env, bte + 8, ra); 102bdd87b3bSRichard Henderson 103bdd87b3bSRichard Henderson if (pt != ptr) { 104bdd87b3bSRichard Henderson lb = ub = 0; 105bdd87b3bSRichard Henderson } 106bdd87b3bSRichard Henderson return ((uint64_t)ub << 32) | lb; 107bdd87b3bSRichard Henderson } 108bdd87b3bSRichard Henderson 109bdd87b3bSRichard Henderson void helper_bndstx64(CPUX86State *env, target_ulong base, target_ulong ptr, 110bdd87b3bSRichard Henderson uint64_t lb, uint64_t ub) 111bdd87b3bSRichard Henderson { 112bdd87b3bSRichard Henderson uintptr_t ra = GETPC(); 113bdd87b3bSRichard Henderson uint64_t bte; 114bdd87b3bSRichard Henderson 115bdd87b3bSRichard Henderson bte = lookup_bte64(env, base, ra); 116bdd87b3bSRichard Henderson cpu_stq_data_ra(env, bte, lb, ra); 117bdd87b3bSRichard Henderson cpu_stq_data_ra(env, bte + 8, ub, ra); 118bdd87b3bSRichard Henderson cpu_stq_data_ra(env, bte + 16, ptr, ra); 119bdd87b3bSRichard Henderson } 120bdd87b3bSRichard Henderson 121bdd87b3bSRichard Henderson void helper_bndstx32(CPUX86State *env, target_ulong base, target_ulong ptr, 122bdd87b3bSRichard Henderson uint64_t lb, uint64_t ub) 123bdd87b3bSRichard Henderson { 124bdd87b3bSRichard Henderson uintptr_t ra = GETPC(); 125bdd87b3bSRichard Henderson uint32_t bte; 126bdd87b3bSRichard Henderson 127bdd87b3bSRichard Henderson bte = lookup_bte32(env, base, ra); 128bdd87b3bSRichard Henderson cpu_stl_data_ra(env, bte, lb, ra); 129bdd87b3bSRichard Henderson cpu_stl_data_ra(env, bte + 4, ub, ra); 130bdd87b3bSRichard Henderson cpu_stl_data_ra(env, bte + 8, ptr, ra); 131bdd87b3bSRichard Henderson } 1327d117ce8SRichard Henderson 1337d117ce8SRichard Henderson void helper_bnd_jmp(CPUX86State *env) 1347d117ce8SRichard Henderson { 1357d117ce8SRichard Henderson if (!(env->hflags2 & HF2_MPX_PR_MASK)) { 1367d117ce8SRichard Henderson memset(env->bnd_regs, 0, sizeof(env->bnd_regs)); 1377d117ce8SRichard Henderson env->hflags &= ~HF_MPX_IU_MASK; 1387d117ce8SRichard Henderson } 1397d117ce8SRichard Henderson } 140