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
}
#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,
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
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:
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)
{
#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;
/*
* 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;
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();
-}
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;
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);
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);
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;
rr++;
}
+ if (found == 1)
+ fake_node = 1;
+
return 0;
}
if (nodeid + 1 > numnodes)
numnodes = nodeid + 1;
nodes_present |= (1UL << nodeid);
+ node_set_online(nodeid);
}
/* Initialize final allocator for a zone */
#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,
* 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)
{
#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);
#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)); \
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 */
/* 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)