OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
3 * Use of this source code is governed by a BSD-style license that can be | |
4 * found in the LICENSE file. | |
5 */ | |
6 | |
7 /* Captures instructions that are considered illegal in native client. | |
8 * | |
9 * Note: This is used by the x86-64 validator to decide what instructions | |
10 * should be flagged as illegal. It is expected to also be used for | |
11 * the x86-32 validator sometime in the future. | |
12 * | |
13 * Note: This code doesn't include rules to check for the case of | |
14 * instructions that are near (relative) jumps with operand word size, | |
15 * when decoding 64-bit instructions. These instructions are marked | |
16 * illegal separately by DEF_OPERAND(Jzw) in ncdecode_forms.c | |
17 * See Call/Jcc instructions in Intel document | |
18 * 253666-030US - March 2009, "Intel 654 and IA-32 Architectures | |
19 * Software Developer's Manual, Volume2A", which specifies that | |
20 * such instructions are not supported on all platforms. | |
21 */ | |
22 | |
23 #ifndef NACL_TRUSTED_BUT_NOT_TCB | |
24 #error("This file is not meant for use in the TCB") | |
25 #endif | |
26 | |
27 #include "native_client/src/trusted/validator/x86/decoder/generator/nacl_illegal
.h" | |
28 | |
29 #include "native_client/src/include/nacl_macros.h" | |
30 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_for
ms.h" | |
31 #include "native_client/src/trusted/validator/x86/decoder/generator/ncdecode_tab
legen.h" | |
32 | |
33 /* List of instruction mnemonics that are illegal. */ | |
34 static const NaClMnemonic kNaClIllegalOp[] = { | |
35 /* TODO(karl) This list is incomplete. As we fix instructions to use the new | |
36 * generator model, this list will be extended. | |
37 */ | |
38 /* ISE reviewers suggested making loopne, loope, loop, jcxz illegal */ | |
39 InstAaa, | |
40 InstAad, | |
41 InstAam, | |
42 InstAas, | |
43 InstBound, | |
44 InstDaa, | |
45 InstDas, | |
46 InstEnter, | |
47 InstIn, | |
48 InstInsb, | |
49 InstInsd, | |
50 InstInsw, | |
51 InstInt, | |
52 InstInto, | |
53 InstInt1, | |
54 InstInt3, | |
55 InstLes, | |
56 InstLds, | |
57 InstLfs, | |
58 InstLgs, | |
59 InstLss, | |
60 InstIret, | |
61 InstIretd, | |
62 InstIretq, | |
63 InstLeave, | |
64 InstOut, | |
65 InstOutsb, | |
66 InstOutsd, | |
67 InstOutsw, | |
68 InstPopa, | |
69 InstPopad, | |
70 InstPopf, | |
71 InstPopfd, | |
72 InstPopfq, | |
73 InstPrefetch_reserved, | |
74 InstPusha, | |
75 InstPushad, | |
76 InstPushf, | |
77 InstPushfd, | |
78 InstPushfq, | |
79 InstRet, | |
80 /* TODO(Karl): Intel manual (see comments above) has a blank entry | |
81 * for opcode 0xd6, which states that blank entries in the tables | |
82 * correspond to reserved (undefined) values Should we treat this | |
83 * accordingly? Making illegal till we know more. | |
84 */ | |
85 InstSalc, | |
86 InstSysret, | |
87 /* Note: Ud2 is special. We except the instruction sequence "0f0b" (with no | |
88 * no prefix bytes) as a special case on a nop instruction. The entry below | |
89 * amkes all other forms, i.e. with a prefix bytes, illegal. | |
90 */ | |
91 InstUd2, | |
92 InstXlat, /* ISE reviewers suggested this omision */ | |
93 /* https://code.google.com/p/nativeclient/issues/detail?id=3944 */ | |
94 InstClflush | |
95 }; | |
96 | |
97 static const NaClNameOpcodeSeq kNaClIllegalOpSeq[] = { | |
98 /* The AMD manual shows 0x82 as a synonym for 0x80 in 32-bit mode only. | |
99 * They are illegal in 64-bit mode. We omit them for both cases. | |
100 */ | |
101 { InstPush, { 0x06 , END_OPCODE_SEQ } }, | |
102 { InstPush, { 0x0e , END_OPCODE_SEQ } }, | |
103 | |
104 /* The following are illegal since they are define by AMD(tm), but not | |
105 * Intel(TM). | |
106 */ | |
107 { InstNop, { 0x0f , 0x19 , END_OPCODE_SEQ } }, | |
108 { InstNop, { 0x0f , 0x1a , END_OPCODE_SEQ } }, | |
109 { InstNop, { 0x0f , 0x1b , END_OPCODE_SEQ } }, | |
110 { InstNop, { 0x0f , 0x1c , END_OPCODE_SEQ } }, | |
111 { InstNop, { 0x0f , 0x1d , END_OPCODE_SEQ } }, | |
112 { InstNop, { 0x0f , 0x1e , END_OPCODE_SEQ } }, | |
113 { InstNop, { 0x0f , 0x1f , END_OPCODE_SEQ } }, | |
114 | |
115 /* Disallow pushing/popping to segment registers. */ | |
116 { InstPush, { 0x06 , END_OPCODE_SEQ } }, | |
117 { InstPush, { 0x16 , END_OPCODE_SEQ } }, | |
118 { InstPush, { 0x0e , END_OPCODE_SEQ } }, | |
119 { InstPush, { 0x1e , END_OPCODE_SEQ } }, | |
120 { InstPush, { 0x0f , 0xa0 , END_OPCODE_SEQ } }, | |
121 { InstPush, { 0x0f , 0xa8 , END_OPCODE_SEQ } }, | |
122 { InstPop , { 0x07 , END_OPCODE_SEQ } }, | |
123 { InstPop , { 0x17 , END_OPCODE_SEQ } }, | |
124 { InstPop , { 0x1f , END_OPCODE_SEQ } }, | |
125 { InstPop , { 0x0f , 0xa1 , END_OPCODE_SEQ } }, | |
126 { InstPop , { 0x0f , 0xa9 , END_OPCODE_SEQ } }, | |
127 | |
128 /* The following operations are provided as a synonym | |
129 * for the corresponding 0x80 code. NaCl requires the | |
130 * use of the 0x80 version. | |
131 */ | |
132 { InstAdd , { 0x82 , SL(0) , END_OPCODE_SEQ } }, | |
133 { InstOr , { 0x82 , SL(1) , END_OPCODE_SEQ } }, | |
134 { InstAdc , { 0x82 , SL(2) , END_OPCODE_SEQ } }, | |
135 { InstSbb , { 0x82 , SL(3) , END_OPCODE_SEQ } }, | |
136 { InstAnd , { 0x82 , SL(4) , END_OPCODE_SEQ } }, | |
137 { InstSub , { 0x82 , SL(5) , END_OPCODE_SEQ } }, | |
138 { InstXor , { 0x82 , SL(6) , END_OPCODE_SEQ } }, | |
139 { InstCmp , { 0x82 , SL(7) , END_OPCODE_SEQ } }, | |
140 | |
141 /* TODO(Karl): Don't know why these are disallowed. */ | |
142 { InstMov , { 0x8c , END_OPCODE_SEQ } }, | |
143 { InstMov , { 0x8e , END_OPCODE_SEQ } }, | |
144 | |
145 /* Don't allow far calls/jumps. */ | |
146 { InstCall , { 0x9a , END_OPCODE_SEQ } }, | |
147 /* Note: special case 64-bit with 66 prefix, which is not suppported on some | |
148 * Intel Chips. See explicit rules in ncdecode_onebyte.c for specific | |
149 * override. | |
150 * See Call instruction in Intel document 253666-030US - March 2009, | |
151 * "Intel 654 and IA-32 Architectures Software Developer's Manual, Volume2A". | |
152 * { InstCall , { 0xe8 , END_OCCODE_SEQ } } with prefix 66 | |
153 */ | |
154 { InstJmp , { 0xea , END_OPCODE_SEQ } }, | |
155 { InstCall, { 0xff , SL(3), END_OPCODE_SEQ } }, | |
156 { InstJmp , { 0xff , SL(5), END_OPCODE_SEQ } }, | |
157 | |
158 /* ISE reviewers suggested omitting bt. Issues have with how many bytes are | |
159 * accessable when using memory for bit base. Note: Current solution is | |
160 * to allow the form that uses a byte, but not general memory/registers. | |
161 * This allows bit access to all standard size integers, but doesn't allow | |
162 * accesses that are very far away. | |
163 */ | |
164 { InstBt , { 0x0f , 0xa3 , END_OPCODE_SEQ } }, | |
165 { InstBtc , { 0x0f , 0xbb , END_OPCODE_SEQ } }, | |
166 { InstBtr , { 0x0f , 0xb3 , END_OPCODE_SEQ } }, | |
167 { InstBts , { 0x0f , 0xab , END_OPCODE_SEQ } }, | |
168 | |
169 /* Added the group17 form of this instruction, since xed does not implement, | |
170 * just to be safe. Note: The form in 660F79 is still allowed. | |
171 */ | |
172 { InstExtrq , { PR(0x66) , 0x0f, 0x78 , SL(0), END_OPCODE_SEQ } }, | |
173 }; | |
174 | |
175 /* Holds illegal opcode sequences for 32-bit model only. */ | |
176 static const NaClNameOpcodeSeq kNaClIllegal32OpSeq[] = { | |
177 /* ISE reviewers suggested omitting bt, btc, btr and bts, but bt must | |
178 * be kept in 64-bit mode, because the compiler needs it to access | |
179 * the top 32-bits of a 64-bit value. | |
180 * Note: For 32-bit mode, we followed the existing implementation | |
181 * that doesn't even allow the one byte form. | |
182 */ | |
183 { InstBt , { 0x0f , 0xba , SL(4) , END_OPCODE_SEQ } }, | |
184 { InstBts , { 0x0f , 0xba , SL(5) , END_OPCODE_SEQ } }, | |
185 { InstBtr , { 0x0f , 0xba , SL(6) , END_OPCODE_SEQ } }, | |
186 { InstBtc , { 0x0f , 0xba , SL(7) , END_OPCODE_SEQ } }, | |
187 }; | |
188 | |
189 void NaClAddNaClIllegalIfApplicable(void) { | |
190 Bool is_illegal = FALSE; /* until proven otherwise. */ | |
191 NaClModeledInst* inst = NaClGetDefInst(); | |
192 | |
193 /* TODO(karl) Once all instructions have been modified to be explicitly | |
194 * marked as illegal, remove the corresponding switch from nc_illegal.c. | |
195 * | |
196 * Note: As instructions are modified to use the new generator model, | |
197 * The file testdata/64/modeled_insts.txt will reflect it by showing | |
198 * the NaClIllegal flag. | |
199 */ | |
200 /* Be sure to handle instruction groups we don't allow. */ | |
201 switch (inst->insttype) { | |
202 case NACLi_RETURN: | |
203 case NACLi_EMMX: | |
204 /* EMMX needs to be supported someday but isn't ready yet. */ | |
205 case NACLi_ILLEGAL: | |
206 case NACLi_SYSTEM: | |
207 case NACLi_RDMSR: | |
208 case NACLi_RDTSCP: | |
209 case NACLi_SVM: | |
210 case NACLi_3BYTE: | |
211 case NACLi_UNDEFINED: | |
212 case NACLi_INVALID: | |
213 case NACLi_SYSCALL: | |
214 case NACLi_SYSENTER: | |
215 case NACLi_VMX: | |
216 case NACLi_FXSAVE: /* don't allow until we can handle. */ | |
217 is_illegal = TRUE; | |
218 break; | |
219 default: | |
220 if (NaClInInstructionSet( | |
221 kNaClIllegalOp, NACL_ARRAY_SIZE(kNaClIllegalOp), | |
222 kNaClIllegalOpSeq, NACL_ARRAY_SIZE(kNaClIllegalOpSeq)) || | |
223 ((X86_32 == NACL_FLAGS_run_mode) && | |
224 NaClInInstructionSet( | |
225 NULL, 0, | |
226 kNaClIllegal32OpSeq, NACL_ARRAY_SIZE(kNaClIllegal32OpSeq)))) { | |
227 is_illegal = TRUE; | |
228 } | |
229 break; | |
230 } | |
231 if (is_illegal) { | |
232 NaClAddIFlags(NACL_IFLAG(NaClIllegal)); | |
233 } | |
234 } | |
OLD | NEW |