ame='generator' content='cgit v1.2.3'/>
aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/ia64/tools/privify/privify.c
blob: 2b1018677830872fea56a92eaadd630e9eee7f77 (plain)
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
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
/*
 * Binary translate privilege-sensitive ops to privileged
 *
 * Copyright (C) 2004 Hewlett-Packard Co.
 *      Dan Magenheimer (dan.magenheimer@hp.com)
 *
 */

#include "privify.h"

typedef unsigned long long u64;
typedef unsigned long long IA64_INST;

typedef union U_IA64_BUNDLE {
    u64 i64[2];
    struct { u64 template:5,slot0:41,slot1a:18,slot1b:23,slot2:41; };
    // NOTE: following doesn't work because bitfields can't cross natural
    // size boundaries
    //struct { u64 template:5, slot0:41, slot1:41, slot2:41; };
} IA64_BUNDLE;

typedef enum E_IA64_SLOT_TYPE { I, M, F, B, L, ILLEGAL } IA64_SLOT_TYPE;

typedef union U_INST64_A5 {
    IA64_INST inst;
    struct { u64 qp:6, r1:7, imm7b:7, r3:2, imm5c:5, imm9d:9, s:1, major:4; };
} INST64_A5;

typedef union U_INST64_B4 {
    IA64_INST inst;
    struct { u64 qp:6, btype:3, un3:3, p:1, b2:3, un11:11, x6:6, wh:2, d:1, un1:1, major:4; };
} INST64_B4;

typedef union U_INST64_B8 {
    IA64_INST inst;
    struct { u64 qp:6, un21:21, x6:6, un4:4, major:4; };
} INST64_B8;

typedef union U_INST64_B9 {
    IA64_INST inst;
    struct { u64 qp:6, imm20:20, :1, x6:6, :3, i:1, major:4; };
} INST64_B9;

typedef union U_INST64_I19 {
    IA64_INST inst;
    struct { u64 qp:6, imm20:20, :1, x6:6, x3:3, i:1, major:4; };
} INST64_I19;

typedef union U_INST64_I26 {
    IA64_INST inst;
    struct { u64 qp:6, :7, r2:7, ar3:7, x6:6, x3:3, :1, major:4;};
} INST64_I26;

typedef union U_INST64_I27 {
    IA64_INST inst;
    struct { u64 qp:6, :7, imm:7, ar3:7, x6:6, x3:3, s:1, major:4;};
} INST64_I27;

typedef union U_INST64_I28 { // not privileged (mov from AR)
    IA64_INST inst;
    struct { u64 qp:6, r1:7, :7, ar3:7, x6:6, x3:3, :1, major:4;};
} INST64_I28;

typedef union U_INST64_M28 {
    IA64_INST inst;
    struct { u64 qp:6, :14, r3:7, x6:6, x3:3, :1, major:4;};
} INST64_M28;

typedef union U_INST64_M29 {
    IA64_INST inst;
    struct { u64 qp:6, :7, r2:7, ar3:7, x6:6, x3:3, :1, major:4;};
} INST64_M29;

typedef union U_INST64_M30 {
    IA64_INST inst;
    struct { u64 qp:6, :7, imm:7, ar3:7,x4:4,x2:2,x3:3,s:1,major:4;};
} INST64_M30;

typedef union U_INST64_M31 {
    IA64_INST inst;
    struct { u64 qp:6, r1:7, :7, ar3:7, x6:6, x3:3, :1, major:4;};
} INST64_M31;

typedef union U_INST64_M32 {
    IA64_INST inst;
    struct { u64 qp:6, :7, r2:7, cr3:7, x6:6, x3:3, :1, major:4;};
} INST64_M32;

typedef union U_INST64_M33 {
    IA64_INST inst;
    struct { u64 qp:6, r1:7, :7, cr3:7, x6:6, x3:3, :1, major:4; };
} INST64_M33;

typedef union U_INST64_M35 {
    IA64_INST inst;
    struct { u64 qp:6, :7, r2:7, :7, x6:6, x3:3, :1, major:4; };
    	
} INST64_M35;

typedef union U_INST64_M36 {
    IA64_INST inst;
    struct { u64 qp:6, r1:7, :14, x6:6, x3:3, :1, major:4; }; 
} INST64_M36;

typedef union U_INST64_M41 {
    IA64_INST inst;
    struct { u64 qp:6, :7, r2:7, :7, x6:6, x3:3, :1, major:4; }; 
} INST64_M41;

