x86/fpu: Use bitfield accessors for desc_struct
authorThomas Gleixner <tglx@linutronix.de>
Mon, 28 Aug 2017 06:47:39 +0000 (08:47 +0200)
committerIngo Molnar <mingo@kernel.org>
Tue, 29 Aug 2017 10:07:25 +0000 (12:07 +0200)
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>
arch/x86/math-emu/fpu_entry.c
arch/x86/math-emu/fpu_system.h
arch/x86/math-emu/get_address.c

index 0203baefb5c0a35d9bf67f581cc0707849caaa7d..d4a7df2205b8de2576bc7cdbf8455f2fa9987b66 100644 (file)
@@ -147,7 +147,7 @@ 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;
@@ -155,11 +155,10 @@ void math_emulate(struct math_emu_info *info)
                        /* 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;
        }
index a179254a5122c4ebd3cdeef76b40cee18db66fcf..2319a257ec322d67f2250c904fa34e4cdc499e4d 100644 (file)
@@ -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)
index b8ef9f9d2ffc71ebe584af74be0cc9a51ab92b76..c48967c6a0e2b28083de2dd8fc66e18832321c14 100644 (file)
@@ -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;
@@ -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;