]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Essential x86-64 updates
authorAndi Kleen <ak@muc.de>
Sun, 26 Oct 2003 01:17:34 +0000 (17:17 -0800)
committerLinus Torvalds <torvalds@home.osdl.org>
Sun, 26 Oct 2003 01:17:34 +0000 (17:17 -0800)
The most important part is that it makes x86-64 compile again.
Without that 2.6 users won't be very happy.

It also works around a bug that allowed every user program to reboot the
system on B stepping K8.

Also update to match some recent i386 fixes.

Full ChangeLog:
 - Add acpi_pic_set_level_irq to make ACPI compile again
 - Work around compat mode K8 bug in IRET exception handling
 - Increase exception stack. The old 1k stack was too easy
   to overflow (from Jim Paradis, changed by me)
 - Replace safe_smp_processor_id with cpuid (needed for above)
 - When there is only one node always enable fake_node mode
 - Merge with i386 (NTP gettimeofday monoticity fix, irq nr_vectors change)
 - Fix compile problem for UP kernels in time/cpufreq
 - Set all nodes online at bootup
 - Define node_to_cpumask correctly

16 files changed:
arch/x86_64/kernel/acpi/boot.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/io_apic.c
arch/x86_64/kernel/setup64.c
arch/x86_64/kernel/smp.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/x8664_ksyms.c
arch/x86_64/mm/extable.c
arch/x86_64/mm/k8topology.c
arch/x86_64/mm/numa.c
include/asm-x86_64/hw_irq.h
include/asm-x86_64/irq.h
include/asm-x86_64/pci.h
include/asm-x86_64/processor.h
include/asm-x86_64/smp.h
include/asm-x86_64/topology.h

index 56aaf7859b645060cad849f8b1760c52cbe901bb..f3094f0b7f17b49e302f19ac902cfd5ef5599f2f 100644 (file)
@@ -251,6 +251,33 @@ acpi_parse_hpet (
 } 
 #endif
 
+#ifdef CONFIG_ACPI_BUS
+/*
+ * Set specified PIC IRQ to level triggered mode.
+ *
+ * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
+ * for the 8259 PIC.  bit[n] = 1 means irq[n] is Level, otherwise Edge.
+ * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0)
+ * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
+ *
+ * As the BIOS should have done this for us,
+ * print a warning if the IRQ wasn't already set to level.
+ */
+
+void acpi_pic_set_level_irq(unsigned int irq)
+{
+       unsigned char mask = 1 << (irq & 7);
+       unsigned int port = 0x4d0 + (irq >> 3);
+       unsigned char val = inb(port);
+
+       if (!(val & mask)) {
+               printk(KERN_WARNING PREFIX "IRQ %d was Edge Triggered, "
+                       "setting to Level Triggerd\n", irq);
+               outb(val | mask, port);
+       }
+}
+#endif /* CONFIG_ACPI_BUS */
+
 static unsigned long __init
 acpi_scan_rsdp (
        unsigned long           start,
index a97ab7acc18f0f274cad76a0d5f41c0b1fd777d9..fcfa1af913c721107df2c16c5fa3379a3fac3db4 100644 (file)
@@ -566,8 +566,14 @@ error_kernelspace:
        incl %ebx
        /* There are two places in the kernel that can potentially fault with
           usergs. Handle them here. The exception handlers after
-         iret run with kernel gs again, so don't set the user space flag. */
-       cmpq $iret_label,RIP(%rsp) 
+          iret run with kernel gs again, so don't set the user space flag.
+          B stepping K8s sometimes report an truncated RIP for IRET 
+          exceptions returning to compat mode. Check for these here too. */
+       leaq iret_label(%rip),%rbp
+       cmpq %rbp,RIP(%rsp) 
+       je   error_swapgs
+       movl %ebp,%ebp  /* zero extend */
+       cmpq %rbp,RIP(%rsp) 
        je   error_swapgs
        cmpq $gs_change,RIP(%rsp)
         je   error_swapgs
index 65c7acadef46459719f8af2dbf6b4f6e771a5023..1148ddec35a3e904cc7221e85b3510e56928ff17 100644 (file)
@@ -622,11 +622,13 @@ static inline int IO_APIC_irq_trigger(int irq)
        return 0;
 }
 