typedef union U_INST64_M42 {
    IA64_INST inst;
    struct { u64 qp:6, :7, r2:7, r3:7, x6:6, x3:3, :1, major:4; };
} INST64_M42;

typedef union U_INST64_M43 {
    IA64_INST inst;
    struct { u64 qp:6, r1:7, :7, r3:7, x6:6, x3:3, :1, major:4; };
} INST64_M43;

typedef union U_INST64_M44 {
    IA64_INST inst;
    struct { u64 qp:6, imm:21, x4:4, i2:2, x3:3, i:1, major:4; };
} INST64_M44;

typedef union U_INST64_M45 {
    IA64_INST inst;
    struct { u64 qp:6, :7, r2:7, r3:7, x6:6, x3:3, :1, major:4; };
} INST64_M45;

typedef union U_INST64_M46 {
    IA64_INST inst;
    struct { u64 qp:6, r1:7, un7:7, r3:7, x6:6, x3:3, un1:1, major:4; };
} INST64_M46;

typedef union U_INST64 {
    IA64_INST inst;
    struct { u64 :37, major:4; } generic;
    INST64_A5 A5;	// used in build_hypercall_bundle only
    INST64_B4 B4;	// used in build_hypercall_bundle only
    INST64_B8 B8;	// rfi, bsw.[01]
    INST64_B9 B9;	// break.b
    INST64_I19 I19;	// used in build_hypercall_bundle only
    INST64_I26 I26;	// mov register to ar (I unit)
    INST64_I27 I27;	// mov immediate to ar (I unit)
    INST64_I28 I28;	// mov from ar (I unit)
    INST64_M28 M28;	// purge translation cache entry
    INST64_M29 M29;	// mov register to ar (M unit)
    INST64_M30 M30;	// mov immediate to ar (M unit)
    INST64_M31 M31;	// mov from ar (M unit)
    INST64_M32 M32;	// mov reg to cr
    INST64_M33 M33;	// mov from cr
    INST64_M35 M35;	// mov to psr
    INST64_M36 M36;	// mov from psr
    INST64_M41 M41;	// translation cache insert
    INST64_M42 M42;	// mov to indirect reg/translation reg insert
    INST64_M43 M43;	// mov from indirect reg
    INST64_M44 M44;	// set/reset system mask
    INST64_M45 M45;	// translation purge
    INST64_M46 M46;	// translation access (tpa,tak)
} INST64;

#define MASK_41 ((u64)0x1ffffffffff)

long priv_verbose = 0;
#define verbose(a...) do { if (priv_verbose) printf(a); } while(0)

/*
 * privify_inst
 *
 * Replaces privilege-sensitive instructions (and reads from write-trapping
 * registers) with privileged/trapping instructions as follows:
 *	mov rx=ar.cflg -> mov ar.cflg=r(x+64) [**]
 *	mov rx=ar.ky -> mov ar.ky=r(x+64)
 *	fc rx -> ptc r(x+64)
 *	thash rx=ry -> tak rx=r(y+64)
 *	ttag rx=ry -> tpa rx=r(y+64)
 *	mov rx=cpuid[ry] -> mov r(x+64)=rr[ry]
 *	mov rx=pmd[ry] -> mov r(x+64)=pmc[ry] [**]
 *	cover -> break.b 0x1fffff
 *
 * [**] not currently implemented
 */
IA64_INST privify_inst(IA64_INST inst_val,
		IA64_SLOT_TYPE slot_type, IA64_BUNDLE *bp, char **msg)
{
	INST64 inst = *(INST64 *)&inst_val;

	*msg = 0;
	switch (slot_type) {
	    case M:
		// FIXME: Also use for mov_to/from_ar.cflag (M29/M30) (IA32 only)
		if (inst.generic.major != 1) break;
		if (inst.M46.x3 != 0) break;
		if (inst.M31.x6 == 0x22 && inst.M31.ar3 < 8) {
			// mov r1=kr -> mov kr=r1+64
			verbose("privify_inst: privified mov r1=kr @%p\n",bp);
			if (inst.M31.r1 >= 64) *msg = "mov r1=kr w/r1>63";
			else privify_mov_from_kr_m(inst);
			break;
		}
		if (inst.M29.x6 == 0x2a && inst.M29.ar3 < 8)  {// mov kr=r1
			if (inst.M29.r2 >= 64) *msg = "mov kr=r2 w/r2>63";
			break;
		}
		if (inst.M28.x6 == 0x30) {