Skip to content

Commit

Permalink
x86/fpu: Use bitfield accessors for desc_struct
Browse files Browse the repository at this point in the history
desc_struct is a union of u32 fields and bitfields. The access to the u32
fields is done with magic macros.

Convert it to use the bitfields and replace the macro magic with parseable
inline functions.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/20170828064958.042406718@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Thomas Gleixner authored and Ingo Molnar committed Aug 29, 2017
1 parent 1dd439f commit 718f5d0
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 25 deletions.
11 changes: 5 additions & 6 deletions arch/x86/math-emu/fpu_entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,19 +147,18 @@ void math_emulate(struct math_emu_info *info)
}

code_descriptor = FPU_get_ldt_descriptor(FPU_CS);
if (SEG_D_SIZE(code_descriptor)) {
if (code_descriptor.d) {
/* The above test may be wrong, the book is not clear */
/* Segmented 32 bit protected mode */
addr_modes.default_mode = SEG32;
} else {
/* 16 bit protected mode */
addr_modes.default_mode = PM16;
}
FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
code_limit = code_base
+ (SEG_LIMIT(code_descriptor) +
1) * SEG_GRANULARITY(code_descriptor)
- 1;
FPU_EIP += code_base = seg_get_base(&code_descriptor);
code_limit = seg_get_limit(&code_descriptor) + 1;
code_limit *= seg_get_granularity(&code_descriptor);
code_limit += code_base - 1;
if (code_limit < code_base)
code_limit = 0xffffffff;
}
Expand Down
48 changes: 37 additions & 11 deletions arch/x86/math-emu/fpu_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,43 @@ static inline struct desc_struct FPU_get_ldt_descriptor(unsigned seg)
return ret;
}

#define SEG_D_SIZE(x) ((x).b & (3 << 21))
#define SEG_G_BIT(x) ((x).b & (1 << 23))
#define SEG_GRANULARITY(x) (((x).b & (1 << 23)) ? 4096 : 1)
#define SEG_286_MODE(x) ((x).b & ( 0xff000000 | 0xf0000 | (1 << 23)))
#define SEG_BASE_ADDR(s) (((s).b & 0xff000000) \
| (((s).b & 0xff) << 16) | ((s).a >> 16))
#define SEG_LIMIT(s) (((s).b & 0xff0000) | ((s).a & 0xffff))
#define SEG_EXECUTE_ONLY(s) (((s).b & ((1 << 11) | (1 << 9))) == (1 << 11))
#define SEG_WRITE_PERM(s) (((s).b & ((1 << 11) | (1 << 9))) == (1 << 9))
#define SEG_EXPAND_DOWN(s) (((s).b & ((1 << 11) | (1 << 10))) \
== (1 << 10))
#define SEG_TYPE_WRITABLE (1U << 1)
#define SEG_TYPE_EXPANDS_DOWN (1U << 2)
#define SEG_TYPE_EXECUTE (1U << 3)
#define SEG_TYPE_EXPAND_MASK (SEG_TYPE_EXPANDS_DOWN | SEG_TYPE_EXECUTE)
#define SEG_TYPE_EXECUTE_MASK (SEG_TYPE_WRITABLE | SEG_TYPE_EXECUTE)

static inline unsigned long seg_get_base(struct desc_struct *d)
{
unsigned long base = (unsigned long)d->base2 << 24;

return base | ((unsigned long)d->base1 << 16) | d->base0;
}

static inline unsigned long seg_get_limit(struct desc_struct *d)
{
return ((unsigned long)d->limit << 16) | d->limit0;
}

static inline unsigned long seg_get_granularity(struct desc_struct *d)
{
return d->g ? 4096 : 1;
}

static inline bool seg_expands_down(struct desc_struct *d)
{
return (d->type & SEG_TYPE_EXPAND_MASK) == SEG_TYPE_EXPANDS_DOWN;
}

static inline bool seg_execute_only(struct desc_struct *d)
{
return (d->type & SEG_TYPE_EXECUTE_MASK) == SEG_TYPE_EXECUTE;
}

static inline bool seg_writable(struct desc_struct *d)
{
return (d->type & SEG_TYPE_EXECUTE_MASK) == SEG_TYPE_WRITABLE;
}

#define I387 (&current->thread.fpu.state)
#define FPU_info (I387->soft.info)
Expand Down
17 changes: 9 additions & 8 deletions arch/x86/math-emu/get_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,18 @@ static long pm_address(u_char FPU_modrm, u_char segment,
}

descriptor = FPU_get_ldt_descriptor(addr->selector);
base_address = SEG_BASE_ADDR(descriptor);
base_address = seg_get_base(&descriptor);
address = base_address + offset;
limit = base_address
+ (SEG_LIMIT(descriptor) + 1) * SEG_GRANULARITY(descriptor) - 1;
limit = seg_get_limit(&descriptor) + 1;
limit *= seg_get_granularity(&descriptor);
limit += base_address - 1;
if (limit < base_address)
limit = 0xffffffff;

if (SEG_EXPAND_DOWN(descriptor)) {
if (SEG_G_BIT(descriptor))
if (seg_expands_down(&descriptor)) {
if (descriptor.g) {
seg_top = 0xffffffff;
else {
} else {
seg_top = base_address + (1 << 20);
if (seg_top < base_address)
seg_top = 0xffffffff;
Expand All @@ -182,8 +183,8 @@ static long pm_address(u_char FPU_modrm, u_char segment,
(address > limit) || (address < base_address) ? 0 :
((limit - address) >= 254 ? 255 : limit - address + 1);
}
if (SEG_EXECUTE_ONLY(descriptor) ||
(!SEG_WRITE_PERM(descriptor) && (FPU_modrm & FPU_WRITE_BIT))) {
if (seg_execute_only(&descriptor) ||
(!seg_writable(&descriptor) && (FPU_modrm & FPU_WRITE_BIT))) {
access_limit = 0;
}
return address;
Expand Down

0 comments on commit 718f5d0

Please sign in to comment.