-int irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 };
+/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
+u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
 
 static int __init assign_irq_vector(int irq)
 {
        static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
+       BUG_ON(irq >= NR_IRQ_VECTORS);
        if (IO_APIC_VECTOR(irq) > 0)
                return IO_APIC_VECTOR(irq);
 next:
index 19379a38687e0b2929f615a467f73fc0637ae0c4..4a0804165984d068f6c3d913ec6ba0480ef66ef5 100644 (file)
@@ -189,8 +189,7 @@ void pda_init(int cpu)
        pda->irqstackptr += IRQSTACKSIZE-64;
 } 
 
-#define EXCEPTION_STK_ORDER 0 /* >= N_EXCEPTION_STACKS*EXCEPTION_STKSZ */
-char boot_exception_stacks[N_EXCEPTION_STACKS*EXCEPTION_STKSZ];
+char boot_exception_stacks[N_EXCEPTION_STACKS * EXCEPTION_STKSZ];
 
 void syscall_init(void)
 {
@@ -226,15 +225,12 @@ void __init cpu_init (void)
 #endif
        struct tss_struct * t = &init_tss[cpu];
        unsigned long v, efer; 
-       char *estacks; 
+       char *estacks = NULL; 
        struct task_struct *me;
 
        /* CPU 0 is initialised in head64.c */
        if (cpu != 0) {
                pda_init(cpu);
-               estacks = (char *)__get_free_pages(GFP_ATOMIC, 0); 
-               if (!estacks)
-                       panic("Can't allocate exception stacks for CPU %d\n",cpu);
        } else 
                estacks = boot_exception_stacks; 
 
@@ -282,10 +278,15 @@ void __init cpu_init (void)
        /*
         * set up and load the per-CPU TSS
         */
-       estacks += EXCEPTION_STKSZ;
        for (v = 0; v < N_EXCEPTION_STACKS; v++) {
-               t->ist[v] = (unsigned long)estacks;
+               if (cpu) {
+                       estacks = (char *)__get_free_pages(GFP_ATOMIC, 0);
+                       if (!estacks)
+                               panic("Cannot allocate exception stack %ld %d\n",
+                                     v, cpu); 
+               }
                estacks += EXCEPTION_STKSZ;
+               t->ist[v] = (unsigned long)estacks;
        }
 
        t->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
index 299b3d50e7dfbc0a79bd81e573a9635eba191a61..7ee5cea794dc99d729dfc4c3aef050470cfa44c9 100644 (file)
@@ -487,25 +487,3 @@ asmlinkage void smp_call_function_interrupt(void)
                atomic_inc(&call_data->finished);
        }
 }
-
-/* Slow. Should be only used for debugging. */
-int slow_smp_processor_id(void)
-{ 
-       int stack_location;
-       unsigned long sp = (unsigned long)&stack_location; 
-       int offset = 0, cpu;
-
-       for (offset = 0; next_cpu(offset, cpu_online_map) < NR_CPUS; offset = cpu + 1) {
-               cpu = next_cpu(offset, cpu_online_map);
-
-               if (sp >= (u64)cpu_pda[cpu].irqstackptr - IRQSTACKSIZE && 
-                   sp <= (u64)cpu_pda[cpu].irqstackptr)
-                       return cpu;
-
-               unsigned long estack = init_tss[cpu].ist[0] - EXCEPTION_STKSZ;
-               if (sp >= estack && sp <= estack+(1<<(PAGE_SHIFT+EXCEPTION_STK_ORDER)))
-                       return cpu;                     
-       }
-
-       return stack_smp_processor_id();
-} 
index a57945080f41627e3128fb9d38d6a729be323054..8b07916214257cb4ccdd28f7b223f1a38e5bc845 100644 (file)
@@ -111,6 +111,14 @@ void do_gettimeofday(struct timeval *tv)
                sec = xtime.tv_sec;
                usec = xtime.tv_nsec / 1000;
 
