xref: /qemu/target/i386/tcg/mpx_helper.c (revision 84307cd6027c4602913177ff09aeefa4743b7234)
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"
23*42fa9665SPhilippe Mathieu-Daudé #include "accel/tcg/cpu-ldst.h"
249c2ff9cdSPierrick Bouvier #include "exec/target_page.h"
25ed69e831SClaudio Fontana #include "helper-tcg.h"
26f4f1110eSRichard Henderson 
27f4f1110eSRichard Henderson 
helper_bndck(CPUX86State * env,uint32_t fail)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 
lookup_bte64(CPUX86State * env,uint64_t base,uintptr_t ra)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 
lookup_bte32(CPUX86State * env,uint32_t base,uintptr_t ra)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 
helper_bndldx64(CPUX86State * env,target_ulong base,target_ulong ptr)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 
helper_bndldx32(CPUX86State * env,target_ulong base,target_ulong ptr)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 
helper_bndstx64(CPUX86State * env,target_ulong base,target_ulong ptr,uint64_t lb,uint64_t ub)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 
helper_bndstx32(CPUX86State * env,target_ulong base,target_ulong ptr,uint64_t lb,uint64_t ub)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 
helper_bnd_jmp(CPUX86State * env)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