diff options
| author | Akinobu Mita <akinobu.mita@gmail.com> | 2009-07-18 11:11:06 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-07-19 12:27:52 -0400 |
| commit | 57594742a2b545f8f114cda34f15650be8ae976d (patch) | |
| tree | 2682b10d68f3fb33aa047fa2a3ff6db2061c0740 | |
| parent | fde0312d01b60a3fd5dc56e69a9613defbbc7097 (diff) | |
x86: Introduce set_desc_base() and set_desc_limit()
Rename set_base()/set_limit to set_desc_base()/set_desc_limit()
and rewrite them in C. These are naturally introduced by the
idea of get_desc_base()/get_desc_limit().
The conversion actually found the bug in apm_32.c:
bad_bios_desc is written at run-time, but it is defined const
variable.
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
LKML-Reference: <20090718151105.GC11294@localhost.localdomain>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
| -rw-r--r-- | arch/x86/include/asm/desc.h | 13 | ||||
| -rw-r--r-- | arch/x86/include/asm/stackprotector.h | 4 | ||||
| -rw-r--r-- | arch/x86/include/asm/system.h | 27 | ||||
| -rw-r--r-- | arch/x86/kernel/apm_32.c | 18 | ||||
| -rw-r--r-- | drivers/pnp/pnpbios/bioscalls.c | 21 |
5 files changed, 34 insertions, 49 deletions
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h index c993e9e0fed4..e8de2f6f5ca5 100644 --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h | |||
| @@ -291,11 +291,24 @@ static inline unsigned long get_desc_base(const struct desc_struct *desc) | |||
| 291 | return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24); | 291 | return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24); |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | static inline void set_desc_base(struct desc_struct *desc, unsigned long base) | ||
| 295 | { | ||
| 296 | desc->base0 = base & 0xffff; | ||
| 297 | desc->base1 = (base >> 16) & 0xff; | ||
| 298 | desc->base2 = (base >> 24) & 0xff; | ||
| 299 | } | ||
| 300 | |||
| 294 | static inline unsigned long get_desc_limit(const struct desc_struct *desc) | 301 | static inline unsigned long get_desc_limit(const struct desc_struct *desc) |
| 295 | { | 302 | { |
| 296 | return desc->limit0 | (desc->limit << 16); | 303 | return desc->limit0 | (desc->limit << 16); |
| 297 | } | 304 | } |
| 298 | 305 | ||
| 306 | static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit) | ||
| 307 | { | ||
| 308 | desc->limit0 = limit & 0xffff; | ||
| 309 | desc->limit = (limit >> 16) & 0xf; | ||
| 310 | } | ||
| 311 | |||
| 299 | static inline void _set_gate(int gate, unsigned type, void *addr, | 312 | static inline void _set_gate(int gate, unsigned type, void *addr, |
| 300 | unsigned dpl, unsigned ist, unsigned seg) | 313 | unsigned dpl, unsigned ist, unsigned seg) |
| 301 | { | 314 | { |
diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h index c2d742c6e15f..cdc5e0b126a7 100644 --- a/arch/x86/include/asm/stackprotector.h +++ b/arch/x86/include/asm/stackprotector.h | |||
| @@ -90,9 +90,7 @@ static inline void setup_stack_canary_segment(int cpu) | |||
| 90 | struct desc_struct desc; | 90 | struct desc_struct desc; |
| 91 | 91 | ||
| 92 | desc = gdt_table[GDT_ENTRY_STACK_CANARY]; | 92 | desc = gdt_table[GDT_ENTRY_STACK_CANARY]; |
| 93 | desc.base0 = canary & 0xffff; | 93 | set_desc_base(&desc, canary); |
| 94 | desc.base1 = (canary >> 16) & 0xff; | ||
| 95 | desc.base2 = (canary >> 24) & 0xff; | ||
| 96 | write_gdt_entry(gdt_table, GDT_ENTRY_STACK_CANARY, &desc, DESCTYPE_S); | 94 | write_gdt_entry(gdt_table, GDT_ENTRY_STACK_CANARY, &desc, DESCTYPE_S); |
| 97 | #endif | 95 | #endif |
| 98 | } | 96 | } |
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 643c59b4bc6e..75c49c782e20 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h | |||
| @@ -150,33 +150,6 @@ do { \ | |||
| 150 | #endif | 150 | #endif |
| 151 | 151 | ||
| 152 | #ifdef __KERNEL__ | 152 | #ifdef __KERNEL__ |
| 153 | #define _set_base(addr, base) do { unsigned long __pr; \ | ||
| 154 | __asm__ __volatile__ ("movw %%dx,%1\n\t" \ | ||
| 155 | "rorl $16,%%edx\n\t" \ | ||
| 156 | "movb %%dl,%2\n\t" \ | ||
| 157 | "movb %%dh,%3" \ | ||
| 158 | :"=&d" (__pr) \ | ||
| 159 | :"m" (*((addr)+2)), \ | ||
| 160 | "m" (*((addr)+4)), \ | ||
| 161 | "m" (*((addr)+7)), \ | ||
| 162 | "0" (base) \ | ||
| 163 | ); } while (0) | ||
| 164 | |||
| 165 | #define _set_limit(addr, limit) do { unsigned long __lr; \ | ||
| 166 | __asm__ __volatile__ ("movw %%dx,%1\n\t" \ | ||
| 167 | "rorl $16,%%edx\n\t" \ | ||
| 168 | "movb %2,%%dh\n\t" \ | ||
| 169 | "andb $0xf0,%%dh\n\t" \ | ||
| 170 | "orb %%dh,%%dl\n\t" \ | ||
| 171 | "movb %%dl,%2" \ | ||
| 172 | :"=&d" (__lr) \ | ||
| 173 | :"m" (*(addr)), \ | ||
| 174 | "m" (*((addr)+6)), \ | ||
| 175 | "0" (limit) \ | ||
| 176 | ); } while (0) | ||
| 177 | |||
| 178 | #define set_base(ldt, base) _set_base(((char *)&(ldt)) , (base)) | ||
| 179 | #define set_limit(ldt, limit) _set_limit(((char *)&(ldt)) , ((limit)-1)) | ||
| 180 | 153 | ||
| 181 | extern void native_load_gs_index(unsigned); | 154 | extern void native_load_gs_index(unsigned); |
| 182 | 155 | ||
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 79302e9a33a4..b5e841bd60d9 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c | |||
| @@ -403,7 +403,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); | |||
| 403 | static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); | 403 | static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); |
| 404 | static struct apm_user *user_list; | 404 | static struct apm_user *user_list; |
| 405 | static DEFINE_SPINLOCK(user_list_lock); | 405 | static DEFINE_SPINLOCK(user_list_lock); |
| 406 | static const struct desc_struct bad_bios_desc = { { { 0, 0x00409200 } } }; | 406 | static struct desc_struct bad_bios_desc = { { { 0, 0x00409200 } } }; |
| 407 | 407 | ||
| 408 | static const char driver_version[] = "1.16ac"; /* no spaces */ | 408 | static const char driver_version[] = "1.16ac"; /* no spaces */ |
| 409 | 409 | ||
| @@ -2337,8 +2337,8 @@ static int __init apm_init(void) | |||
| 2337 | * This is for buggy BIOS's that refer to (real mode) segment 0x40 | 2337 | * This is for buggy BIOS's that refer to (real mode) segment 0x40 |
| 2338 | * even though they are called in protected mode. | 2338 | * even though they are called in protected mode. |
| 2339 | */ | 2339 | */ |
| 2340 | set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); | 2340 | set_desc_base(&bad_bios_desc, (unsigned long)__va(0x40UL << 4)); |
| 2341 | _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); | 2341 | set_desc_limit(&bad_bios_desc, 4095 - (0x40 << 4)); |
| 2342 | 2342 | ||
| 2343 | /* | 2343 | /* |
| 2344 | * Set up the long jump entry point to the APM BIOS, which is called | 2344 | * Set up the long jump entry point to the APM BIOS, which is called |
| @@ -2358,12 +2358,12 @@ static int __init apm_init(void) | |||
| 2358 | * code to that CPU. | 2358 | * code to that CPU. |
| 2359 | */ | 2359 | */ |
| 2360 | gdt = get_cpu_gdt_table(0); | 2360 | gdt = get_cpu_gdt_table(0); |
| 2361 | set_base(gdt[APM_CS >> 3], | 2361 | set_desc_base(&gdt[APM_CS >> 3], |
| 2362 | __va((unsigned long)apm_info.bios.cseg << 4)); | 2362 | (unsigned long)__va((unsigned long)apm_info.bios.cseg << 4)); |
| 2363 | set_base(gdt[APM_CS_16 >> 3], | 2363 | set_desc_base(&gdt[APM_CS_16 >> 3], |
| 2364 | __va((unsigned long)apm_info.bios.cseg_16 << 4)); | 2364 | (unsigned long)__va((unsigned long)apm_info.bios.cseg_16 << 4)); |
| 2365 | set_base(gdt[APM_DS >> 3], | 2365 | set_desc_base(&gdt[APM_DS >> 3], |
| 2366 | __va((unsigned long)apm_info.bios.dseg << 4)); | 2366 | (unsigned long)__va((unsigned long)apm_info.bios.dseg << 4)); |
| 2367 | 2367 | ||
| 2368 | proc_create("apm", 0, NULL, &apm_file_ops); | 2368 | proc_create("apm", 0, NULL, &apm_file_ops); |
| 2369 | 2369 | ||
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index 7e6b5a3b3281..45ad3e9cc362 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c | |||
| @@ -55,9 +55,9 @@ __asm__(".text \n" | |||
| 55 | 55 | ||
| 56 | #define Q2_SET_SEL(cpu, selname, address, size) \ | 56 | #define Q2_SET_SEL(cpu, selname, address, size) \ |
| 57 | do { \ | 57 | do { \ |
| 58 | struct desc_struct *gdt = get_cpu_gdt_table((cpu)); \ | 58 | struct desc_struct *gdt = get_cpu_gdt_table((cpu)); \ |
| 59 | set_base(gdt[(selname) >> 3], (u32)(address)); \ | 59 | set_desc_base(&gdt[(selname) >> 3], (u32)(address)); \ |
| 60 | set_limit(gdt[(selname) >> 3], size); \ | 60 | set_desc_limit(&gdt[(selname) >> 3], (size) - 1); \ |
| 61 | } while(0) | 61 | } while(0) |
| 62 | 62 | ||
| 63 | static struct desc_struct bad_bios_desc; | 63 | static struct desc_struct bad_bios_desc; |
| @@ -479,16 +479,17 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header) | |||
| 479 | bad_bios_desc.a = 0; | 479 | bad_bios_desc.a = 0; |
| 480 | bad_bios_desc.b = 0x00409200; | 480 | bad_bios_desc.b = 0x00409200; |
| 481 | 481 | ||
| 482 | set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); | 482 | set_desc_base(&bad_bios_desc, (unsigned long)__va(0x40UL << 4)); |
| 483 | _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); | 483 | set_desc_limit(&bad_bios_desc, 4095 - (0x40 << 4)); |
| 484 | for_each_possible_cpu(i) { | 484 | for_each_possible_cpu(i) { |
| 485 | struct desc_struct *gdt = get_cpu_gdt_table(i); | 485 | struct desc_struct *gdt = get_cpu_gdt_table(i); |
| 486 | if (!gdt) | 486 | if (!gdt) |
| 487 | continue; | 487 | continue; |
| 488 | set_base(gdt[GDT_ENTRY_PNPBIOS_CS32], &pnp_bios_callfunc); | 488 | set_desc_base(&gdt[GDT_ENTRY_PNPBIOS_CS32], |
| 489 | set_base(gdt[GDT_ENTRY_PNPBIOS_CS16], | 489 | (unsigned long)&pnp_bios_callfunc); |
| 490 | __va(header->fields.pm16cseg)); | 490 | set_desc_base(&gdt[GDT_ENTRY_PNPBIOS_CS16], |
| 491 | set_base(gdt[GDT_ENTRY_PNPBIOS_DS], | 491 | (unsigned long)__va(header->fields.pm16cseg)); |
| 492 | __va(header->fields.pm16dseg)); | 492 | set_desc_base(&gdt[GDT_ENTRY_PNPBIOS_DS], |
| 493 | (unsigned long)__va(header->fields.pm16dseg)); | ||
| 493 | } | 494 | } |
| 494 | } | 495 | } |
