Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


fixed emulation bugs
[palacios.git] / palacios / src / palacios / vmm_emulator.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_emulator.h>
22 #include <palacios/vm_guest_mem.h>
23 #include <palacios/vmm_decoder.h>
24 #include <palacios/vmm_paging.h>
25 #include <palacios/vmm_instr_emulator.h>
26
27 #ifndef DEBUG_EMULATOR
28 #undef PrintDebug
29 #define PrintDebug(fmt, args...)
30 #endif
31
32
33
34
35 static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int src_op_size, int dst_op_size);
36
37 // We emulate up to the next 4KB page boundry
38 static int emulate_string_write_op(struct guest_info * info, struct x86_instr * dec_instr, 
39                                    addr_t write_gva, addr_t write_gpa, addr_t dst_addr, 
40                                    int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), 
41                                    void * priv_data) {
42   uint_t emulation_length = 0;
43   addr_t tmp_rcx = 0;
44   addr_t src_addr = 0;
45
46   if (dec_instr->dst_operand.operand != write_gva) {
47     PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
48                (void *)dec_instr->dst_operand.operand, (void *)write_gva);
49     return -1;
50   }
51   
52   emulation_length = ( (dec_instr->str_op_length  < (0x1000 - PAGE_OFFSET_4KB(write_gva))) ? 
53                        dec_instr->str_op_length :
54                        (0x1000 - PAGE_OFFSET_4KB(write_gva)));
55   
56   /* ** Fix emulation length so that it doesn't overrun over the src page either ** */
57   tmp_rcx = emulation_length;
58   
59
60
61
62   if (dec_instr->op_type == V3_OP_MOVS) {
63
64   // figure out addresses here....
65   if (info->mem_mode == PHYSICAL_MEM) {
66     if (guest_pa_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
67       PrintError("Could not translate write Source (Physical) to host VA\n");
68       return -1;
69     }
70   } else {
71     if (guest_va_to_host_va(info, dec_instr->src_operand.operand, &src_addr) == -1) {
72       PrintError("Could not translate write Source (Virtual) to host VA\n");
73       return -1;
74     }
75   }
76
77     if (dec_instr->dst_operand.size == 1) {
78       movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
79     } else if (dec_instr->dst_operand.size == 2) {
80       movs16((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
81     } else if (dec_instr->dst_operand.size == 4) {
82       movs32((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
83 #ifdef __V3_64BIT__
84     } else if (dec_instr->dst_operand.size == 8) {
85       movs64((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
86 #endif
87     } else {
88       PrintError("Invalid operand length\n");
89       return -1;
90     }
91
92     info->vm_regs.rdi += emulation_length;
93     info->vm_regs.rsi += emulation_length;
94
95     // RCX is only modified if the rep prefix is present
96     if (dec_instr->prefixes.rep == 1) {
97       info->vm_regs.rcx -= emulation_length;
98     }
99
100   } else if (dec_instr->op_type == V3_OP_STOS) {
101
102     if (dec_instr->dst_operand.size == 1) {
103       stos8((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
104     } else if (dec_instr->dst_operand.size == 2) {
105       stos16((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
106     } else if (dec_instr->dst_operand.size == 4) {
107       stos32((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
108 #ifdef __V3_64BIT__
109     } else if (dec_instr->dst_operand.size == 8) {
110       stos64((addr_t *)&dst_addr, (addr_t  *)&(info->vm_regs.rax), &tmp_rcx, (addr_t *)&(info->ctrl_regs.rflags));
111 #endif
112     } else {
113       PrintError("Invalid operand length\n");
114       return -1;
115     }
116
117     info->vm_regs.rdi += emulation_length;
118     
119     // RCX is only modified if the rep prefix is present
120     if (dec_instr->prefixes.rep == 1) {
121       info->vm_regs.rcx -= emulation_length;
122     }
123
124   } else {
125     PrintError("Unimplemented String operation\n");
126     return -1;
127   }
128
129   if (write_fn(write_gpa, (void *)dst_addr, emulation_length, priv_data) != emulation_length) {
130     PrintError("Did not fully read hooked data\n");
131     return -1;
132   }
133
134   if (emulation_length == dec_instr->str_op_length) {
135     info->rip += dec_instr->instr_length;
136   }
137
138   return emulation_length;
139
140
141   
142
143
144 }
145
146
147
148
149
150 int v3_emulate_write_op(struct guest_info * info, addr_t write_gva, addr_t write_gpa,  addr_t dst_addr, 
151                        int (*write_fn)(addr_t guest_addr, void * src, uint_t length, void * priv_data), 
152                        void * priv_data) {
153   struct x86_instr dec_instr;
154   uchar_t instr[15];
155   int ret = 0;
156   addr_t src_addr = 0;
157   int src_op_len = 0;
158   int dst_op_len = 0;
159
160   PrintDebug("Emulating Write for instruction at %p\n", (void *)(addr_t)(info->rip));
161   PrintDebug("GVA=%p\n", (void *)write_gva);
162
163   if (info->mem_mode == PHYSICAL_MEM) { 
164     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
165   } else { 
166     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
167   }
168
169   if (ret == -1) {
170     return -1;
171   }
172
173   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
174     PrintError("Decoding Error\n");
175     // Kick off single step emulator
176     return -1;
177   }
178   
179   if (dec_instr.is_str_op) {
180     return emulate_string_write_op(info, &dec_instr, write_gva, write_gpa, dst_addr, write_fn, priv_data);
181   }
182
183
184   if ((dec_instr.dst_operand.type != MEM_OPERAND) ||
185       (dec_instr.dst_operand.operand != write_gva)) {
186     PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
187                (void *)dec_instr.dst_operand.operand, (void *)write_gva);
188     return -1;
189   }
190
191
192   if (dec_instr.src_operand.type == MEM_OPERAND) {
193     if (info->mem_mode == PHYSICAL_MEM) {
194       if (guest_pa_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
195         PrintError("Could not translate write Source (Physical) to host VA\n");
196         return -1;
197       }
198     } else {
199       if (guest_va_to_host_va(info, dec_instr.src_operand.operand, &src_addr) == -1) {
200         PrintError("Could not translate write Source (Virtual) to host VA\n");
201         return -1;
202       }
203     }
204   } else if (dec_instr.src_operand.type == REG_OPERAND) {
205     src_addr = dec_instr.src_operand.operand;
206   } else {
207     src_addr = (addr_t)&(dec_instr.src_operand.operand);
208   }
209
210   dst_op_len = dec_instr.dst_operand.size;
211   src_op_len = dec_instr.src_operand.size;
212
213   PrintDebug("Dst_Addr = %p, SRC operand = %p\n", 
214              (void *)dst_addr, (void *)src_addr);
215
216
217   if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
218     PrintError("Instruction Emulation Failed\n");
219     return -1;
220   }
221
222   if (write_fn(write_gpa, (void *)dst_addr, dst_op_len, priv_data) != dst_op_len) {
223     PrintError("Did not fully write hooked data\n");
224     return -1;
225   }
226
227   info->rip += dec_instr.instr_length;
228
229   return dst_op_len;
230 }
231
232
233 int v3_emulate_read_op(struct guest_info * info, addr_t read_gva, addr_t read_gpa, addr_t src_addr,
234                        int (*read_fn)(addr_t guest_addr, void * dst, uint_t length, void * priv_data), 
235                        void * priv_data) {
236   struct x86_instr dec_instr;
237   uchar_t instr[15];
238   int ret = 0;
239   addr_t dst_addr = 0;
240   int src_op_len = 0;
241   int dst_op_len = 0;
242
243   PrintDebug("Emulating Read for instruction at %p\n", (void *)(addr_t)(info->rip));
244   PrintDebug("GVA=%p\n", (void *)read_gva);
245
246   if (info->mem_mode == PHYSICAL_MEM) { 
247     ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
248   } else { 
249     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
250   }
251
252   if (ret == -1) {
253     return -1;
254   }
255
256   if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
257     PrintError("Decoding Error\n");
258     // Kick off single step emulator
259     return -1;
260   }
261   
262   if (dec_instr.is_str_op) {
263     PrintError("String operations not implemented on fully hooked regions\n");
264     return -1;
265   }
266
267
268   if ((dec_instr.src_operand.type != MEM_OPERAND) ||
269       (dec_instr.src_operand.operand != read_gva)) {
270     PrintError("Inconsistency between Pagefault and Instruction Decode XED_ADDR=%p, PF_ADDR=%p\n",
271                (void *)dec_instr.src_operand.operand, (void *)read_gva);
272     return -1;
273   }
274
275
276   if (dec_instr.dst_operand.type == MEM_OPERAND) {
277     if (info->mem_mode == PHYSICAL_MEM) {
278       if (guest_pa_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
279         PrintError("Could not translate Read Destination (Physical) to host VA\n");
280         return -1;
281       }
282     } else {
283       if (guest_va_to_host_va(info, dec_instr.dst_operand.operand, &dst_addr) == -1) {
284         PrintError("Could not translate Read Destination (Virtual) to host VA\n");
285         return -1;
286       }
287     }
288   } else if (dec_instr.dst_operand.type == REG_OPERAND) {
289     dst_addr = dec_instr.dst_operand.operand;
290   } else {
291     dst_addr = (addr_t)&(dec_instr.dst_operand.operand);
292   }
293
294   src_op_len = dec_instr.src_operand.size;
295   dst_op_len = dec_instr.dst_operand.size;
296
297   PrintDebug("Dst_Addr = %p, SRC Addr = %p\n", 
298              (void *)dst_addr, (void *)src_addr);
299
300   if (read_fn(read_gpa, (void *)src_addr, src_op_len, priv_data) != src_op_len) {
301     PrintError("Did not fully read hooked data\n");
302     return -1;
303   }
304
305   if (run_op(info, dec_instr.op_type, src_addr, dst_addr, src_op_len, dst_op_len) == -1) {
306     PrintError("Instruction Emulation Failed\n");
307     return -1;
308   }
309
310   info->rip += dec_instr.instr_length;
311
312   return src_op_len;
313 }
314
315
316
317
318
319
320 static int run_op(struct guest_info * info, v3_op_type_t op_type, addr_t src_addr, addr_t dst_addr, int src_op_size, int dst_op_size) {
321
322   if (src_op_size == 1) {
323     PrintDebug("Executing 8 bit instruction\n");
324
325     switch (op_type) {
326     case V3_OP_ADC:
327       adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
328       break;
329     case V3_OP_ADD:
330       add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
331       break;
332     case V3_OP_AND:
333       and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
334       break;
335     case V3_OP_OR:
336       or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
337       break;
338     case V3_OP_XOR:
339       xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
340       break;
341     case V3_OP_SUB:
342       sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
343       break;
344
345     case V3_OP_MOV:
346       mov8((addr_t *)dst_addr, (addr_t *)src_addr);
347       break;
348
349     case V3_OP_MOVZX:
350       movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
351       break;
352     case V3_OP_MOVSX:
353       movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
354       break;
355
356     case V3_OP_NOT:
357       not8((addr_t *)dst_addr);
358       break;
359     case V3_OP_XCHG:
360       xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
361       break;
362       
363
364     case V3_OP_INC:
365       inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
366       break;
367     case V3_OP_DEC:
368       dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
369       break;
370     case V3_OP_NEG:
371       neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
372       break;
373     case V3_OP_SETB:
374       setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
375       break;
376     case V3_OP_SETBE:
377       setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
378       break;
379     case V3_OP_SETL:
380       setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
381       break;
382     case V3_OP_SETLE:
383       setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
384       break;
385     case V3_OP_SETNB:
386       setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
387       break;
388     case V3_OP_SETNBE:
389       setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
390       break;
391     case V3_OP_SETNL:
392       setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
393       break;
394     case V3_OP_SETNLE:
395       setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
396       break;
397     case V3_OP_SETNO:
398       setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
399       break;
400     case V3_OP_SETNP:
401       setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
402       break;
403     case V3_OP_SETNS:
404       setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
405       break;
406     case V3_OP_SETNZ:
407       setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
408       break;
409     case V3_OP_SETO:
410       seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
411       break;
412     case V3_OP_SETP:
413       setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
414       break;
415     case V3_OP_SETS:
416       sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
417       break;
418     case V3_OP_SETZ:
419       setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
420       break;
421
422     default:
423       PrintError("Unknown 8 bit instruction\n");
424       return -1;
425     }
426
427   } else if (src_op_size == 2) {
428     PrintDebug("Executing 16 bit instruction\n");
429
430     switch (op_type) {
431     case V3_OP_ADC:
432       adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
433       break;
434     case V3_OP_ADD:
435       add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
436       break;
437     case V3_OP_AND:
438       and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
439       break;
440     case V3_OP_OR:
441       or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
442       break;
443     case V3_OP_XOR:
444       xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
445       break;
446     case V3_OP_SUB:
447       sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
448       break;
449
450
451     case V3_OP_INC:
452       inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
453       break;
454     case V3_OP_DEC:
455       dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
456       break;
457     case V3_OP_NEG:
458       neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
459       break;
460
461     case V3_OP_MOV:
462       mov16((addr_t *)dst_addr, (addr_t *)src_addr);
463       break;
464     case V3_OP_MOVZX:
465       movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
466       break;
467     case V3_OP_MOVSX:
468       movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
469       break;
470     case V3_OP_NOT:
471       not16((addr_t *)dst_addr);
472       break;
473     case V3_OP_XCHG:
474       xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
475       break;
476       
477     default:
478       PrintError("Unknown 16 bit instruction\n");
479       return -1;
480     }
481
482   } else if (src_op_size == 4) {
483     PrintDebug("Executing 32 bit instruction\n");
484
485     switch (op_type) {
486     case V3_OP_ADC:
487       adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
488       break;
489     case V3_OP_ADD:
490       add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
491       break;
492     case V3_OP_AND:
493       and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
494       break;
495     case V3_OP_OR:
496       or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
497       break;
498     case V3_OP_XOR:
499       xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
500       break;
501     case V3_OP_SUB:
502       sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
503       break;
504
505     case V3_OP_INC:
506       inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
507       break;
508     case V3_OP_DEC:
509       dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
510       break;
511     case V3_OP_NEG:
512       neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
513       break;
514
515     case V3_OP_MOV:
516       mov32((addr_t *)dst_addr, (addr_t *)src_addr);
517       break;
518
519     case V3_OP_NOT:
520       not32((addr_t *)dst_addr);
521       break;
522     case V3_OP_XCHG:
523       xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
524       break;
525       
526     default:
527       PrintError("Unknown 32 bit instruction\n");
528       return -1;
529     }
530
531 #ifdef __V3_64BIT__
532   } else if (src_op_size == 8) {
533     PrintDebug("Executing 64 bit instruction\n");
534
535     switch (op_type) {
536     case V3_OP_ADC:
537       adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
538       break;
539     case V3_OP_ADD:
540       add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
541       break;
542     case V3_OP_AND:
543       and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
544       break;
545     case V3_OP_OR:
546       or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
547       break;
548     case V3_OP_XOR:
549       xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
550       break;
551     case V3_OP_SUB:
552       sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
553       break;
554
555     case V3_OP_INC:
556       inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
557       break;
558     case V3_OP_DEC:
559       dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
560       break;
561     case V3_OP_NEG:
562       neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
563       break;
564
565     case V3_OP_MOV:
566       mov64((addr_t *)dst_addr, (addr_t *)src_addr);
567       break;
568
569     case V3_OP_NOT:
570       not64((addr_t *)dst_addr);
571       break;
572     case V3_OP_XCHG:
573       xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
574       break;
575       
576     default:
577       PrintError("Unknown 64 bit instruction\n");
578       return -1;
579     }
580 #endif
581
582   } else {
583     PrintError("Invalid Operation Size\n");
584     return -1;
585   }
586
587   return 0;
588 }