summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/kernel/acpi/boot.c27
-rw-r--r--arch/x86_64/kernel/entry.S10
-rw-r--r--arch/x86_64/kernel/io_apic.c4
-rw-r--r--arch/x86_64/kernel/setup64.c17
-rw-r--r--arch/x86_64/kernel/smp.c22
-rw-r--r--arch/x86_64/kernel/time.c20
-rw-r--r--arch/x86_64/kernel/x8664_ksyms.c2
-rw-r--r--arch/x86_64/mm/extable.c4
-rw-r--r--arch/x86_64/mm/k8topology.c3
-rw-r--r--arch/x86_64/mm/numa.c1
-rw-r--r--include/asm-x86_64/hw_irq.h4
-rw-r--r--include/asm-x86_64/irq.h1
-rw-r--r--include/asm-x86_64/pci.h2
-rw-r--r--include/asm-x86_64/processor.h4
-rw-r--r--include/asm-x86_64/smp.h10
-rw-r--r--include/asm-x86_64/topology.h4
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)