diff options
| -rw-r--r-- | arch/x86_64/kernel/acpi/boot.c | 27 | ||||
| -rw-r--r-- | arch/x86_64/kernel/entry.S | 10 | ||||
| -rw-r--r-- | arch/x86_64/kernel/io_apic.c | 4 | ||||
| -rw-r--r-- | arch/x86_64/kernel/setup64.c | 17 | ||||
| -rw-r--r-- | arch/x86_64/kernel/smp.c | 22 | ||||
| -rw-r--r-- | arch/x86_64/kernel/time.c | 20 | ||||
| -rw-r--r-- | arch/x86_64/kernel/x8664_ksyms.c | 2 | ||||
| -rw-r--r-- | arch/x86_64/mm/extable.c | 4 | ||||
| -rw-r--r-- | arch/x86_64/mm/k8topology.c | 3 | ||||
| -rw-r--r-- | arch/x86_64/mm/numa.c | 1 | ||||
| -rw-r--r-- | include/asm-x86_64/hw_irq.h | 4 | ||||
| -rw-r--r-- | include/asm-x86_64/irq.h | 1 | ||||
| -rw-r--r-- | include/asm-x86_64/pci.h | 2 | ||||
| -rw-r--r-- | include/asm-x86_64/processor.h | 4 | ||||
| -rw-r--r-- | include/asm-x86_64/smp.h | 10 | ||||
| -rw-r--r-- | include/asm-x86_64/topology.h | 4 |
16 files changed, 84 insertions, 51 deletions
diff --git a/arch/x86_64/kernel/acpi/boot.c b/arch/x86_64/kernel/acpi/boot.c index 56aaf7859b64..f3094f0b7f17 100644 --- a/arch/x86_64/kernel/acpi/boot.c +++ b/arch/x86_64/kernel/acpi/boot.c @@ -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, diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index a97ab7acc18f..fcfa1af913c7 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -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 diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 65c7acadef46..1148ddec35a3 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -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: diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 19379a38687e..4a0804165984 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -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; diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c index 299b3d50e7df..7ee5cea794dc 100644 --- a/arch/x86_64/kernel/smp.c +++ b/arch/x86_64/kernel/smp.c @@ -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(); -} diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index a57945080f41..8b0791621425 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -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); diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index 2042d9295796..3208ad9c98f3 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c @@ -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); diff --git a/arch/x86_64/mm/extable.c b/arch/x86_64/mm/extable.c index 710e9372a9d6..8b62676f3e73 100644 --- a/arch/x86_64/mm/extable.c +++ b/arch/x86_64/mm/extable.c @@ -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; diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c index 43df86e4f3ca..8df7e3f276b8 100644 --- a/arch/x86_64/mm/k8topology.c +++ b/arch/x86_64/mm/k8topology.c @@ -164,5 +164,8 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) rr++; } + if (found == 1) + fake_node = 1; + return 0; } diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index c9ee3ee2b491..b2e05d04c566 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c @@ -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 */ diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h index aa7037368274..e1423be20796 100644 --- a/include/asm-x86_64/hw_irq.h +++ b/include/asm-x86_64/hw_irq.h @@ -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, diff --git a/include/asm-x86_64/irq.h b/include/asm-x86_64/irq.h index 7415660ffb69..f7512e095d3d 100644 --- a/include/asm-x86_64/irq.h +++ b/include/asm-x86_64/irq.h @@ -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) { diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h index b072364de2bd..b64f5bd97a2d 100644 --- a/include/asm-x86_64/pci.h +++ b/include/asm-x86_64/pci.h @@ -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); diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index 805b7c03dbbc..f468b68e3839 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h @@ -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)); \ diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h index ba4e4ad1a189..8f425a3acdf6 100644 --- a/include/asm-x86_64/smp.h +++ b/include/asm-x86_64/smp.h @@ -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 */ diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h index d4548e5ed6dc..1a614e8c0b18 100644 --- a/include/asm-x86_64/topology.h +++ b/include/asm-x86_64/topology.h @@ -10,13 +10,15 @@ /* 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) |
