-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathCPU_Basic_Features_Ext2.asm
329 lines (295 loc) · 12.4 KB
/
CPU_Basic_Features_Ext2.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
;==============================================================================
;
; UASM64 Library
;
; https://github.com/mrfearless/UASM64-Library
;
;==============================================================================
.686
.MMX
.XMM
.x64
option casemap : none
IF @Platform EQ 1
option win64 : 11
ENDIF
option frame : auto
_CPU_Features_CalcStringLength PROTO lpTable:QWORD, qwRecordCount:QWORD, qwRegValue:QWORD, qwStringType:QWORD, qwStringStyle:QWORD, lpqwCount:QWORD
_CPU_Features_CopyStrings PROTO lpTable:QWORD, qwRecordCount:QWORD, qwRegValue:QWORD, qwStringType:QWORD, qwStringStyle:QWORD, lpszFeatureString:QWORD, qwStringOffset:QWORD, qwEntriesFound:QWORD, bMore:QWORD
;GlobalAlloc PROTO uFlags:DWORD, qwBytes:QWORD
;
;IFNDEF GMEM_FIXED
;GMEM_FIXED EQU 0000h
;ENDIF
;IFNDEF GMEM_ZEROINIT
;GMEM_ZEROINIT EQU 0040h
;ENDIF
;
;includelib kernel32.lib
include UASM64.inc
IFNDEF CPU_FEATURES_RECORD
CPU_FEATURES_RECORD STRUCT
BitValue DD ?
lpszMnemonic DB 24 DUP (?)
lpszFeature DB 80 DUP (?)
CPU_FEATURES_RECORD ENDS
ENDIF
.DATA
CPU_FEATURES_EXT2_EDX_TABLE \
CPU_FEATURES_RECORD <(1 SHL 0), "PSFD", "Fast Store Forwarding Predictor">
CPU_FEATURES_RECORD <(1 SHL 1), "PRED_CTRL", "IPRED_DIS controls supported"> ;
CPU_FEATURES_RECORD <(1 SHL 2), "RRSBA_CTRL", "RRSBA behavior disable supported">
CPU_FEATURES_RECORD <(1 SHL 3), "DDPD_U", "Data Dependent Prefetcher disable supported">
CPU_FEATURES_RECORD <(1 SHL 4), "BHI_CTRL", "BHI_DIS_S behavior enable supported">
CPU_FEATURES_RECORD <(1 SHL 5), "MCDT_NO", "No MXCSR configuration dependent timing">
CPU_FEATURES_RECORD <(1 SHL 6), "UC_LOCK_CTRL", "UC-lock disable feature supported">
CPU_FEATURES_RECORD <(1 SHL 7), "MONITOR_MITG_NO", "MONITOR/UMONITOR instructions are not affected by performance/power issues">
CPU_FEATURES_RECORD <(1 SHL 8), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 9), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 10), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 11), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 12), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 13), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 14), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 15), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 16), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 17), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 18), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 19), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 20), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 21), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 22), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 23), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 24), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 25), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 26), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 27), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 28), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 29), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 30), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD <(1 SHL 31), <0>, <0>> ; "(Reserved)"
CPU_FEATURES_RECORD < 0, <0>, <0>>
CPU_FEATURES_EXT2_EDX_LENGTH EQU $ - CPU_FEATURES_EXT2_EDX_TABLE
CPU_FEATURES_EXT2_EDX_SIZE DQ CPU_FEATURES_EXT2_EDX_LENGTH
CPU_FEATURES_EXT2_EDX_RECORDS EQU (CPU_FEATURES_EXT2_EDX_LENGTH / SIZEOF CPU_FEATURES_RECORD) -1
.CODE
UASM64_ALIGN
;------------------------------------------------------------------------------
; CPU_Basic_Features_Ext2
;
; Check which features are supported and return them as in a formatted string
; as a list separated by space, tab, comma, line-feed, carriage return & line
; feed or null. The formatted string is terminated by a double null.
;
; Parameters:
;
; * lpqwFeaturesString - Pointer to a QWORD variable used to store the pointer
; to the formatted features string.
;
; * lpqwFeaturesStringSize - Pointer to a QWORD variable used to store the size
; of the formatted features string.
;
; * qwStringType - The type of feature string to include, can be one of the
; following value:
;
; * CFST_MNEMONIC - Short form of the feature: "AVX"
; * CFST_FEATURE - Long form describing the feature: "Advanced Vector Exte.."
; * CFST_BOTH - "AVX: Advanced Vector Extensions (AVX) Instruction Extensions"
;
; * qwStringStyle - the style of formatting for the feature string, can be one
; of the following values:
;
; * CFSS_NULL - null separated.
; * CFSS_SPACE - space separated.
; * CFSS_COMMA - comma and space separated.
; * CFSS_TAB - tab separated.
; * CFSS_LF - line feed (LF) separated.
; * CFSS_CRLF - carriage return (CR) and line feed (LF) separated.
; * CFSS_LIST - dash '- ' precedes text and CRLF separates.
;
; * qwMaskEDX - a QWORD value to mask the features returned in the EDX register
; so that only the features you are interested in are collected. A mask value
; -1 means to include all features that are found. A mask value of 0 means
; to exclude all features found for EDX feature flags.
;
; Returns:
;
; TRUE if successful, or FALSE otherwise
;
; Notes:
;
; The variables pointed to by the lpqwFeaturesString parameter and the
; lpqwFeaturesStringSize parameter will be set to 0 if the function returns
; FALSE.
;
; The string returned and stoed in the variable pointed to by the
; lpqwFeaturesString parameter should be freed with a call to GlobalFree when
; you no longer require it.
;
; CPUID EAX=7,ECX=2: Extended feature bits in EDX
;
;------------------------------------------------------------------------------
CPU_Basic_Features_Ext2 PROC FRAME USES RBX RCX RDX lpqwFeaturesString:QWORD, lpqwFeaturesStringSize:QWORD, qwStringType:QWORD, qwStringStyle:QWORD, qwMaskEDX:QWORD
LOCAL FeatureEDX:QWORD
LOCAL qwEntriesFoundEDX:QWORD
LOCAL lpszAllStrings:QWORD
LOCAL qwAllStringsLength:QWORD
LOCAL qwStartOffset:QWORD
LOCAL bMoreEntries:QWORD
Invoke CPU_CPUID_Supported
.IF rax == FALSE
jmp CPU_Basic_Features_Ext2_Error
.ENDIF
Invoke CPU_Highest_Basic
.IF rax == 0 || sqword ptr rax < 7
jmp CPU_Basic_Features_Ext2_Error
.ENDIF
Invoke CPU_Highest_Basic_Ext ;CPU_Highest_Basic
.IF rax == -1 || sqword ptr rax < 2
jmp CPU_Basic_Features_Ext2_Error
.ENDIF
.IF qwMaskEDX == 0
; Nothing to check for
jmp CPU_Basic_Features_Ext2_Error
.ENDIF
xor rax, rax
xor rbx, rbx
xor rcx, rcx
xor rdx, rdx
mov eax, 7
mov ecx, 2
cpuid
mov FeatureEDX, rdx
; Mask values
mov rax, qwMaskEDX
and FeatureEDX, rax
mov qwEntriesFoundEDX, 0
mov qwAllStringsLength, 0
;----------------------------------------------------------------------
; Go through the CPU_FEATURES_EDX_TABLE table and AND each BitValue
; against the value in FeatureEDX
;
; For each that matches, calculate the length of string (along with
; string style) and add that to the total for all strings:
; qwAllStringsLength
;----------------------------------------------------------------------
.IF FeatureEDX != 0
IF @Platform EQ 1 ; Win x64
Invoke _CPU_Features_CalcStringLength, Addr CPU_FEATURES_EXT2_EDX_TABLE, CPU_FEATURES_EXT2_EDX_RECORDS, FeatureEDX, qwStringType, qwStringStyle, Addr qwEntriesFoundEDX
ENDIF
IF @Platform EQ 3 ; Linux x64
lea rdi, CPU_FEATURES_EXT2_EDX_TABLE
mov rsi, CPU_FEATURES_EXT2_EDX_RECORDS
mov rdx, FeatureEDX
mov rcx, qwStringType
mov r8, qwStringStyle
lea r9, qwEntriesFoundEDX
call _CPU_Features_CalcStringLength
ENDIF
.IF rax == 0
jmp CPU_Basic_Features_Ext2_Error
.ENDIF
add qwAllStringsLength, rax
.ENDIF
.IF qwEntriesFoundEDX != 0
IFDEF DEBUG32
PrintDec qwEntriesFoundEDX
PrintDec qwAllStringsLength
ENDIF
;------------------------------------------------------------------
; Allocate memory to hold all the strings we require
; adjust for last entries added terminator sizes
;------------------------------------------------------------------
mov rax, qwStringStyle
.IF rax == CFSS_NULL ; null seperated, double null terminated.
sub qwAllStringsLength, 1
.ELSEIF rax == CFSS_SPACE ; space seperated, null terminated.
sub qwAllStringsLength, 1
.ELSEIF rax == CFSS_COMMA ; comma and space seperated, null terminated.
sub qwAllStringsLength, 2
.ELSEIF rax == CFSS_TAB ; tab seperated, null terminated.
sub qwAllStringsLength, 1
.ELSEIF rax == CFSS_LF ; line feed (LF) seperated, null terminated.
sub qwAllStringsLength, 1
.ELSEIF rax == CFSS_CRLF ; carriage return (CR) and line feed (LF) seperated, null terminated.
sub qwAllStringsLength, 2
.ELSEIF rax == CFSS_LIST ; dash preceeds text and CRLF seperates, null terminated.
sub qwAllStringsLength, 2
.ELSE
sub qwAllStringsLength, 1 ; CFSS_NULL
.ENDIF
mov rax, qwAllStringsLength
add rax, 4 ; just in case
Invoke Memory_Alloc, rax
;Invoke GlobalAlloc, GMEM_FIXED or GMEM_ZEROINIT, rax
.IF rax == 0
jmp CPU_Basic_Features_Ext2_Error
.ENDIF
mov lpszAllStrings, rax
mov bMoreEntries, TRUE
mov qwStartOffset, 0
;------------------------------------------------------------------
; Go through the CPU_FEATURES_EDX_TABLE table again once more and
; AND each value against BitValue.
;
; For each that matches, copy the string (along with string style)
; to the total strings buffer: lpszAllStrings
;------------------------------------------------------------------
mov bMoreEntries, FALSE
IF @Platform EQ 1 ; Win x64
Invoke _CPU_Features_CopyStrings, Addr CPU_FEATURES_EXT2_EDX_TABLE, CPU_FEATURES_EXT2_EDX_RECORDS, FeatureEDX, qwStringType, qwStringStyle, lpszAllStrings, qwStartOffset, qwEntriesFoundEDX, bMoreEntries
ENDIF
IF @Platform EQ 3 ; Linux x64
lea rdi, CPU_FEATURES_EXT2_EDX_TABLE
mov rsi, CPU_FEATURES_EXT2_EDX_RECORDS
mov rdx, FeatureEDX
mov rcx, qwStringType
mov r8, qwStringStyle
lea r9, lpszAllStrings
push qwStartOffset
push qwEntriesFoundEDX
push bMoreEntries
call _CPU_Features_CopyStrings
ENDIF
.IF rax == 0
jmp CPU_Basic_Features_Ext2_Error
.ENDIF
.ELSE
;------------------------------------------------------------------
; Did NOT find any values in either feature table
; Could be reserved, or it isnt defined or something else?
;------------------------------------------------------------------
jmp CPU_Basic_Features_Ext2_Error
.ENDIF
jmp CPU_Basic_Features_Ext2_Exit
CPU_Basic_Features_Ext2_Error:
.IF lpqwFeaturesString != 0
mov rbx, lpqwFeaturesString
mov rax, 0
mov [rbx], rax
.ENDIF
.IF lpqwFeaturesStringSize != 0
mov rbx, lpqwFeaturesStringSize
mov rax, 0
mov [rbx], rax
.ENDIF
mov rax, FALSE
ret
CPU_Basic_Features_Ext2_Exit:
;------------------------------------------------------------------
; Pass back the all strings buffer and size of it.
;------------------------------------------------------------------
.IF lpqwFeaturesString != 0
mov rbx, lpqwFeaturesString
mov rax, lpszAllStrings
mov [rbx], rax
.ENDIF
.IF lpqwFeaturesStringSize != 0
mov rbx, lpqwFeaturesStringSize
mov rax, qwAllStringsLength
mov [rbx], rax
.ENDIF
mov rax, TRUE
ret
CPU_Basic_Features_Ext2 ENDP
END