+               /*
+                * If time_adjust is negative then NTP is slowing the clock
+                * so make sure not to go into next possible interval.
+                * Better to lose some accuracy than have time go backwards..
+                */
+               if (unlikely(time_adjust < 0) && usec > tickadj)
+                       usec = tickadj;
+
                t = (jiffies - wall_jiffies) * (1000000L / HZ) +
                        do_gettimeoffset();
                usec += t;
@@ -477,22 +485,28 @@ unsigned long get_cmos_time(void)
 static unsigned int  ref_freq = 0;
 static unsigned long loops_per_jiffy_ref = 0;
 
-//static unsigned long fast_gettimeoffset_ref = 0;
 static unsigned long cpu_khz_ref = 0;
 
 static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
                                 void *data)
 {
         struct cpufreq_freqs *freq = data;
+       unsigned long *lpj;
+
+#ifdef CONFIG_SMP
+       lpj = &cpu_data[freq->cpu].loops_per_jiffy;
+#else
+       lpj = &boot_cpu_data.loops_per_jiffy;
+#endif
 
        if (!ref_freq) {
                ref_freq = freq->old;
-               loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
+               loops_per_jiffy_ref = *lpj;
                cpu_khz_ref = cpu_khz;
        }
         if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
             (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
-                cpu_data[freq->cpu].loops_per_jiffy =
+                *lpj =
                cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
 
                cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
index 2042d92957960388ffb78f406bb98ffbf77d4e29..3208ad9c98f32bad8a3c11ebdbab1751f2cbac75 100644 (file)
@@ -153,7 +153,7 @@ EXPORT_SYMBOL_GPL(unset_nmi_callback);
 
 extern void * memset(void *,int,__kernel_size_t);
 extern size_t strlen(const char *);
-extern char * bcopy(const char * src, char * dest, int count);
+extern void bcopy(const char * src, char * dest, int count);
 extern void * memmove(void * dest,const void *src,size_t count);
 extern char * strcpy(char * dest,const char *src);
 extern int strcmp(const char * cs,const char * ct);
index 710e9372a9d6da1438933f8b3ef949b558398254..8b62676f3e73966b276ddef5f94f55c07a1408b3 100644 (file)
@@ -14,6 +14,10 @@ search_extable(const struct exception_table_entry *first,
               const struct exception_table_entry *last,
               unsigned long value)
 {
+       /* Work around a B stepping K8 bug */
+       if ((value >> 32) == 0)
+               value |= 0xffffffffUL << 32; 
+
         while (first <= last) {
                const struct exception_table_entry *mid;
                long diff;
index 43df86e4f3ca9abbbf41581dd3da1db28a026831..8df7e3f276b801c55172fed24f1a724d7ae3d8e4 100644 (file)
@@ -164,5 +164,8 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
                rr++; 
        }
 
+       if (found == 1) 
+               fake_node = 1;
+
        return 0;
 } 
index c9ee3ee2b4911b35ab1cc0e7bea55c3c9103b018..b2e05d04c56659877fef61d71024503e6604b77b 100644 (file)
@@ -104,6 +104,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
        if (nodeid + 1 > numnodes)
                numnodes = nodeid + 1;
        nodes_present |= (1UL << nodeid); 
+       node_set_online(nodeid);
 } 
 
 /* Initialize final allocator for a zone */
index aa70373682744344d421245d5d53edf6a92510c8..e1423be2079655434a91ee6d436708c9f6c3ce57 100644 (file)
@@ -76,8 +76,8 @@ struct hw_interrupt_type;
 
 
 #ifndef __ASSEMBLY__
-extern int irq_vector[NR_IRQS];
-#define IO_APIC_VECTOR(irq)    irq_vector[irq]
+extern u8 irq_vector[NR_IRQ_VECTORS];
+#define IO_APIC_VECTOR(irq)    ((int)irq_vector[irq])
 
 /*
  * Various low-level irq details needed by irq.c, process.c,
index 7415660ffb69d1980e3a7cd7af7bf178f8b7d8a9..f7512e095d3de21624fecc03c45b16ef1fa6315d 100644 (file)
@@ -22,6 +22,7 @@
  * the usable vector space is 0x20-0xff (224 vectors)
  */
 #define NR_IRQS 224
+#define NR_IRQ_VECTORS NR_IRQS
 
 static __inline__ int irq_canonicalize(int irq)
 {
index b072364de2bd2e537812250764e707d950b17375..b64f5bd97a2d1c3bbf2dc081f04109456a1634e1 100644 (file)
@@ -24,6 +24,8 @@ extern unsigned long pci_mem_start;
 #define PCIBIOS_MIN_IO         0x1000
 #define PCIBIOS_MIN_MEM                (pci_mem_start)
 
+#define PCIBIOS_MIN_CARDBUS_IO 0x4000
+
 void pcibios_config_init(void);
 struct pci_bus * pcibios_scan_root(int bus);
 extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value);
index 805b7c03dbbcb6f1fc266482d4bb4efdff79dcdf..f468b68e3839ec8700f2c8e7285949e281cef904 100644 (file)
@@ -263,8 +263,8 @@ struct thread_struct {
 #define DOUBLEFAULT_STACK 2 
 #define NMI_STACK 3 
 #define N_EXCEPTION_STACKS 3  /* hw limit: 7 */
-#define EXCEPTION_STKSZ 1024
-#define EXCEPTION_STK_ORDER 0
+#define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER)
+#define EXCEPTION_STACK_ORDER 0 
 
 #define start_thread(regs,new_rip,new_rsp) do { \
        asm volatile("movl %0,%%fs; movl %0,%%es; movl %0,%%ds": :"r" (0));      \
index ba4e4ad1a1898629c754a7e42a5d9bd00e5ad8b9..8f425a3acdf6e9cc84ae4802797f9cd8718769ba 100644 (file)
@@ -74,15 +74,7 @@ extern __inline int hard_smp_processor_id(void)
        return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
 }
 
-extern int slow_smp_processor_id(void);
-
-extern inline int safe_smp_processor_id(void)
-{ 
-       if (disable_apic)
-               return slow_smp_processor_id(); 
-       else
-               return hard_smp_processor_id();
-} 
+#define safe_smp_processor_id() (cpuid_ebx(1) >> 24) 
 
 #define cpu_online(cpu) cpu_isset(cpu, cpu_online_map)
 #endif /* !ASSEMBLY */
index d4548e5ed6dca00b6013602fe7663374dd6ba5de..1a614e8c0b189d5db72f13e1624af4721d14cc9c 100644 (file)
 /* Map the K8 CPU local memory controllers to a simple 1:1 CPU:NODE topology */
 
 extern int fake_node;
+/* This is actually a cpumask_t, but doesn't matter because we don't have
+   >BITS_PER_LONG CPUs */
 extern unsigned long cpu_online_map;
 
 #define cpu_to_node(cpu)               (fake_node ? 0 : (cpu))
 #define memblk_to_node(memblk)         (fake_node ? 0 : (memblk))
 #define parent_node(node)              (node)
 #define node_to_first_cpu(node)        (fake_node ? 0 : (node))
-#define node_to_cpu_mask(node) (fake_node ? cpu_online_map : (1UL << (node)))
+#define node_to_cpumask(node)  (fake_node ? cpu_online_map : (1UL << (node)))
 #define node_to_memblk(node)           (node)
 
 static inline unsigned long pcibus_to_cpumask(int bus)