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.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2013, Peter Dinda <pdinda@northwestern.edu>
11 * Copyright (c) 2013, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Peter Dinda <pdinda@northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
23 #include <palacios/vmm_types.h>
24 #include <palacios/vmm.h>
25 #ifdef V3_CONFIG_LAZY_FPU_SWITCH
26 #include <interfaces/vmm_lazy_fpu.h>
29 // the FPRs are arranged into the
30 // precise layout of the FXSAVE/FXRESTORE instructions
31 // bytes 32+, which is common for all three variants
32 // 8*6 reserved + 8*10 (fpu/mmx) + 16*16 (xmm)
33 // + 3*16 (res) + 3*16 (ava) = 480 bytes
34 // another 32 bytes are used for the store header
35 // which varies depending on machine mode
37 v3_fp_mmx_reg_t stmm0; // stmm0..7 are the x87 stack or mmx regs
39 v3_fp_mmx_reg_t stmm1;
41 v3_fp_mmx_reg_t stmm2;
43 v3_fp_mmx_reg_t stmm3;
45 v3_fp_mmx_reg_t stmm4;
47 v3_fp_mmx_reg_t stmm5;
49 v3_fp_mmx_reg_t stmm6;
51 v3_fp_mmx_reg_t stmm7;
53 v3_xmm_reg_t xmm0; // xmm0..7 are the "classic" SSE regs
61 v3_xmm_reg_t xmm8; //xmm8..15 are the "new" SSE reg
69 v3_xmm_reg_t res16; // reserved
75 } __attribute__((packed)) __attribute__((aligned(16)));
77 // FXSAVE, 32 bit mode header (32 bytes)
79 struct v3_fp_32_state {
85 uint32_t fip; //fpu instruction pointer
86 uint16_t fcs; //fpu code segment selector
88 uint32_t fdp; //fpu data pointer
89 uint16_t fds; //fpu data segment selector
93 } __attribute__((packed)) __attribute__((aligned(16)));
95 // FXSAVE, 64 bit mode header, REX.W=1 (32 bytes)
97 struct v3_fp_64_state {
103 uint64_t fip; //fpu instruction pointer
104 uint64_t fdp; //fpu data pointer
107 } __attribute__((packed)) __attribute__((aligned(16)));
110 // FXSAVE, 64 bit mode header, REX.W=0 (32 bytes)
111 // V3_FP_MODE_64_COMPAT
112 struct v3_fp_64compat_state {
118 uint32_t fip; //fpu instruction pointer
119 uint16_t fcs; //fpu code segment selector
121 uint32_t fdp; //fpu data pointer
122 uint16_t fds; //fpu data segment selector
126 } __attribute__((packed)) __attribute__((aligned(16)));
130 // This is an FXSAVE block
132 struct v3_fp_state_core {
134 struct v3_fp_32_state fp32;
135 struct v3_fp_64_state fp64;
136 struct v3_fp_64compat_state fp64compat;
138 struct v3_fp_regs fprs;
139 } __attribute__((packed)) __attribute__((aligned(16)));
142 // Do we need to restore on next entry?
145 enum {V3_FP_MODE_32=0, V3_FP_MODE_64, V3_FP_MODE_64_COMPAT} state_type;
146 struct v3_fp_state_core state __attribute__((aligned(16)));
152 // Can we save FP state on this core?
153 int v3_can_handle_fp_state();
155 // Save state from this core to the structure
156 int v3_get_fp_state(struct guest_info *core);
158 // Restore FP state from this structure to this core
159 int v3_put_fp_state(struct guest_info *core);
161 int v3_init_fp(void);
162 int v3_deinit_fp(void);
164 #ifndef V3_CONFIG_FP_SWITCH
166 /* Ideally these would use the TS trick to do lazy calls to used_fpu() */
167 #define V3_FP_EXIT_SAVE(core)
169 #define V3_FP_ENTRY_RESTORE(core) \
171 if ((core)->fp_state.need_restore) { \
172 v3_put_fp_state(core); \
173 (core)->fp_state.need_restore=0; \
179 #ifdef V3_CONFIG_LAZY_FPU_SWITCH
182 /* Ideally these would use the TS trick to do lazy calls to used_fpu() */
183 #define V3_FP_EXIT_SAVE(core) \
185 extern struct v3_lazy_fpu_hooks * lazy_fpu_hooks; \
186 if ((lazy_fpu_hooks) && (lazy_fpu_hooks)->used_fpu) { \
187 (lazy_fpu_hooks)->used_fpu(); \
189 v3_get_fp_state(core); \
193 #define V3_FP_ENTRY_RESTORE(core) \
195 extern struct v3_lazy_fpu_hooks * lazy_fpu_hooks; \
196 if ((core)->fp_state.need_restore) { \
197 v3_put_fp_state(core); \
198 (core)->fp_state.need_restore=0; \
200 if ((lazy_fpu_hooks) && (lazy_fpu_hooks)->will_use_fpu) { \
201 (lazy_fpu_hooks)->need_fpu(); \
203 v3_put_fp_state(core); \
210 // conservative FPU switching
212 #define V3_FP_EXIT_SAVE(core) v3_get_fp_state(core)
213 #define V3_FP_ENTRY_RESTORE(core) v3_put_fp_state(core)
219 #ifdef V3_CONFIG_CHECKPOINT
223 // save state from structure to checkpoint/migration context
224 int v3_save_fp_state(struct v3_chkpt_ctx *ctx, struct guest_info *core);
226 // load state from checkpoint/migration context to structure
227 int v3_load_fp_state(struct v3_chkpt_ctx *ctx, struct guest_info *core);