x86: Introduce GDT_ENTRY_INIT()
Subsystems (4)
PATCH 1/1 x86: Introduce GDT_ENTRY_INIT()
GDT_ENTRY_INIT is static initializer of desc_struct.
We already have similar macro GDT_ENTRY() but it's static initializer for u64 and it cannot be used for desc_struct.
--- arch/x86/include/asm/desc_defs.h | 6 +++++ arch/x86/include/asm/lguest.h | 5 ++- arch/x86/include/asm/stackprotector.h | 2 +- arch/x86/kernel/apm_32.c | 2 +- arch/x86/kernel/cpu/common.c | 40 ++++++++++++++++---------------- drivers/pnp/pnpbios/bioscalls.c | 5 +--- 6 files changed, 32 insertions(+), 28 deletions(-)
arch/x86/include/asm/desc_defs.h +6 -0
@@ -34,6 +34,12 @@ struct desc_struct { }; } __attribute__((packed)); +#define GDT_ENTRY_INIT (flags, base, limit) { { { \ + .a = ((limit) & 0xffff) | (((base) & 0xffff) << 16), \ + .b = (((base) & 0xff0000) >> 16) | (((flags) & 0xf0ff) << 8) | \ + ((limit) & 0xf0000) | ((base) & 0xff000000), \ + } } } +enum {GATE_INTERRUPT =0xE ,GATE_TRAP =0xF ,
arch/x86/include/asm/lguest.h +3 -2
@@ -91,8 +91,9 @@ static inline void lguest_set_ts(void) }/* Full 4G segment descriptors, suitable for CS and DS. */ -#define FULL_EXEC_SEGMENT ((struct desc_struct){ { {0x0000ffff, 0x00cf9b00} } }) -#define FULL_SEGMENT ((struct desc_struct){ { {0x0000ffff, 0x00cf9300} } }) +#define FULL_EXEC_SEGMENT \ + ((struct desc_struct)GDT_ENTRY_INIT(0xc09b, 0, 0xfffff)) +#define FULL_SEGMENT ((struct desc_struct)GDT_ENTRY_INIT(0xc093, 0, 0xfffff))#endif /* __ASSEMBLY__ */
arch/x86/include/asm/stackprotector.h +1 -1
@@ -48,7 +48,7 @@* head_32 for boot CPU and setup_per_cpu_areas() for others. */ #define GDT_STACK_CANARY_INIT \ - [GDT_ENTRY_STACK_CANARY] = { { { 0x00000018, 0x00409000 } } }, + [GDT_ENTRY_STACK_CANARY] = GDT_ENTRY_INIT(0x4090, 0, 0x18),/* * Initialize the stackprotector canary value.
arch/x86/kernel/apm_32.c +1 -1
@@ -403,7 +403,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);static DECLARE_WAIT_QUEUE_HEAD (apm_suspend_waitqueue);static struct apm_user *user_list;static DEFINE_SPINLOCK (user_list_lock); -static struct desc_struct bad_bios_desc = { { {0 ,0x00409200 } } }; +static struct desc_struct bad_bios_desc =GDT_ENTRY_INIT (0x4092 ,0 ,0 );static const char driver_version[] ="1.16ac" ;/* no spaces */
arch/x86/kernel/cpu/common.c +20 -20
@@ -71,45 +71,45 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {* TLS descriptors are currently at a different place compared to i386. * Hopefully nobody expects them at a fixed place (Wine?) */ - [GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } }, - [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } }, - [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } }, - [GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } }, - [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } }, - [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } }, + [GDT_ENTRY_KERNEL32_CS] = GDT_ENTRY_INIT(0xc09b, 0, 0xfffff), + [GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff), + [GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc093, 0, 0xfffff), + [GDT_ENTRY_DEFAULT_USER32_CS] = GDT_ENTRY_INIT(0xc0fb, 0, 0xfffff), + [GDT_ENTRY_DEFAULT_USER_DS] = GDT_ENTRY_INIT(0xc0f3, 0, 0xfffff), + [GDT_ENTRY_DEFAULT_USER_CS] = GDT_ENTRY_INIT(0xa0fb, 0, 0xfffff), #else - [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, - [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, - [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } }, - [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } }, + [GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xc09a, 0, 0xfffff), + [GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff), + [GDT_ENTRY_DEFAULT_USER_CS] = GDT_ENTRY_INIT(0xc0fa, 0, 0xfffff), + [GDT_ENTRY_DEFAULT_USER_DS] = GDT_ENTRY_INIT(0xc0f2, 0, 0xfffff),/* * Segments used for calling PnP BIOS have byte granularity. * They code segments and data segments have fixed 64k limits, * the transfer segment sizes are set at run time. */ /* 32-bit code */ - [GDT_ENTRY_PNPBIOS_CS32] = { { { 0x0000ffff, 0x00409a00 } } }, + [GDT_ENTRY_PNPBIOS_CS32] = GDT_ENTRY_INIT(0x409a, 0, 0xffff),/* 16-bit code */ - [GDT_ENTRY_PNPBIOS_CS16] = { { { 0x0000ffff, 0x00009a00 } } }, + [GDT_ENTRY_PNPBIOS_CS16] = GDT_ENTRY_INIT(0x009a, 0, 0xffff),/* 16-bit data */ - [GDT_ENTRY_PNPBIOS_DS] = { { { 0x0000ffff, 0x00009200 } } }, + [GDT_ENTRY_PNPBIOS_DS] = GDT_ENTRY_INIT(0x0092, 0, 0xffff),/* 16-bit data */ - [GDT_ENTRY_PNPBIOS_TS1] = { { { 0x00000000, 0x00009200 } } }, + [GDT_ENTRY_PNPBIOS_TS1] = GDT_ENTRY_INIT(0x0092, 0, 0),/* 16-bit data */ - [GDT_ENTRY_PNPBIOS_TS2] = { { { 0x00000000, 0x00009200 } } }, + [GDT_ENTRY_PNPBIOS_TS2] = GDT_ENTRY_INIT(0x0092, 0, 0),/* * The APM segments have byte granularity and their bases * are set at run time. All have 64k limits. */ /* 32-bit code */ - [GDT_ENTRY_APMBIOS_BASE] = { { { 0x0000ffff, 0x00409a00 } } }, + [GDT_ENTRY_APMBIOS_BASE] = GDT_ENTRY_INIT(0x409a, 0, 0xffff),/* 16-bit code */ - [GDT_ENTRY_APMBIOS_BASE+1] = { { { 0x0000ffff, 0x00009a00 } } }, + [GDT_ENTRY_APMBIOS_BASE+1] = GDT_ENTRY_INIT(0x009a, 0, 0xffff),/* data */ - [GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } }, + [GDT_ENTRY_APMBIOS_BASE+2] = GDT_ENTRY_INIT(0x4092, 0, 0xffff), - [GDT_ENTRY_ESPFIX_SS] = { { { 0x0000ffff, 0x00cf9200 } } }, - [GDT_ENTRY_PERCPU] = { { { 0x0000ffff, 0x00cf9200 } } }, + [GDT_ENTRY_ESPFIX_SS] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff), + [GDT_ENTRY_PERCPU ] =GDT_ENTRY_INIT (0xc092 ,0 ,0xfffff ), GDT_STACK_CANARY_INIT#endif } };
drivers/char/vr41xx_giu.c deleted +0 -0
drivers/pnp/pnpbios/bioscalls.c +1 -4
@@ -60,7 +60,7 @@ do { \set_desc_limit (&gdt[(selname) >>3 ], (size) -1 ); \ }while (0 ) -static struct desc_struct bad_bios_desc; +static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092, 0, 0);/* * At some point we want to use this stack frame pointer to unwind
@@ -476,9 +476,6 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header) pnp_bios_callpoint.offset = header->fields.pm16offset; pnp_bios_callpoint.segment =PNP_CS16 ; - bad_bios_desc.a =0 ; - bad_bios_desc.b =0x00409200 ; -set_desc_base (&bad_bios_desc, (unsigned long )__va (0x40UL <<4 ));set_desc_limit (&bad_bios_desc,4095 - (0x40 <<4 ));for_each_possible_cpu (i) {
[tip:x86/asm] x86: Introduce GDT_ENTRY_INIT(), fix APM
Commit-ID: 72c4d8530244264317a662de9a55cc47e6c8e9df Gitweb: http://git.kernel.org/tip/72c4d8530244264317a662de9a55cc47e6c8e9df Author: Ingo Molnar <[email protected]> AuthorDate: Mon, 3 Aug 2009 08:47:07 +0200 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 8 Aug 2009 17:47:12 +0200
x86: Introduce GDT_ENTRY_INIT(), fix APM
This crash:
[ 0.891983] calling cache_sysfs_init+0x0/0x1ee @ 1 [ 0.897251] initcall cache_sysfs_init+0x0/0x1ee returned 0 after 405 usecs [ 0.904019] calling mce_init_device+0x0/0x242 @ 1 [ 0.909124] initcall mce_init_device+0x0/0x242 returned 0 after 347 usecs [ 0.915815] calling apm_init+0x0/0x38d @ 1 [ 0.919967] apm: BIOS version 1.2 Flags 0x07 (Driver version 1.16ac) [ 0.926813] general protection fault: 0000 [#1] [ 0.927269] last sysfs file: [ 0.927269] Modules linked in: [ 0.927269] [ 0.927269] Pid: 271, comm: kapmd Not tainted (2.6.31-rc3-00100-gd520da1-dirty #311) System Product Name [ 0.927269] EIP: 00c0:[<000082b2>] EFLAGS: 00010002 CPU: 0 [ 0.927269] EIP is at 0x82b2 [ 0.927269] EAX: 0000530e EBX: 00000000 ECX: 00000102 EDX: 00000000 [ 0.927269] ESI: 00000000 EDI: f6a4bf44 EBP: 67890000 ESP: f6a4beec [ 0.927269] DS: 00c8 ES: 0000 FS: 0000 GS: 0000 SS: 0068 [ 0.927269] Process kapmd (pid: 271, ti=f6a4a000 task=f7142280 task.ti=f6a4a000) [ 0.927269] Stack: [ 0.927269] 0000828d 02160000 00b88092 f6a4bf3c c102a63d 00000060 f6a4bf3c f6a4bf44 [ 0.927269] <0> 0000007b 0000007b 00000000 00000000 00000000 00000000 560aae9e 00000000 [ 0.927269] <0> 00000200 f705fd74 00000000 c102af70 f6a4bf60 c102a6ec 0000530e 00000000 [ 0.927269] Call Trace: [ 0.927269] [<c102a63d>] ? __apm_bios_call_simple+0x7d/0x110 [ 0.927269] [<c102af70>] ? apm+0x0/0x6a0 [ 0.927269] [<c102a6ec>] ? apm_bios_call_simple+0x1c/0x50 [ 0.927269] [<c102b3f5>] ? apm+0x485/0x6a0 [ 0.927269] [<c1038e7a>] ? finish_task_switch+0x2a/0xb0 [ 0.927269] [<c164a69e>] ? schedule+0x31e/0x480 [ 0.927269] [<c102af70>] ? apm+0x0/0x6a0 [ 0.927269] [<c102af70>] ? apm+0x0/0x6a0 [ 0.927269] [<c1052654>] ? kthread+0x74/0x80 [ 0.927269] [<c10525e0>] ? kthread+0x0/0x80 [ 0.927269] [<c101d627>] ? kernel_thread_helper+0x7/0x10 [ 0.927269] Code: Bad EIP value. [ 0.927269] EIP: [<000082b2>] 0x82b2 SS:ESP 0068:f6a4beec [ 0.927269] ---[ end trace a7919e7f17c0a725 ]--- [ 0.927269] Kernel panic - not syncing: Fatal exception [ 0.927269] Pid: 271, comm: kapmd Tainted: G D 2.6.31-rc3-00100-gd520da1-dirty #311
Is caused by an incorrect GDT_ENTRY_INIT() conversion in the apm code, as noticed by hpa.
LKML-Reference: <[email protected]>
--- arch/x86/kernel/cpu/common.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/kernel/cpu/common.c +1 -1
@@ -106,7 +106,7 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { /* 16-bit code */ [GDT_ENTRY_APMBIOS_BASE+1] = GDT_ENTRY_INIT(0x009a, 0, 0xffff),/* data */ - [GDT_ENTRY_APMBIOS_BASE+2] = GDT_ENTRY_INIT(0x409a, 0, 0xffff), + [GDT_ENTRY_APMBIOS_BASE+2] = GDT_ENTRY_INIT(0x4092, 0, 0xffff), [GDT_ENTRY_ESPFIX_SS] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff), [GDT_ENTRY_PERCPU] = GDT_ENTRY_INIT(0xc092, 0, 0xfffff),
H. Peter Anvin
reviewerQuoted 17 lines · Akinobu Mita
drivers/char/vr41xx_giu.c deleted +0
-0drivers/pnp/pnpbios/bioscalls.c +1
-1@@ -60,7 +60,7 @@ do { \set_desc_limit (&gdt[(selname) >>3 ], (size) -1 ); \ }while (0 ) -static struct desc_struct bad_bios_desc; +static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092, 0, 0);/* * At some point we want to use this stack frame pointer to unwind
drivers/pnp/pnpbios/bioscalls.c void pnpbios_calls_init(union pnp_bios_install_struct *header) · line 481
Quoted 9 lines
drivers/pnp/pnpbios/bioscalls.c +0
-3@@ -476,9 +476,6 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header) pnp_bios_callpoint.offset = header->fields.pm16offset; pnp_bios_callpoint.segment =PNP_CS16 ; - bad_bios_desc.a =0 ; - bad_bios_desc.b =0x00409200 ; -set_desc_base (&bad_bios_desc, (unsigned long )__va (0x40UL <<4 ));set_desc_limit (&bad_bios_desc,4095 - (0x40 <<4 ));for_each_possible_cpu (i) {
Please also fix this hunk to do the full initialization statically instead of doing some fields statically and some dynamically.
-hpa
Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center I work for Intel. I don't speak on their behalf.
PATCH 1/1 x86: Introduce GDT_ENTRY_INIT(), initialize bad_bios_desc statically
Fully initialize bad_bios_desc statically instead of doing some fields statically and some dynamically.
--- arch/x86/kernel/apm_32.c | 19 +++++++++---------- drivers/pnp/pnpbios/bioscalls.c | 5 ++--- 2 files changed, 11 insertions(+), 13 deletions(-)
arch/x86/kernel/apm_32.c +9 -10
@@ -403,7 +403,15 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);static DECLARE_WAIT_QUEUE_HEAD (apm_suspend_waitqueue);static struct apm_user *user_list;static DEFINE_SPINLOCK (user_list_lock); -static struct desc_struct bad_bios_desc =GDT_ENTRY_INIT (0x4092 ,0 ,0 ); + +/* +* Set up a segment that references the real mode segment 0x40 +* that extends up to the end of page zero (that we have reserved). +* This is for buggy BIOS's that refer to (real mode) segment 0x40 +* even though they are called in protected mode. +*/ +static struct desc_struct bad_bios_desc =GDT_ENTRY_INIT (0x4092 , + (unsigned long )__va (0x400UL ),PAGE_SIZE -0x400 -1 );static const char driver_version[] ="1.16ac" ;/* no spaces */
@@ -2332,15 +2340,6 @@ static int __init apm_init(void) pm_flags |=PM_APM ;/* -* Set up a segment that references the real mode segment 0x40 -* that extends up to the end of page zero (that we have reserved). -* This is for buggy BIOS's that refer to (real mode) segment 0x40 -* even though they are called in protected mode. -*/ -set_desc_base (&bad_bios_desc, (unsigned long )__va (0x40UL <<4 )); -set_desc_limit (&bad_bios_desc,4095 - (0x40 <<4 )); - -/* * Set up the long jump entry point to the APM BIOS, which is called * from inline assembly. */
drivers/pnp/pnpbios/bioscalls.c +2 -3
@@ -60,7 +60,8 @@ do { \set_desc_limit (&gdt[(selname) >>3 ], (size) -1 ); \ }while (0 ) -static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092, 0, 0); +static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092, + (unsigned long )__va (0x400UL ),PAGE_SIZE -0x400 -1 );/* * At some point we want to use this stack frame pointer to unwind
@@ -476,8 +477,6 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header) pnp_bios_callpoint.offset = header->fields.pm16offset; pnp_bios_callpoint.segment =PNP_CS16 ; -set_desc_base (&bad_bios_desc, (unsigned long )__va (0x40UL <<4 )); -set_desc_limit (&bad_bios_desc,4095 - (0x40 <<4 ));for_each_possible_cpu (i) {struct desc_struct *gdt =get_cpu_gdt_table (i);if (!gdt)
[tip:x86/asm] x86: Introduce GDT_ENTRY_INIT(), initialize bad_bios_desc statically
Commit-ID: c7425314c755d5f94da7c978205c85a7c6201212 Gitweb: http://git.kernel.org/tip/c7425314c755d5f94da7c978205c85a7c6201212 Author: Akinobu Mita <[email protected]> AuthorDate: Sun, 9 Aug 2009 17:03:52 +0900 Committer: Ingo Molnar <[email protected]> CommitDate: Mon, 10 Aug 2009 11:10:52 +0200
x86: Introduce GDT_ENTRY_INIT(), initialize bad_bios_desc statically
Fully initialize bad_bios_desc statically instead of doing some fields statically and some dynamically.
LKML-Reference: <[email protected]>
--- arch/x86/kernel/apm_32.c | 19 +++++++++---------- drivers/pnp/pnpbios/bioscalls.c | 5 ++--- 2 files changed, 11 insertions(+), 13 deletions(-)
arch/x86/kernel/apm_32.c +9 -10
@@ -403,7 +403,15 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);static DECLARE_WAIT_QUEUE_HEAD (apm_suspend_waitqueue);static struct apm_user *user_list;static DEFINE_SPINLOCK (user_list_lock); -static struct desc_struct bad_bios_desc =GDT_ENTRY_INIT (0x4092 ,0 ,0 ); + +/* +* Set up a segment that references the real mode segment 0x40 +* that extends up to the end of page zero (that we have reserved). +* This is for buggy BIOS's that refer to (real mode) segment 0x40 +* even though they are called in protected mode. +*/ +static struct desc_struct bad_bios_desc =GDT_ENTRY_INIT (0x4092 , + (unsigned long )__va (0x400UL ),PAGE_SIZE -0x400 -1 );static const char driver_version[] ="1.16ac" ;/* no spaces */
@@ -2332,15 +2340,6 @@ static int __init apm_init(void) pm_flags |=PM_APM ;/* -* Set up a segment that references the real mode segment 0x40 -* that extends up to the end of page zero (that we have reserved). -* This is for buggy BIOS's that refer to (real mode) segment 0x40 -* even though they are called in protected mode. -*/ -set_desc_base (&bad_bios_desc, (unsigned long )__va (0x40UL <<4 )); -set_desc_limit (&bad_bios_desc,4095 - (0x40 <<4 )); - -/* * Set up the long jump entry point to the APM BIOS, which is called * from inline assembly. */
drivers/pnp/pnpbios/bioscalls.c +2 -3
@@ -60,7 +60,8 @@ do { \set_desc_limit (&gdt[(selname) >>3 ], (size) -1 ); \ }while (0 ) -static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092, 0, 0); +static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092, + (unsigned long )__va (0x400UL ),PAGE_SIZE -0x400 -1 );/* * At some point we want to use this stack frame pointer to unwind
@@ -476,8 +477,6 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header) pnp_bios_callpoint.offset = header->fields.pm16offset; pnp_bios_callpoint.segment =PNP_CS16 ; -set_desc_base (&bad_bios_desc, (unsigned long )__va (0x40UL <<4 )); -set_desc_limit (&bad_bios_desc,4095 - (0x40 <<4 ));for_each_possible_cpu (i) {struct desc_struct *gdt =get_cpu_gdt_table (i);if (!gdt)