Fix FPU interface changes
PATCH 2/4 Fix FPU interface changes
The FPU interface changed to dynamic allocation; redefine the missing struct fpu to be a static structure and add back the old macros.
Quoted 1 line
From
95be2b1ac41a40f2f3d581f0674b25ca4b70a025Mon Sep 17 00:00:00 2001
From: Zachary Amsden <[email protected]>
Date: Tue, 25 May 2010 16:32:14 -1000
Subject: [PATCH 2/5] Extend module compatability to FPU code
--- x86/external-module-compat.h | 84 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 84 insertions(+), 0 deletions(-)
x86/external-module-compat.h +84 -0
@@ -788,3 +788,87 @@ struct kvm_pvclock_vcpu_time_info {#else #define kvm_pvclock_vcpu_time_info pvclock_vcpu_time_info#endif + +#if LINUX_VERSION_CODE <KERNEL_VERSION (2 ,6 ,34 ) +#include <asm/processor.h> +#include <asm/i387.h> +struct _fpu { +struct i387_fxsave_struct fxsave; +struct i387_fxsave_struct host_fx_image; +}; + +struct fpu { +struct _fpu *state; +struct _fpu state_static; +}; + +static inline bool fpu_allocated (struct fpu *fpu) +{ + fpu->state = &fpu->state_static; +return true; +} + +static inline int fpu_alloc (struct fpu *fpu) +{ + fpu->state = &fpu->state_static; +return 0 ; +} + +static inline void fpu_free (struct fpu *fpu) +{ +} + +static inline void kvm_fx_finit (void ) +{ + asm("finit" ); +} + +static inline void kvm_fx_save (struct i387_fxsave_struct *image) +{ + asm("fxsave (%0)" ::"r" (image)); +} + +static inline void kvm_fx_restore (struct i387_fxsave_struct *image) +{ + asm("fxrstor (%0)" ::"r" (image)); +} + +static inline void fpu_finit (struct fpu *fpu) +{ +unsigned after_mxcsr_mask; + +/* +* Touch the fpu the first time in non atomic context as if +* this is the first fpu instruction the exception handler +* will fire before the instruction returns and it'll have to +* allocate ram with GFP_KERNEL. +*/ +if (!used_math ()) +kvm_fx_save (&fpu->state->host_fx_image); + +/* Initialize guest FPU by resetting ours and saving into guest's */ +preempt_disable (); +kvm_fx_save (&fpu->state->host_fx_image); +kvm_fx_finit (); +kvm_fx_save (&fpu->state->fxsave); +kvm_fx_restore (&fpu->state->host_fx_image); +preempt_enable (); + + after_mxcsr_mask = offsetof(struct i387_fxsave_struct , st_space); + fpu->state->fxsave.mxcsr =0x1f80 ; +memset ((void *)&fpu->state->fxsave + after_mxcsr_mask, +0 ,sizeof (struct i387_fxsave_struct ) - after_mxcsr_mask); +} + +static inline void fpu_restore_checking (struct fpu *fpu) +{ +kvm_fx_save (&fpu->state->host_fx_image); +kvm_fx_restore (&fpu->state->fxsave); +} + +static inline void fpu_save_init (struct fpu *fpu) +{ +kvm_fx_save (&fpu->state->fxsave); +kvm_fx_restore (&fpu->state->host_fx_image); +} +#endif
Signature · 1 line
1.7.0.1
Quoted 22 lines · Zachary Amsden
The FPU interface changed to dynamic allocation; redefine the missing struct fpu to be a static structure and add back the old macros.
The FPU interface changed to dynamic allocation; redefine the missing struct fpu to be a static structure and add back the old macros.
From
95be2b1ac41a40f2f3d581f0674b25ca4b70a025Mon Sep 17 00:00:00 2001
From: Zachary Amsden <[email protected]>
Date: Tue, 25 May 2010 16:32:14 -1000
Subject: [PATCH 2/5] Extend module compatability to FPU codeSigned-off-by Zachary Amsden <[email protected]>--- x86/external-module-compat.h | 84 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 84 insertions(+), 0 deletions(-)x86/external-module-compat.h +0
-0
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 792
Quoted 5 lines
x86/external-module-compat.h +2
-0@@ -788,3 +788,87 @@ struct kvm_pvclock_vcpu_time_info {#else #define kvm_pvclock_vcpu_time_info pvclock_vcpu_time_info#endif + +#if LINUX_VERSION_CODE <KERNEL_VERSION (2 ,6 ,34 )
The FPU changes look like 2.6.36 material.
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 797
Quoted 5 lines
x86/external-module-compat.h +5
-0+#include <asm/processor.h> +#include <asm/i387.h> +struct _fpu { +struct i387_fxsave_struct fxsave; +struct i387_fxsave_struct host_fx_image;
The original code before 9144b51caf only used a single state - for the guest.
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 809
Quoted 12 lines
x86/external-module-compat.h +12
-0+}; + +struct fpu { +struct _fpu *state; +struct _fpu state_static; +}; + +static inline bool fpu_allocated (struct fpu *fpu) +{ + fpu->state = &fpu->state_static; +return true; +}
Unused.
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 815
Quoted 6 lines
x86/external-module-compat.h +6
-0+ +static inline int fpu_alloc (struct fpu *fpu) +{ + fpu->state = &fpu->state_static; +return 0 ; +}
That's smarter than the dumb copy of upstream fpu_alloc that I hacked up.
Quoted 30 lines
x86/external-module-compat.h +30
-0+ +static inline void fpu_free (struct fpu *fpu) +{ +} + +static inline void kvm_fx_finit (void ) +{ + asm("finit" ); +} + +static inline void kvm_fx_save (struct i387_fxsave_struct *image) +{ + asm("fxsave (%0)" ::"r" (image)); +} + +static inline void kvm_fx_restore (struct i387_fxsave_struct *image) +{ + asm("fxrstor (%0)" ::"r" (image)); +} + +static inline void fpu_finit (struct fpu *fpu) +{ +unsigned after_mxcsr_mask; + +/* +* Touch the fpu the first time in non atomic context as if +* this is the first fpu instruction the exception handler +* will fire before the instruction returns and it'll have to +* allocate ram with GFP_KERNEL. +*/
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 855
Quoted 10 lines
x86/external-module-compat.h +10
-0+if (!used_math ()) +kvm_fx_save (&fpu->state->host_fx_image); + +/* Initialize guest FPU by resetting ours and saving into guest's */ +preempt_disable (); +kvm_fx_save (&fpu->state->host_fx_image); +kvm_fx_finit (); +kvm_fx_save (&fpu->state->fxsave); +kvm_fx_restore (&fpu->state->host_fx_image); +preempt_enable ();
The original KVM code before 9144b51caf just did finit+fxsave. Why this saving/restoring of the host state?
Quoted 8 lines
x86/external-module-compat.h +8
-0+ + after_mxcsr_mask = offsetof(struct i387_fxsave_struct , st_space); + fpu->state->fxsave.mxcsr =0x1f80 ; +memset ((void *)&fpu->state->fxsave + after_mxcsr_mask, +0 ,sizeof (struct i387_fxsave_struct ) - after_mxcsr_mask); +} + +static inline void fpu_restore_checking (struct fpu *fpu)
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 873
Quoted 10 lines
x86/external-module-compat.h +10
-0+{ +kvm_fx_save (&fpu->state->host_fx_image); +kvm_fx_restore (&fpu->state->fxsave); +} + +static inline void fpu_save_init (struct fpu *fpu) +{ +kvm_fx_save (&fpu->state->fxsave); +kvm_fx_restore (&fpu->state->host_fx_image); +}
Also here: Why bother about the host state?
Jan
Quoted 19 lines · Jan Kiszka
Quoted 17 lines · Zachary Amsden
The FPU interface changed to dynamic allocation; redefine the missing struct fpu to be a static structure and add back the old macros.
The FPU interface changed to dynamic allocation; redefine the missing struct fpu to be a static structure and add back the old macros.
From
95be2b1ac41a40f2f3d581f0674b25ca4b70a025Mon Sep 17 00:00:00 2001
From: Zachary Amsden<[email protected]>
Date: Tue, 25 May 2010 16:32:14 -1000
Subject: [PATCH 2/5] Extend module compatability to FPU codeSigned-off-by Zachary Amsden<[email protected]>--- x86/external-module-compat.h | 84 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 84 insertions(+), 0 deletions(-)
Quoted 13 lines
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 792
Quoted 11 lines
x86/external-module-compat.h +2
-0@@ -788,3 +788,87 @@ struct kvm_pvclock_vcpu_time_info {#else #define kvm_pvclock_vcpu_time_info pvclock_vcpu_time_info#endif + +#if LINUX_VERSION_CODE <KERNEL_VERSION (2 ,6 ,34 )The FPU changes look like 2.6.36 material.
It's quite likely I got the version wrong.
Quoted 71 lines
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 797
Quoted 6 lines
x86/external-module-compat.h +5
-0+#include <asm/processor.h> +#include <asm/i387.h> +struct _fpu { +struct i387_fxsave_struct fxsave; +struct i387_fxsave_struct host_fx_image;The original code before
9144b51cafonly used a single state - for the guest.x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 809
Quoted 13 lines
x86/external-module-compat.h +12
-0+}; + +struct fpu { +struct _fpu *state; +struct _fpu state_static; +}; + +static inline bool fpu_allocated (struct fpu *fpu) +{ + fpu->state =&fpu->state_static; +return true; +}Unused.
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 815
Quoted 7 lines
x86/external-module-compat.h +6
-0+ +static inline int fpu_alloc (struct fpu *fpu) +{ + fpu->state =&fpu->state_static; +return 0 ; +}That's smarter than the dumb copy of upstream
fpu_allocthat I hacked up.Quoted 35 lines
x86/external-module-compat.h +35
-0+ +static inline void fpu_free (struct fpu *fpu) +{ +} + +static inline void kvm_fx_finit (void ) +{ + asm("finit" ); +} + +static inline void kvm_fx_save (struct i387_fxsave_struct *image) +{ + asm("fxsave (%0)" ::"r" (image)); +} + +static inline void kvm_fx_restore (struct i387_fxsave_struct *image) +{ + asm("fxrstor (%0)" ::"r" (image)); +} + +static inline void fpu_finit (struct fpu *fpu) +{ +unsigned after_mxcsr_mask; + +/* +* Touch the fpu the first time in non atomic context as if +* this is the first fpu instruction the exception handler +* will fire before the instruction returns and it'll have to +* allocate ram with GFP_KERNEL. +*/ +if (!used_math ()) +kvm_fx_save (&fpu->state->host_fx_image); + +/* Initialize guest FPU by resetting ours and saving into guest's */ +preempt_disable ();
Quoted 9 lines
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 855
Quoted 6 lines
x86/external-module-compat.h +5
-0+kvm_fx_save (&fpu->state->host_fx_image); +kvm_fx_finit (); +kvm_fx_save (&fpu->state->fxsave); +kvm_fx_restore (&fpu->state->host_fx_image); +preempt_enable ();The original KVM code before
9144b51cafjust did finit+fxsave. Why this saving/restoring of the host state?
It looks like the new FPU contract allows one to "allocate" an FPU context for the thread. Older kernels might have some other thread's FPU state lazily lying around? It wasn't clear, I didn't care to check all kernel, and this code is verbatim from 2.6.33 asm/i387.h
Quoted 12 lines
Quoted 12 lines
x86/external-module-compat.h +12
-0+ + after_mxcsr_mask = offsetof(struct i387_fxsave_struct , st_space); + fpu->state->fxsave.mxcsr =0x1f80 ; +memset ((void *)&fpu->state->fxsave + after_mxcsr_mask, +0 ,sizeof (struct i387_fxsave_struct ) - after_mxcsr_mask); +} + +static inline void fpu_restore_checking (struct fpu *fpu) +{ +kvm_fx_save (&fpu->state->host_fx_image); +kvm_fx_restore (&fpu->state->fxsave); +}
Quoted 9 lines
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 873
Quoted 7 lines
x86/external-module-compat.h +6
-0+ +static inline void fpu_save_init (struct fpu *fpu) +{ +kvm_fx_save (&fpu->state->fxsave); +kvm_fx_restore (&fpu->state->host_fx_image); +}Also here: Why bother about the host state?
Ditto.
Quoted 121 lines · Zachary Amsden
Quoted 21 lines · Jan Kiszka
Quoted 19 lines · Zachary Amsden
The FPU interface changed to dynamic allocation; redefine the missing struct fpu to be a static structure and add back the old macros.
The FPU interface changed to dynamic allocation; redefine the missing struct fpu to be a static structure and add back the old macros.
From
95be2b1ac41a40f2f3d581f0674b25ca4b70a025Mon Sep 17 00:00:00 2001
From: Zachary Amsden<[email protected]>
Date: Tue, 25 May 2010 16:32:14 -1000
Subject: [PATCH 2/5] Extend module compatability to FPU codeSigned-off-by Zachary Amsden<[email protected]>--- x86/external-module-compat.h | 84 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 84 insertions(+), 0 deletions(-)Quoted 13 lines
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 792
Quoted 11 lines
x86/external-module-compat.h +2
-0@@ -788,3 +788,87 @@ struct kvm_pvclock_vcpu_time_info {#else #define kvm_pvclock_vcpu_time_info pvclock_vcpu_time_info#endif + +#if LINUX_VERSION_CODE <KERNEL_VERSION (2 ,6 ,34 )The FPU changes look like 2.6.36 material.
It's quite likely I got the version wrong.
Quoted 72 lines
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 797
Quoted 6 lines
x86/external-module-compat.h +5
-0+#include <asm/processor.h> +#include <asm/i387.h> +struct _fpu { +struct i387_fxsave_struct fxsave; +struct i387_fxsave_struct host_fx_image;The original code before
9144b51cafonly used a single state - for the guest.x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 809
Quoted 13 lines
x86/external-module-compat.h +12
-0+}; + +struct fpu { +struct _fpu *state; +struct _fpu state_static; +}; + +static inline bool fpu_allocated (struct fpu *fpu) +{ + fpu->state =&fpu->state_static; +return true; +}Unused.
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 815
Quoted 7 lines
x86/external-module-compat.h +6
-0+ +static inline int fpu_alloc (struct fpu *fpu) +{ + fpu->state =&fpu->state_static; +return 0 ; +}That's smarter than the dumb copy of upstream
fpu_allocthat I hacked up.Quoted 36 lines
x86/external-module-compat.h +34
-0+ +static inline void fpu_free (struct fpu *fpu) +{ +} + +static inline void kvm_fx_finit (void ) +{ + asm("finit" ); +} + +static inline void kvm_fx_save (struct i387_fxsave_struct *image) +{ + asm("fxsave (%0)" ::"r" (image)); +} + +static inline void kvm_fx_restore (struct i387_fxsave_struct *image) +{ + asm("fxrstor (%0)" ::"r" (image)); +} + +static inline void fpu_finit (struct fpu *fpu) +{ +unsigned after_mxcsr_mask; + +/* +* Touch the fpu the first time in non atomic context as if +* this is the first fpu instruction the exception handler +* will fire before the instruction returns and it'll have to +* allocate ram with GFP_KERNEL. +*/ +if (!used_math ()) +kvm_fx_save (&fpu->state->host_fx_image); + +/* Initialize guest FPU by resetting ours and saving into guest's */
+preempt_disable();Quoted 9 lines
x86/external-module-compat.h struct kvm_pvclock_vcpu_time_info { · line 855
Quoted 6 lines
x86/external-module-compat.h +5
-0+kvm_fx_save (&fpu->state->host_fx_image); +kvm_fx_finit (); +kvm_fx_save (&fpu->state->fxsave); +kvm_fx_restore (&fpu->state->host_fx_image); +preempt_enable ();The original KVM code before
9144b51cafjust did finit+fxsave. Why this saving/restoring of the host state?
Quoted 4 lines
It looks like the new FPU contract allows one to "allocate" an FPU context for the thread. Older kernels might have some other thread's FPU state lazily lying around? It wasn't clear, I didn't care to check all kernel, and this code is verbatim from 2.6.33
asm/i387.h
I think it's safe to assume that previous KVM code, including that which is delivered with 2.6.33 or .34, is sufficient for our purpose. So I basically implanted it into the wrappers you can find in my next branch. Builds are fine for all versions (I'm now just waiting for the final warnings fix being merged). And it works fine for me, but I only tested with a 2.6.27 host kernel. Please give it a try.
Jan