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