Skip to content

Commit 7496d64

Browse files
Fenghua YuH. Peter Anvin
authored andcommitted
Define kernel API to get address of each state in xsave area
In standard form, each state is saved in the xsave area in fixed offset. But in compacted form, offset of each saved state only can be calculated during run time because some xstates may not be enabled and saved. We define kernel API get_xsave_addr() returns address of a given state saved in a xsave area. It can be called in kernel to get address of each xstate in xsave area in either standard format or compacted format. It's useful when kernel wants to directly access each state in xsave area. Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> Link: http://lkml.kernel.org/r/1401387164-43416-17-git-send-email-fenghua.yu@intel.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
1 parent 7e7ce87 commit 7496d64

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

arch/x86/include/asm/xsave.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,4 +255,7 @@ static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask)
255255
return err;
256256
}
257257

258+
void *get_xsave_addr(struct xsave_struct *xsave, int xstate);
259+
void setup_xstate_comp(void);
260+
258261
#endif

arch/x86/kernel/process.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ void arch_task_cache_init(void)
9393
kmem_cache_create("task_xstate", xstate_size,
9494
__alignof__(union thread_xstate),
9595
SLAB_PANIC | SLAB_NOTRACK, NULL);
96+
setup_xstate_comp();
9697
}
9798

9899
/*

arch/x86/kernel/xsave.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,47 @@ static void __init setup_xstate_features(void)
481481
} while (1);
482482
}
483483

484+
/*
485+
* This function sets up offsets and sizes of all extended states in
486+
* xsave area. This supports both standard format and compacted format
487+
* of the xsave aread.
488+
*
489+
* Input: void
490+
* Output: void
491+
*/
492+
void setup_xstate_comp(void)
493+
{
494+
int i;
495+
496+
xstate_comp_offsets = kmalloc(xstate_features * sizeof(int),
497+
GFP_KERNEL);
498+
xstate_comp_sizes = kmalloc(xstate_features * sizeof(int), GFP_KERNEL);
499+
500+
if (!cpu_has_xsaves) {
501+
for (i = 2; i < xstate_features; i++) {
502+
if (test_bit(i, (unsigned long *)&pcntxt_mask)) {
503+
xstate_comp_offsets[i] = xstate_offsets[i];
504+
xstate_comp_sizes[i] = xstate_sizes[i];
505+
}
506+
}
507+
return;
508+
}
509+
510+
xstate_comp_offsets[2] = FXSAVE_SIZE + XSAVE_HDR_SIZE;
511+
512+
for (i = 2; i < xstate_features; i++) {
513+
if (test_bit(i, (unsigned long *)&pcntxt_mask))
514+
xstate_comp_sizes[i] = xstate_sizes[i];
515+
else
516+
xstate_comp_sizes[i] = 0;
517+
518+
if (i > 2)
519+
xstate_comp_offsets[i] = xstate_comp_offsets[i-1]
520+
+ xstate_comp_sizes[i-1];
521+
522+
}
523+
}
524+
484525
/*
485526
* setup the xstate image representing the init state
486527
*/
@@ -668,3 +709,26 @@ void eager_fpu_init(void)
668709
else
669710
fxrstor_checking(&init_xstate_buf->i387);
670711
}
712+
713+
/*
714+
* Given the xsave area and a state inside, this function returns the
715+
* address of the state.
716+
*
717+
* This is the API that is called to get xstate address in either
718+
* standard format or compacted format of xsave area.
719+
*
720+
* Inputs:
721+
* xsave: base address of the xsave area;
722+
* xstate: state which is defined in xsave.h (e.g. XSTATE_FP, XSTATE_SSE,
723+
* etc.)
724+
* Output:
725+
* address of the state in the xsave area.
726+
*/
727+
void *get_xsave_addr(struct xsave_struct *xsave, int xstate)
728+
{
729+
int feature = fls64(xstate) - 1;
730+
if (!test_bit(feature, (unsigned long *)&pcntxt_mask))
731+
return NULL;
732+
733+
return (void *)xsave + xstate_comp_offsets[feature];
734+
}

0 commit comments

Comments
 (0)