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.


Minor compile warning fixup and error checks
[palacios.git] / palacios / src / palacios / vmm_fp.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) 2013, Peter Dinda <pdinda@northwestern.edu> 
11  * Copyright (c) 2013, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Peter Dinda <pdinda@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_fp.h>
22 #include <palacios/vm_guest.h>
23 #include <palacios/vmm_lowlevel.h>
24
25 #ifdef V3_CONFIG_CHECKPOINT
26 #include <palacios/vmm_checkpoint.h>
27 #endif
28
29
30 static int can_do_fp=-1;
31
32 // assumes identical on all cores...
33 int v3_can_handle_fp_state()
34 {
35   if (can_do_fp!=-1) { 
36     return can_do_fp;
37   } else {
38     uint32_t eax=0, ebx=0, ecx=0, edx=0;
39
40     v3_cpuid(CPUID_FEATURE_IDS,&eax,&ebx,&ecx,&edx);
41     
42     can_do_fp= !!(edx & (1<<25)); // do we have SSE?
43     
44     return can_do_fp;
45   }
46 }
47
48 int v3_init_fp()
49 {
50   if (v3_can_handle_fp_state()) { 
51     V3_Print(VM_NONE,VCORE_NONE,"Floating point save/restore init:  available on this hardware\n");
52   } else {
53     V3_Print(VM_NONE,VCORE_NONE,"Floating point save/restore init:  UNAVAILABLE ON THIS HARDWARE\n");
54   }
55   return 0;
56 }
57
58 int v3_deinit_fp()
59 {
60   V3_Print(VM_NONE,VCORE_NONE,"Floating point save/restore deinited\n");
61   return 0;
62 }
63
64 #define EFER_MSR 0xc0000080
65
66
67 int v3_get_fp_state(struct guest_info *core)
68
69   if (v3_can_handle_fp_state()) { 
70     /*
71       If the fast-FXSAVE/FXRSTOR (FFXSR) feature is enabled in EFER, FXSAVE and FXRSTOR do not save or restore the XMM0–15 registers when executed in 64-bit mode at CPL 0. The x87 environment and MXCSR are saved whether fast-FXSAVE/FXRSTOR is enabled or not. Software can use the CPUID instruction to determine whether the fast-FXSAVE/FXRSTOR feature is available
72       (CPUID Fn8000_0001h_EDX[FFXSR]). The fast-FXSAVE/FXRSTOR feature has no effect on FXSAVE/FXRSTOR in non 64-bit mode or when CPL > 0.
73       
74     */
75
76     // We need to assure that the fast-FXSAVE/FXRSTOR are not on
77     // otherwise we will NOT have the XMM regs since we running at CPL 0
78     //
79
80     int restore=0;
81     uint32_t high,low;
82     
83     v3_get_msr(EFER_MSR,&high,&low);
84     
85     if (low & (0x1<<14)) { 
86       // fast save is in effect
87       low &= ~(0x1<<14);
88       restore=1;
89       v3_set_msr(EFER_MSR, high, low);
90     }
91     
92     __asm__ __volatile__(" rex64/fxsave %0 ; "
93                          : "=m"(core->fp_state.state)); /* no input, no clobber */
94     if (restore) { 
95       low |= 0x1<<14;
96       v3_set_msr(EFER_MSR, high, low);
97     }
98
99     // this is a giant guess
100     // we really need to capture the state type as seen in the guest, not here...
101     core->fp_state.state_type=V3_FP_MODE_64;
102     
103     return 0;
104
105   } else {
106     return -1;
107   }
108 }
109
110
111 // Restore FP state from this structure to this core
112 int v3_put_fp_state(struct guest_info *core)
113 {
114   if (v3_can_handle_fp_state()) {
115     // We need to assure that the fast-FXSAVE/FXRSTOR are not on
116     // otherwise we will NOT have the XMM regs since we running at CPL 0
117     //
118
119     int restore=0;
120     uint32_t high,low;
121     
122     v3_get_msr(EFER_MSR,&high,&low);
123     
124     if (low & (0x1<<14)) { 
125       // fast restore is in effect
126       low &= ~(0x1<<14);
127       restore=1;
128       v3_set_msr(EFER_MSR, high, low);
129     }
130
131     __asm__ __volatile__(" rex64/fxrstor %0; "
132                          : /* no output */
133                          : "m"((core->fp_state.state)) ); /* no clobber*/
134
135     
136     if (restore) { 
137       low |= 0x1<<14;
138       v3_set_msr(EFER_MSR, high, low);
139     }
140
141     return 0;
142   } else {
143     return -1;
144   }
145 }
146
147 #ifdef V3_CONFIG_CHECKPOINT
148
149
150 int v3_save_fp_state(struct v3_chkpt_ctx *ctx, struct guest_info *core)
151 {
152   V3_CHKPT_SAVE(ctx, "FP_STATE_TYPE", core->fp_state.state_type, savefailout);
153   if (v3_chkpt_save(ctx,"FP_STATE_BLOB",sizeof(core->fp_state.state),&(core->fp_state.state))) { 
154     goto savefailout;
155   }
156   
157   return 0;
158
159  savefailout:
160   PrintError(core->vm_info,core,"Unable to save floating point state\n");
161   return -1;
162 }
163
164
165 int v3_load_fp_state(struct v3_chkpt_ctx *ctx, struct guest_info *core)
166 {
167   V3_CHKPT_LOAD(ctx, "FP_STATE_TYPE", core->fp_state.state_type, loadfailout);
168   if (v3_chkpt_load(ctx,"FP_STATE_BLOB",sizeof(core->fp_state.state),&(core->fp_state.state))) { 
169     goto loadfailout;
170   }
171   
172   return 0;
173
174  loadfailout:
175   PrintError(core->vm_info,core,"Unable to load floating point state\n");
176   return -1;
177 }
178
179 #endif