[patch] APM TLS fix, 2.5.31-BK

From: Ingo Molnar (mingo@elte.hu)
Date: Tue Aug 13 2002 - 09:31:15 EST


the attached (tested) patch fixes APM support on 2.5.31-BK. The patch is
based on Stephen Rothwell's patch.

        Ingo

--- linux/arch/i386/kernel/apm.c.orig Tue Aug 13 16:24:41 2002
+++ linux/arch/i386/kernel/apm.c Tue Aug 13 16:26:59 2002
@@ -214,6 +214,7 @@
 #include <linux/sched.h>
 #include <linux/pm.h>
 #include <linux/kernel.h>
+#include <linux/smp.h>
 #include <linux/smp_lock.h>
 
 #include <asm/system.h>
@@ -419,6 +420,7 @@
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 static struct apm_user * user_list;
 static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED;
+static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
 
 static char driver_version[] = "1.16"; /* no spaces */
 
@@ -568,7 +570,12 @@
         u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi)
 {
         APM_DECL_SEGS
- unsigned long flags;
+ unsigned long flags;
+ int cpu = smp_processor_id();
+ struct desc_struct save_desc_40;
+
+ save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
+ cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
 
         local_save_flags(flags);
         APM_DO_CLI;
@@ -591,6 +598,7 @@
                 : "memory", "cc");
         APM_DO_RESTORE_SEGS;
         local_irq_restore(flags);
+ cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
         return *eax & 0xff;
 }
 
@@ -613,6 +621,11 @@
         u8 error;
         APM_DECL_SEGS
         unsigned long flags;
+ int cpu = smp_processor_id();
+ struct desc_struct save_desc_40;
+
+ save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
+ cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
 
         local_save_flags(flags);
         APM_DO_CLI;
@@ -639,6 +652,7 @@
         }
         APM_DO_RESTORE_SEGS;
         local_irq_restore(flags);
+ cpu_gdt_table[smp_processor_id()][0x40 / 8] = save_desc_40;
         return error;
 }
 
@@ -1927,13 +1941,13 @@
          * NOTE: on SMP we call into the APM BIOS only on CPU#0, so it's
          * enough to modify CPU#0's GDT.
          */
- for (i = 0; i < NR_CPUS; i++) {
- set_base(cpu_gdt_table[i][APM_40 >> 3],
- __va((unsigned long)0x40 << 4));
- _set_limit((char *)&cpu_gdt_table[i][APM_40 >> 3], 4095 - (0x40 << 4));
+ set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
+ _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
+
+ apm_bios_entry.offset = apm_info.bios.offset;
+ apm_bios_entry.segment = APM_CS;
 
- apm_bios_entry.offset = apm_info.bios.offset;
- apm_bios_entry.segment = APM_CS;
+ for (i = 0; i < NR_CPUS; i++) {
                 set_base(cpu_gdt_table[i][APM_CS >> 3],
                          __va((unsigned long)apm_info.bios.cseg << 4));
                 set_base(cpu_gdt_table[i][APM_CS_16 >> 3],
--- linux/include/linux/apm_bios.h.orig Tue Aug 13 16:24:59 2002
+++ linux/include/linux/apm_bios.h Tue Aug 13 16:26:05 2002
@@ -21,8 +21,7 @@
 
 #ifdef __KERNEL__
 
-#define APM_40 (GDT_ENTRY_APMBIOS_BASE * 8)
-#define APM_CS (APM_BASE + 8)
+#define APM_CS (GDT_ENTRY_APMBIOS_BASE * 8)
 #define APM_CS_16 (APM_CS + 8)
 #define APM_DS (APM_CS_16 + 8)
 

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Aug 15 2002 - 22:00:32 EST