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.


various changes...
[palacios.git] / palacios / src / palacios / vmm_ctrl_regs.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_mem.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmcb.h>
23 #include <palacios/vmm_decoder.h>
24 #include <palacios/vm_guest_mem.h>
25 #include <palacios/vmm_ctrl_regs.h>
26 #include <palacios/vmm_direct_paging.h>
27
28 #ifndef CONFIG_DEBUG_CTRL_REGS
29 #undef PrintDebug
30 #define PrintDebug(fmt, args...)
31 #endif
32
33
34 static int handle_lmsw(struct guest_info * info, struct x86_instr * dec_instr);
35 static int handle_clts(struct guest_info * info, struct x86_instr * dec_instr);
36 static int handle_mov_to_cr0(struct guest_info * info, struct x86_instr * dec_instr);
37
38
39 // First Attempt = 494 lines
40 // current = 106 lines
41 int v3_handle_cr0_write(struct guest_info * info) {
42     uchar_t instr[15];
43     int ret;
44     struct x86_instr dec_instr;
45     
46     if (info->mem_mode == PHYSICAL_MEM) { 
47         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
48     } else { 
49         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
50     }
51     
52     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
53         PrintError("Could not decode instruction\n");
54         return -1;
55     }
56
57     
58     if (dec_instr.op_type == V3_OP_LMSW) {
59         if (handle_lmsw(info, &dec_instr) == -1) {
60             return -1;
61         }
62     } else if (dec_instr.op_type == V3_OP_MOV2CR) {
63         if (handle_mov_to_cr0(info, &dec_instr) == -1) {
64             return -1;
65         }
66     } else if (dec_instr.op_type == V3_OP_CLTS) {
67         if (handle_clts(info, &dec_instr) == -1) {
68             return -1;
69         }
70     } else {
71         PrintError("Unhandled opcode in handle_cr0_write\n");
72         return -1;
73     }
74     
75     info->rip += dec_instr.instr_length;
76     
77     return 0;
78 }
79
80
81
82
83 // The CR0 register only has flags in the low 32 bits
84 // The hardware does a format check to make sure the high bits are zero
85 // Because of this we can ignore the high 32 bits here
86 static int handle_mov_to_cr0(struct guest_info * info, struct x86_instr * dec_instr) {
87     // 32 bit registers
88     struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
89     struct cr0_32 * new_cr0 = (struct cr0_32 *)(dec_instr->src_operand.operand);
90     struct cr0_32 * guest_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
91     uint_t paging_transition = 0;
92     
93     PrintDebug("MOV2CR0 (MODE=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
94     
95     PrintDebug("OperandVal = %x, length=%d\n", *(uint_t *)new_cr0, dec_instr->src_operand.size);
96     
97     PrintDebug("Old CR0=%x\n", *(uint_t *)shadow_cr0);
98     PrintDebug("Old Guest CR0=%x\n", *(uint_t *)guest_cr0);     
99     
100     
101     // We detect if this is a paging transition
102     if (guest_cr0->pg != new_cr0->pg) {
103         paging_transition = 1;
104     }  
105     
106     // Guest always sees the value they wrote
107     *guest_cr0 = *new_cr0;
108     
109     // This value must always be set to 1 
110     guest_cr0->et = 1;    
111     
112     // Set the shadow register to catch non-virtualized flags
113     *shadow_cr0 = *guest_cr0;
114     
115     // Paging is always enabled
116     shadow_cr0->pg = 1;  
117     
118     // Was there a paging transition
119     // Meaning we need to change the page tables
120     if (paging_transition) {
121         if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) {
122             
123             struct efer_64 * guest_efer  = (struct efer_64 *)&(info->shdw_pg_state.guest_efer);
124             struct efer_64 * shadow_efer = (struct efer_64 *)&(info->ctrl_regs.efer);
125             
126             // Check long mode LME to set LME
127             if (guest_efer->lme == 1) {
128                 PrintDebug("Enabing Long Mode\n");
129                 guest_efer->lma = 1;
130                 
131                 shadow_efer->lma = 1;
132                 shadow_efer->lme = 1;
133                 
134                 PrintDebug("New EFER %p\n", (void *)*(addr_t *)(shadow_efer));
135             }
136             
137             PrintDebug("Activating Shadow Page Tables\n");
138             
139             if (v3_activate_shadow_pt(info) == -1) {
140                 PrintError("Failed to activate shadow page tables\n");
141                 return -1;
142             }
143         } else {
144
145             shadow_cr0->wp = 1;
146             
147             if (v3_activate_passthrough_pt(info) == -1) {
148                 PrintError("Failed to activate passthrough page tables\n");
149                 return -1;
150             }
151         }
152     }
153     
154     
155     PrintDebug("New Guest CR0=%x\n",*(uint_t *)guest_cr0);  
156     PrintDebug("New CR0=%x\n", *(uint_t *)shadow_cr0);
157     
158     return 0;
159 }
160
161
162
163
164 static int handle_clts(struct guest_info * info, struct x86_instr * dec_instr) {
165     // CLTS
166     struct cr0_32 * real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
167     
168     real_cr0->ts = 0;
169     
170     if (info->shdw_pg_mode == SHADOW_PAGING) {
171         struct cr0_32 * guest_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
172         guest_cr0->ts = 0;
173     }
174     return 0;
175 }
176
177
178 static int handle_lmsw(struct guest_info * info, struct x86_instr * dec_instr) {
179     struct cr0_real * real_cr0  = (struct cr0_real *)&(info->ctrl_regs.cr0);
180     // XED is a mess, and basically reverses the operand order for an LMSW
181     struct cr0_real * new_cr0 = (struct cr0_real *)(dec_instr->dst_operand.operand);    
182     uchar_t new_cr0_val;
183     
184     PrintDebug("LMSW\n");
185     
186     new_cr0_val = (*(char*)(new_cr0)) & 0x0f;
187     
188     PrintDebug("OperandVal = %x\n", new_cr0_val);
189     
190     // We can just copy the new value through
191     // we don't need to virtualize the lower 4 bits
192     PrintDebug("Old CR0=%x\n", *(uint_t *)real_cr0);    
193     *(uchar_t*)real_cr0 &= 0xf0;
194     *(uchar_t*)real_cr0 |= new_cr0_val;
195     PrintDebug("New CR0=%x\n", *(uint_t *)real_cr0);    
196     
197     
198     // If Shadow paging is enabled we push the changes to the virtualized copy of cr0
199     if (info->shdw_pg_mode == SHADOW_PAGING) {
200         struct cr0_real * guest_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0);
201         
202         PrintDebug("Old Guest CR0=%x\n", *(uint_t *)guest_cr0); 
203         *(uchar_t*)guest_cr0 &= 0xf0;
204         *(uchar_t*)guest_cr0 |= new_cr0_val;
205         PrintDebug("New Guest CR0=%x\n", *(uint_t *)guest_cr0); 
206     }
207     return 0;
208 }
209
210
211
212
213
214 // First attempt = 253 lines
215 // current = 51 lines
216 int v3_handle_cr0_read(struct guest_info * info) {
217     uchar_t instr[15];
218     int ret;
219     struct x86_instr dec_instr;
220     
221     if (info->mem_mode == PHYSICAL_MEM) { 
222         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
223     } else { 
224         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
225     }
226     
227     
228     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
229         PrintError("Could not decode instruction\n");
230         return -1;
231     }
232     
233     if (dec_instr.op_type == V3_OP_MOVCR2) {
234         PrintDebug("MOVCR2 (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
235
236         if ((v3_get_vm_cpu_mode(info) == LONG) || 
237             (v3_get_vm_cpu_mode(info) == LONG_32_COMPAT)) {
238             struct cr0_64 * dst_reg = (struct cr0_64 *)(dec_instr.dst_operand.operand);
239         
240             if (info->shdw_pg_mode == SHADOW_PAGING) {
241                 struct cr0_64 * guest_cr0 = (struct cr0_64 *)&(info->shdw_pg_state.guest_cr0);
242                 *dst_reg = *guest_cr0;
243             } else {
244                 struct cr0_64 * shadow_cr0 = (struct cr0_64 *)&(info->ctrl_regs.cr0);
245                 *dst_reg = *shadow_cr0;
246             }
247
248             PrintDebug("returned CR0: %p\n", (void *)*(addr_t *)dst_reg);
249         } else {
250             struct cr0_32 * dst_reg = (struct cr0_32 *)(dec_instr.dst_operand.operand);
251         
252             if (info->shdw_pg_mode == SHADOW_PAGING) {
253                 struct cr0_32 * guest_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
254                 *dst_reg = *guest_cr0;
255             } else {
256                 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
257                 *dst_reg = *shadow_cr0;
258             }
259
260             PrintDebug("returned CR0: %x\n", *(uint_t*)dst_reg);
261         }
262
263     } else if (dec_instr.op_type == V3_OP_SMSW) {
264         struct cr0_real * shadow_cr0 = (struct cr0_real *)&(info->ctrl_regs.cr0);
265         struct cr0_real * dst_reg = (struct cr0_real *)(dec_instr.dst_operand.operand);
266         char cr0_val = *(char*)shadow_cr0 & 0x0f;
267         
268         PrintDebug("SMSW\n");
269         
270         // The lower 4 bits of the guest/shadow CR0 are mapped through
271         // We can treat nested and shadow paging the same here
272         *(char *)dst_reg &= 0xf0;
273         *(char *)dst_reg |= cr0_val;
274         
275     } else {
276         PrintError("Unhandled opcode in handle_cr0_read\n");
277         return -1;
278     }
279     
280     info->rip += dec_instr.instr_length;
281
282     return 0;
283 }
284
285
286
287
288 // First Attempt = 256 lines
289 // current = 65 lines
290 int v3_handle_cr3_write(struct guest_info * info) {
291     int ret;
292     uchar_t instr[15];
293     struct x86_instr dec_instr;
294     
295     if (info->mem_mode == PHYSICAL_MEM) { 
296         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
297     } else { 
298         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
299     }
300     
301     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
302         PrintError("Could not decode instruction\n");
303         return -1;
304     }
305     
306     if (dec_instr.op_type == V3_OP_MOV2CR) {
307         PrintDebug("MOV2CR3 (cpu_mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
308         
309         if (info->shdw_pg_mode == SHADOW_PAGING) {
310             PrintDebug("Old Shadow CR3=%p; Old Guest CR3=%p\n", 
311                        (void *)(addr_t)(info->ctrl_regs.cr3), 
312                        (void*)(addr_t)(info->shdw_pg_state.guest_cr3));
313             
314             
315             // We update the guest CR3    
316             if (info->cpu_mode == LONG) {
317                 struct cr3_64 * new_cr3 = (struct cr3_64 *)(dec_instr.src_operand.operand);
318                 struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->shdw_pg_state.guest_cr3);
319                 *guest_cr3 = *new_cr3;
320             } else {
321                 struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
322                 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
323                 *guest_cr3 = *new_cr3;
324             }
325
326
327             // If Paging is enabled in the guest then we need to change the shadow page tables
328             if (info->mem_mode == VIRTUAL_MEM) {
329                 if (v3_activate_shadow_pt(info) == -1) {
330                     PrintError("Failed to activate 32 bit shadow page table\n");
331                     return -1;
332                 }
333             }
334             
335             PrintDebug("New Shadow CR3=%p; New Guest CR3=%p\n", 
336                        (void *)(addr_t)(info->ctrl_regs.cr3), 
337                        (void*)(addr_t)(info->shdw_pg_state.guest_cr3));
338             
339         } else if (info->shdw_pg_mode == NESTED_PAGING) {
340             
341             // This is just a passthrough operation which we probably don't need here
342             if (info->cpu_mode == LONG) {
343                 struct cr3_64 * new_cr3 = (struct cr3_64 *)(dec_instr.src_operand.operand);
344                 struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->ctrl_regs.cr3);
345                 *guest_cr3 = *new_cr3;
346             } else {
347                 struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
348                 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
349                 *guest_cr3 = *new_cr3;
350             }
351             
352         }
353     } else {
354         PrintError("Unhandled opcode in handle_cr3_write\n");
355         return -1;
356     }
357     
358     info->rip += dec_instr.instr_length;
359     
360     return 0;
361 }
362
363
364
365 // first attempt = 156 lines
366 // current = 36 lines
367 int v3_handle_cr3_read(struct guest_info * info) {
368     uchar_t instr[15];
369     int ret;
370     struct x86_instr dec_instr;
371     
372     if (info->mem_mode == PHYSICAL_MEM) { 
373         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
374     } else { 
375         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
376     }
377     
378     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
379         PrintError("Could not decode instruction\n");
380         return -1;
381     }
382     
383     if (dec_instr.op_type == V3_OP_MOVCR2) {
384         PrintDebug("MOVCR32 (mode=%s)\n", v3_cpu_mode_to_str(info->cpu_mode));
385         
386         if (info->shdw_pg_mode == SHADOW_PAGING) {
387             
388             if ((v3_get_vm_cpu_mode(info) == LONG) || 
389                 (v3_get_vm_cpu_mode(info) == LONG_32_COMPAT)) {
390                 struct cr3_64 * dst_reg = (struct cr3_64 *)(dec_instr.dst_operand.operand);
391                 struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->shdw_pg_state.guest_cr3);
392                 *dst_reg = *guest_cr3;
393             } else {
394                 struct cr3_32 * dst_reg = (struct cr3_32 *)(dec_instr.dst_operand.operand);
395                 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
396                 *dst_reg = *guest_cr3;
397             }
398             
399         } else if (info->shdw_pg_mode == NESTED_PAGING) {
400             
401             // This is just a passthrough operation which we probably don't need here
402             if ((v3_get_vm_cpu_mode(info) == LONG) || 
403                 (v3_get_vm_cpu_mode(info) == LONG_32_COMPAT)) {
404                 struct cr3_64 * dst_reg = (struct cr3_64 *)(dec_instr.dst_operand.operand);
405                 struct cr3_64 * guest_cr3 = (struct cr3_64 *)&(info->ctrl_regs.cr3);
406                 *dst_reg = *guest_cr3;
407             } else {
408                 struct cr3_32 * dst_reg = (struct cr3_32 *)(dec_instr.dst_operand.operand);
409                 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3);
410                 *dst_reg = *guest_cr3;
411             }
412         }
413         
414     } else {
415         PrintError("Unhandled opcode in handle_cr3_read\n");
416         return -1;
417     }
418     
419     info->rip += dec_instr.instr_length;
420     
421     return 0;
422 }
423
424
425 // We don't need to virtualize CR4, all we need is to detect the activation of PAE
426 int v3_handle_cr4_read(struct guest_info * info) {
427     //  PrintError("CR4 Read not handled\n");
428     // Do nothing...
429     return 0;
430 }
431
432 int v3_handle_cr4_write(struct guest_info * info) {
433     uchar_t instr[15];
434     int ret;
435     int flush_tlb=0;
436     struct x86_instr dec_instr;
437     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info);
438     
439     if (info->mem_mode == PHYSICAL_MEM) { 
440         ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
441     } else { 
442         ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
443     }
444     
445     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
446         PrintError("Could not decode instruction\n");
447         return -1;
448     }
449     
450     if (dec_instr.op_type != V3_OP_MOV2CR) {
451         PrintError("Invalid opcode in write to CR4\n");
452         return -1;
453     }
454     
455     // Check to see if we need to flush the tlb
456     
457     if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) { 
458         struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
459         struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
460         
461         // if pse, pge, or pae have changed while PG (in any mode) is on
462         // the side effect is a TLB flush, which means we need to
463         // toss the current shadow page tables too
464         //
465         // 
466         // TODO - PAE FLAG needs to be special cased
467         if ((cr4->pse != new_cr4->pse) || 
468             (cr4->pge != new_cr4->pge) || 
469             (cr4->pae != new_cr4->pae)) { 
470             PrintDebug("Handling PSE/PGE/PAE -> TLBFlush case, flag set\n");
471             flush_tlb=1;
472             
473         }
474     }
475     
476
477     if ((cpu_mode == PROTECTED) || (cpu_mode == PROTECTED_PAE)) {
478         struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
479         struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
480         
481         PrintDebug("OperandVal = %x, length = %d\n", *(uint_t *)new_cr4, dec_instr.src_operand.size);
482         PrintDebug("Old CR4=%x\n", *(uint_t *)cr4);
483         
484         if ((info->shdw_pg_mode == SHADOW_PAGING)) { 
485             if (v3_get_vm_mem_mode(info) == PHYSICAL_MEM) {
486                 
487                 if ((cr4->pae == 0) && (new_cr4->pae == 1)) {
488                     PrintDebug("Creating PAE passthrough tables\n");
489                     
490                     // create 32 bit PAE direct map page table
491                     if (v3_reset_passthrough_pts(info) == -1) {
492                         PrintError("Could not create 32 bit PAE passthrough pages tables\n");
493                         return -1;
494                     }
495
496                     // reset cr3 to new page tables
497                     info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
498                     
499                 } else if ((cr4->pae == 1) && (new_cr4->pae == 0)) {
500                     // Create passthrough standard 32bit pagetables
501                     PrintError("Switching From PAE to Protected mode not supported\n");
502                     return -1;
503                 } 
504             }
505         }
506         
507         *cr4 = *new_cr4;
508         PrintDebug("New CR4=%x\n", *(uint_t *)cr4);
509         
510     } else if ((cpu_mode == LONG) || (cpu_mode == LONG_32_COMPAT)) {
511         struct cr4_64 * new_cr4 = (struct cr4_64 *)(dec_instr.src_operand.operand);
512         struct cr4_64 * cr4 = (struct cr4_64 *)&(info->ctrl_regs.cr4);
513         
514         PrintDebug("Old CR4=%p\n", (void *)*(addr_t *)cr4);
515         PrintDebug("New CR4=%p\n", (void *)*(addr_t *)new_cr4);
516         
517         if (new_cr4->pae == 0) {
518             // cannot turn off PAE in long mode GPF the guest
519             PrintError("Cannot disable PAE in long mode, should send GPF\n");
520             return -1;
521         }
522         
523         *cr4 = *new_cr4;
524         
525     } else {
526         PrintError("CR4 write not supported in CPU_MODE: %s\n", v3_cpu_mode_to_str(cpu_mode));
527         return -1;
528     }
529     
530     
531     if (flush_tlb) {
532         PrintDebug("Handling PSE/PGE/PAE -> TLBFlush (doing flush now!)\n");
533         if (v3_activate_shadow_pt(info) == -1) {
534             PrintError("Failed to activate shadow page tables when emulating TLB flush in handling cr4 write\n");
535             return -1;
536         }
537     }
538     
539     
540     info->rip += dec_instr.instr_length;
541     return 0;
542 }
543
544
545 int v3_handle_efer_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
546     struct guest_info * info = (struct guest_info *)(priv_data);
547     PrintDebug("EFER Read HI=%x LO=%x\n", info->shdw_pg_state.guest_efer.hi, info->shdw_pg_state.guest_efer.lo);
548     
549     dst->value = info->shdw_pg_state.guest_efer.value;
550     
551     return 0;
552 }
553
554
555
556 // TODO: this is a disaster we need to clean this up...
557 int v3_handle_efer_write(uint_t msr, struct v3_msr src, void * priv_data) {
558     struct guest_info * info = (struct guest_info *)(priv_data);
559     //struct efer_64 * new_efer = (struct efer_64 *)&(src.value);
560     struct efer_64 * shadow_efer = (struct efer_64 *)&(info->ctrl_regs.efer);
561     struct v3_msr * guest_efer = &(info->shdw_pg_state.guest_efer);
562     
563     PrintDebug("EFER Write\n");
564     PrintDebug("EFER Write Values: HI=%x LO=%x\n", src.hi, src.lo);
565     //PrintDebug("Old EFER=%p\n", (void *)*(addr_t*)(shadow_efer));
566     
567     // We virtualize the guests efer to hide the SVME and LMA bits
568     guest_efer->value = src.value;
569     
570     
571     // Enable/Disable Syscall
572     shadow_efer->sce = src.value & 0x1;
573     
574     return 0;
575 }