OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2012 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 /* | |
8 * Checks that CPU ID features match instructions found in executable. | |
9 */ | |
10 | |
11 #include <stdlib.h> | |
12 #include <string.h> | |
13 | |
14 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_cpu_checks.h" | |
15 | |
16 #include "native_client/src/shared/platform/nacl_log.h" | |
17 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h" | |
18 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal
.h" | |
19 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.
h" | |
20 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_
internal.h" | |
21 #include "native_client/src/trusted/validator/x86/nc_segment.h" | |
22 | |
23 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter_inl.c" | |
24 | |
25 void NaClCpuCheckMemoryInitialize(NaClValidatorState* state) { | |
26 NaClClearCPUFeaturesX86(&state->cpu_checks.cpu_features); | |
27 state->cpu_checks.f_CMOV_and_x87 = FALSE; | |
28 state->cpu_checks.f_MMX_or_SSE2 = FALSE; | |
29 } | |
30 | |
31 /* Helper function to report unsupported features */ | |
32 static INLINE void NaClCheckFeature(NaClCPUFeatureX86ID feature, | |
33 struct NaClValidatorState* vstate, | |
34 Bool* squash_me) { | |
35 if (!NaClGetCPUFeatureX86(&vstate->cpu_features, feature)) { | |
36 if (!NaClGetCPUFeatureX86(&vstate->cpu_checks.cpu_features, feature)) { | |
37 NaClValidatorInstMessage( | |
38 LOG_WARNING, vstate, vstate->cur_inst_state, | |
39 "CPU model does not support %s instructions.\n", | |
40 NaClGetCPUFeatureX86Name(feature)); | |
41 NaClSetCPUFeatureX86(&vstate->cpu_checks.cpu_features, feature, TRUE); | |
42 } | |
43 *squash_me = TRUE; | |
44 } | |
45 } | |
46 | |
47 void NaClCpuCheck(struct NaClValidatorState* state, | |
48 struct NaClInstIter* iter) { | |
49 Bool squash_me = FALSE; | |
50 switch (state->cur_inst->insttype) { | |
51 case NACLi_X87: | |
52 case NACLi_X87_FSINCOS: | |
53 NaClCheckFeature(NaClCPUFeatureX86_x87, state, &squash_me); | |
54 break; | |
55 case NACLi_SFENCE_CLFLUSH: | |
56 /* TODO(bradchen): distinguish between SFENCE and CLFLUSH */ | |
57 NaClCheckFeature(NaClCPUFeatureX86_CLFLUSH, state, &squash_me); | |
58 NaClCheckFeature(NaClCPUFeatureX86_FXSR, state, &squash_me); | |
59 break; | |
60 case NACLi_LAHF: | |
61 if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_TARGET_SUBARCH == 64) | |
62 NaClCheckFeature(NaClCPUFeatureX86_LAHF, state, &squash_me); | |
63 break; | |
64 case NACLi_CMPXCHG8B: | |
65 NaClCheckFeature(NaClCPUFeatureX86_CX8, state, &squash_me); | |
66 break; | |
67 case NACLi_CMPXCHG16B: | |
68 NaClCheckFeature(NaClCPUFeatureX86_CX16, state, &squash_me); | |
69 break; | |
70 case NACLi_CMOV: | |
71 NaClCheckFeature(NaClCPUFeatureX86_CMOV, state, &squash_me); | |
72 break; | |
73 case NACLi_FCMOV: | |
74 if (!(NaClGetCPUFeatureX86(&state->cpu_features, | |
75 NaClCPUFeatureX86_CMOV) && | |
76 NaClGetCPUFeatureX86(&state->cpu_features, | |
77 NaClCPUFeatureX86_x87))) { | |
78 if (!state->cpu_checks.f_CMOV_and_x87) { | |
79 NaClValidatorInstMessage( | |
80 LOG_WARNING, state, state->cur_inst_state, | |
81 "CPU model does not support CMOV and x87 instructions.\n"); | |
82 state->cpu_checks.f_CMOV_and_x87 = TRUE; | |
83 } | |
84 squash_me = TRUE; | |
85 } | |
86 break; | |
87 case NACLi_RDTSC: | |
88 NaClCheckFeature(NaClCPUFeatureX86_TSC, state, &squash_me); | |
89 break; | |
90 case NACLi_MMX: | |
91 NaClCheckFeature(NaClCPUFeatureX86_MMX, state, &squash_me); | |
92 break; | |
93 case NACLi_MMXSSE2: | |
94 /* Note: We accept these instructions if either MMX or SSE2 bits */ | |
95 /* are set, in case MMX instructions go away someday... */ | |
96 if (!(NaClGetCPUFeatureX86(&state->cpu_features, | |
97 NaClCPUFeatureX86_MMX) || | |
98 NaClGetCPUFeatureX86(&state->cpu_features, | |
99 NaClCPUFeatureX86_SSE2))) { | |
100 if (!state->cpu_checks.f_MMX_or_SSE2) { | |
101 NaClValidatorInstMessage( | |
102 LOG_WARNING, state, state->cur_inst_state, | |
103 "CPU model does not support MMX or SSE2 instructions.\n"); | |
104 state->cpu_checks.f_MMX_or_SSE2 = TRUE; | |
105 } | |
106 } | |
107 squash_me = TRUE; | |
108 break; | |
109 case NACLi_SSE: | |
110 NaClCheckFeature(NaClCPUFeatureX86_SSE, state, &squash_me); | |
111 break; | |
112 case NACLi_SSE2: | |
113 NaClCheckFeature(NaClCPUFeatureX86_SSE2, state, &squash_me); | |
114 break; | |
115 case NACLi_SSE3: | |
116 NaClCheckFeature(NaClCPUFeatureX86_SSE3, state, &squash_me); | |
117 break; | |
118 case NACLi_SSE4A: | |
119 NaClCheckFeature(NaClCPUFeatureX86_SSE4A, state, &squash_me); | |
120 break; | |
121 case NACLi_SSE41: | |
122 NaClCheckFeature(NaClCPUFeatureX86_SSE41, state, &squash_me); | |
123 break; | |
124 case NACLi_SSE42: | |
125 NaClCheckFeature(NaClCPUFeatureX86_SSE42, state, &squash_me); | |
126 break; | |
127 case NACLi_MOVBE: | |
128 NaClCheckFeature(NaClCPUFeatureX86_MOVBE, state, &squash_me); | |
129 break; | |
130 case NACLi_POPCNT: | |
131 NaClCheckFeature(NaClCPUFeatureX86_POPCNT, state, &squash_me); | |
132 break; | |
133 case NACLi_LZCNT: | |
134 NaClCheckFeature(NaClCPUFeatureX86_LZCNT, state, &squash_me); | |
135 break; | |
136 case NACLi_SSSE3: | |
137 NaClCheckFeature(NaClCPUFeatureX86_SSSE3, state, &squash_me); | |
138 break; | |
139 case NACLi_3DNOW: | |
140 NaClCheckFeature(NaClCPUFeatureX86_3DNOW, state, &squash_me); | |
141 break; | |
142 case NACLi_E3DNOW: | |
143 NaClCheckFeature(NaClCPUFeatureX86_E3DNOW, state, &squash_me); | |
144 break; | |
145 case NACLi_LONGMODE: | |
146 /* TODO(karl): Remove this when NACLi_LONGMODE is no longer needed */ | |
147 NaClCheckFeature(NaClCPUFeatureX86_LM, state, &squash_me); | |
148 break; | |
149 case NACLi_SSE2x: | |
150 /* This case requires CPUID checking code */ | |
151 /* DATA16 prefix required */ | |
152 if (!(state->cur_inst_state->prefix_mask & kPrefixDATA16)) { | |
153 NaClValidatorInstMessage( | |
154 LOG_ERROR, state, state->cur_inst_state, | |
155 "SSEx instruction must use prefix 0x66.\n"); | |
156 } | |
157 NaClCheckFeature(NaClCPUFeatureX86_SSE2, state, &squash_me); | |
158 break; | |
159 default: | |
160 /* This instruction could be either legal or illegal, but if we | |
161 * get here it is not CPU-dependent. | |
162 */ | |
163 break; | |
164 } | |
165 if (state->cur_inst->flags & NACL_IFLAG(LongMode)) { | |
166 NaClCheckFeature(NaClCPUFeatureX86_LM, state, &squash_me); | |
167 } | |
168 if (squash_me) { | |
169 if (state->readonly_text) { | |
170 NaClValidatorInstMessage( | |
171 LOG_ERROR, state, state->cur_inst_state, | |
172 "Read-only text: cannot squash unsupported instruction.\n"); | |
173 } else { | |
174 /* Replace all bytes of the instruction with the HLT instruction. */ | |
175 NCStubOutMem(state, NaClInstIterGetInstMemoryInline(iter), | |
176 NaClInstStateLength(state->cur_inst_state)); | |
177 } | |
178 } | |
179 } | |
OLD | NEW |