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" 25f4f1110eSRichard Henderson 26f4f1110eSRichard Henderson 27523e28d7SRichard Henderson void helper_bndck(CPUX86State *env, uint32_t fail) 28523e28d7SRichard Henderson { 29523e28d7SRichard Henderson if (unlikely(fail)) { 30523e28d7SRichard Henderson env->bndcs_regs.sts = 1; 31523e28d7SRichard Henderson raise_exception_ra(env, EXCP05_BOUND, GETPC()); 32523e28d7SRichard Henderson } 33523e28d7SRichard Henderson } 34bdd87b3bSRichard Henderson 35bdd87b3bSRichard Henderson static uint64_t lookup_bte64(CPUX86State *env, uint64_t base, uintptr_t ra) 36bdd87b3bSRichard Henderson { 37bdd87b3bSRichard Henderson uint64_t bndcsr, bde, bt; 38bdd87b3bSRichard Henderson 39bdd87b3bSRichard Henderson if ((env->hflags & HF_CPL_MASK) == 3) { 40bdd87b3bSRichard Henderson bndcsr = env->bndcs_regs.cfgu; 41bdd87b3bSRichard Henderson } else { 42bdd87b3bSRichard Henderson bndcsr = env->msr_bndcfgs; 43bdd87b3bSRichard Henderson } 44bdd87b3bSRichard Henderson 45bdd87b3bSRichard Henderson bde = (extract64(base, 20, 28) << 3) + (extract64(bndcsr, 20, 44) << 12); 46bdd87b3bSRichard Henderson bt = cpu_ldq_data_ra(env, bde, ra); 47bdd87b3bSRichard Henderson if ((bt & 1) == 0) { 48bdd87b3bSRichard Henderson env->bndcs_regs.sts = bde | 2; 49bdd87b3bSRichard Henderson raise_exception_ra(env, EXCP05_BOUND, ra); 50bdd87b3bSRichard Henderson } 51bdd87b3bSRichard Henderson 52bdd87b3bSRichard Henderson return (extract64(base, 3, 17) << 5) + (bt & ~7); 53bdd87b3bSRichard Henderson } 54bdd87b3bSRichard Henderson 55bdd87b3bSRichard Henderson static uint32_t lookup_bte32(CPUX86State *env, uint32_t base, uintptr_t ra) 56bdd87b3bSRichard Henderson { 57bdd87b3bSRichard Henderson uint32_t bndcsr, bde, bt; 58bdd87b3bSRichard Henderson 59bdd87b3bSRichard Henderson if ((env->hflags & HF_CPL_MASK) == 3) { 60bdd87b3bSRichard Henderson bndcsr = env->bndcs_regs.cfgu; 61bdd87b3bSRichard Henderson } else { 62bdd87b3bSRichard Henderson bndcsr = env->msr_bndcfgs; 63bdd87b3bSRichard Henderson } 64bdd87b3bSRichard Henderson 65bdd87b3bSRichard Henderson bde = (extract32(base, 12, 20) << 2) + (bndcsr & TARGET_PAGE_MASK); 66bdd87b3bSRichard Henderson bt = cpu_ldl_data_ra(env, bde, ra); 67bdd87b3bSRichard Henderson if ((bt & 1) == 0) { 68bdd87b3bSRichard Henderson env->bndcs_regs.sts = bde | 2; 69bdd87b3bSRichard Henderson raise_exception_ra(env, EXCP05_BOUND, ra); 70bdd87b3bSRichard Henderson } 71bdd87b3bSRichard Henderson 72bdd87b3bSRichard Henderson return (extract32(base, 2, 10) << 4) + (bt & ~3); 73bdd87b3bSRichard Henderson } 74bdd87b3bSRichard Henderson 75bdd87b3bSRichard Henderson uint64_t helper_bndldx64(CPUX86State *env, target_ulong base, target_ulong ptr) 76bdd87b3bSRichard Henderson { 77bdd87b3bSRichard Henderson uintptr_t ra = GETPC(); 78bdd87b3bSRichard Henderson uint64_t bte, lb, ub, pt; 79bdd87b3bSRichard Henderson 80bdd87b3bSRichard Henderson bte = lookup_bte64(env, base, ra); 81bdd87b3bSRichard Henderson lb = cpu_ldq_data_ra(env, bte, ra); 82bdd87b3bSRichard Henderson ub = cpu_ldq_data_ra(env, bte + 8, ra); 83bdd87b3bSRichard Henderson pt = cpu_ldq_data_ra(env, bte + 16, ra); 84bdd87b3bSRichard Henderson 85bdd87b3bSRichard Henderson if (pt != ptr) { 86bdd87b3bSRichard Henderson lb = ub = 0; 87bdd87b3bSRichard Henderson } 88bdd87b3bSRichard Henderson env->mmx_t0.MMX_Q(0) = ub; 89bdd87b3bSRichard Henderson return lb; 90bdd87b3bSRichard Henderson } 91bdd87b3bSRichard Henderson 92bdd87b3bSRichard Henderson uint64_t helper_bndldx32(CPUX86State *env, target_ulong base, target_ulong ptr) 93bdd87b3bSRichard Henderson { 94bdd87b3bSRichard Henderson uintptr_t ra = GETPC(); 95bdd87b3bSRichard Henderson uint32_t bte, lb, ub, pt; 96bdd87b3bSRichard Henderson 97bdd87b3bSRichard Henderson bte = lookup_bte32(env, base, ra); 98bdd87b3bSRichard Henderson lb = cpu_ldl_data_ra(env, bte, ra); 99bdd87b3bSRichard Henderson ub = cpu_ldl_data_ra(env, bte + 4, ra); 100bdd87b3bSRichard Henderson pt = cpu_ldl_data_ra(env, bte + 8, ra); 101bdd87b3bSRichard Henderson 102bdd87b3bSRichard Henderson if (pt != ptr) { 103bdd87b3bSRichard Henderson lb = ub = 0; 104bdd87b3bSRichard Henderson } 105bdd87b3bSRichard Henderson return ((uint64_t)ub << 32) | lb; 106bdd87b3bSRichard Henderson } 107bdd87b3bSRichard Henderson 108bdd87b3bSRichard Henderson void helper_bndstx64(CPUX86State *env, target_ulong base, target_ulong ptr, 109bdd87b3bSRichard Henderson uint64_t lb, uint64_t ub) 110bdd87b3bSRichard Henderson { 111bdd87b3bSRichard Henderson uintptr_t ra = GETPC(); 112bdd87b3bSRichard Henderson uint64_t bte; 113bdd87b3bSRichard Henderson 114bdd87b3bSRichard Henderson bte = lookup_bte64(env, base, ra); 115bdd87b3bSRichard Henderson cpu_stq_data_ra(env, bte, lb, ra); 116bdd87b3bSRichard Henderson cpu_stq_data_ra(env, bte + 8, ub, ra); 117bdd87b3bSRichard Henderson cpu_stq_data_ra(env, bte + 16, ptr, ra); 118bdd87b3bSRichard Henderson } 119bdd87b3bSRichard Henderson 120bdd87b3bSRichard Henderson void helper_bndstx32(CPUX86State *env, target_ulong base, target_ulong ptr, 121bdd87b3bSRichard Henderson uint64_t lb, uint64_t ub) 122bdd87b3bSRichard Henderson { 123bdd87b3bSRichard Henderson uintptr_t ra = GETPC(); 124bdd87b3bSRichard Henderson uint32_t bte; 125bdd87b3bSRichard Henderson 126bdd87b3bSRichard Henderson bte = lookup_bte32(env, base, ra); 127bdd87b3bSRichard Henderson cpu_stl_data_ra(env, bte, lb, ra); 128bdd87b3bSRichard Henderson cpu_stl_data_ra(env, bte + 4, ub, ra); 129bdd87b3bSRichard Henderson cpu_stl_data_ra(env, bte + 8, ptr, ra); 130bdd87b3bSRichard Henderson } 1317d117ce8SRichard Henderson 1327d117ce8SRichard Henderson void helper_bnd_jmp(CPUX86State *env) 1337d117ce8SRichard Henderson { 1347d117ce8SRichard Henderson if (!(env->hflags2 & HF2_MPX_PR_MASK)) { 1357d117ce8SRichard Henderson memset(env->bnd_regs, 0, sizeof(env->bnd_regs)); 1367d117ce8SRichard Henderson env->hflags &= ~HF_MPX_IU_MASK; 1377d117ce8SRichard Henderson } 1387d117ce8SRichard Henderson } 139