Line 3: |
Line 3: |
| XSAVE stands for similar x86 instruction [https://hjlebbink.github.io/x86doc/html/XSAVE.html <code>xsave</code>] which places extended processor state into a memory area. The saving can be initiated by any userspace application at any moment and size of the memory frame depends on processor features and may vary between different models. Thus if checkpoint and restore are done on different processors the next call to <code>xsave</code> may corrupt memory if sizes mismatch. | | XSAVE stands for similar x86 instruction [https://hjlebbink.github.io/x86doc/html/XSAVE.html <code>xsave</code>] which places extended processor state into a memory area. The saving can be initiated by any userspace application at any moment and size of the memory frame depends on processor features and may vary between different models. Thus if checkpoint and restore are done on different processors the next call to <code>xsave</code> may corrupt memory if sizes mismatch. |
| | | |
− | === XSAVE frame sizes === | + | === XSAVE frame size === |
| | | |
− | Before fetching frame sizes one need to figure out if <code>xsave</code> is supported at all. This should be done by <code> | + | Before fetching frame sizes one need to figure out if <code>xsave</code> is supported at all. There are several helpers we will refer on |
− | cpuid(0x00000001, &eax, &ebx, &ecx, &edx)</code> and bits 26 and 27 are both set in <code>ecx</code> if <code>xsave</code> is supported (strictly speaking bit 27 is reserved for operating system which can clear it to indicate that instruction is disabled). | + | |
| + | static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, |
| + | unsigned int *ecx, unsigned int *edx) |
| + | { |
| + | /* ecx is often an input as well as an output. */ |
| + | asm volatile("cpuid" |
| + | : "=a" (*eax), |
| + | "=b" (*ebx), |
| + | "=c" (*ecx), |
| + | "=d" (*edx) |
| + | : "0" (*eax), "2" (*ecx) |
| + | : "memory"); |
| + | } |
| + | |
| + | static inline void cpuid(unsigned int op, |
| + | unsigned int *eax, unsigned int *ebx, |
| + | unsigned int *ecx, unsigned int *edx) |
| + | { |
| + | *eax = op; |
| + | *ecx = 0; |
| + | native_cpuid(eax, ebx, ecx, edx); |
| + | } |
| + | |
| + | static inline void cpuid_count(unsigned int op, int count, |
| + | unsigned int *eax, unsigned int *ebx, |
| + | unsigned int *ecx, unsigned int *edx) |
| + | { |
| + | *eax = op; |
| + | *ecx = count; |
| + | native_cpuid(eax, ebx, ecx, edx); |
| + | } |
| + | |
| + | Run <code> cpuid(0x1, &eax, &ebx, &ecx, &edx)</code> and bits 26 and 27 are both set in <code>ecx</code> if <code>xsave</code> is supported (strictly speaking bit 27 is reserved for operating system which can clear it to indicate that instruction is disabled). |
| + | |
| + | After that we can fetch maximal frame size which applications may use via <code>cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx)</code> |