Commit 874c4fe3 authored by Andi Kleen's avatar Andi Kleen Committed by Andi Kleen

[PATCH] i386: Allow to use GENERICARCH for UP kernels

There are some machines around (large xSeries or Unisys ES7000) that
need physical IO-APIC destination mode to access all of their IO
devices. This currently doesn't work in UP kernels as used in
distribution installers.

This patch allows to compile even UP kernels as GENERICARCH which
allows to use physical or clustered APIC mode.
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
parent 9142e0c8
...@@ -166,7 +166,6 @@ config X86_VISWS ...@@ -166,7 +166,6 @@ config X86_VISWS
config X86_GENERICARCH config X86_GENERICARCH
bool "Generic architecture (Summit, bigsmp, ES7000, default)" bool "Generic architecture (Summit, bigsmp, ES7000, default)"
depends on SMP
help help
This option compiles in the Summit, bigsmp, ES7000, default subarchitectures. This option compiles in the Summit, bigsmp, ES7000, default subarchitectures.
It is intended for a generic binary kernel. It is intended for a generic binary kernel.
...@@ -263,7 +262,7 @@ source "kernel/Kconfig.preempt" ...@@ -263,7 +262,7 @@ source "kernel/Kconfig.preempt"
config X86_UP_APIC config X86_UP_APIC
bool "Local APIC support on uniprocessors" bool "Local APIC support on uniprocessors"
depends on !SMP && !(X86_VISWS || X86_VOYAGER) depends on !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH)
help help
A local APIC (Advanced Programmable Interrupt Controller) is an A local APIC (Advanced Programmable Interrupt Controller) is an
integrated interrupt controller in the CPU. If you have a single-CPU integrated interrupt controller in the CPU. If you have a single-CPU
...@@ -288,12 +287,12 @@ config X86_UP_IOAPIC ...@@ -288,12 +287,12 @@ config X86_UP_IOAPIC
config X86_LOCAL_APIC config X86_LOCAL_APIC
bool bool
depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH
default y default y
config X86_IO_APIC config X86_IO_APIC
bool bool
depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH
default y default y
config X86_VISWS_APIC config X86_VISWS_APIC
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <asm/nmi.h> #include <asm/nmi.h>
#include <mach_apic.h> #include <mach_apic.h>
#include <mach_apicdef.h>
#include "io_ports.h" #include "io_ports.h"
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <asm/io_apic.h> #include <asm/io_apic.h>
#include <mach_apic.h> #include <mach_apic.h>
#include <mach_apicdef.h>
#include <mach_mpparse.h> #include <mach_mpparse.h>
#include <bios_ebda.h> #include <bios_ebda.h>
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#define APIC_DEFINITION 1 #define APIC_DEFINITION 1
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <asm/smp.h>
#include <asm/mpspec.h> #include <asm/mpspec.h>
#include <asm/genapic.h> #include <asm/genapic.h>
#include <asm/fixmap.h> #include <asm/fixmap.h>
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#define APIC_DEFINITION 1 #define APIC_DEFINITION 1
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <asm/smp.h>
#include <asm/mpspec.h> #include <asm/mpspec.h>
#include <asm/genapic.h> #include <asm/genapic.h>
#include <asm/fixmap.h> #include <asm/fixmap.h>
......
...@@ -119,7 +119,9 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) ...@@ -119,7 +119,9 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
return 0; return 0;
} }
#ifdef CONFIG_SMP
int hard_smp_processor_id(void) int hard_smp_processor_id(void)
{ {
return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID));
} }
#endif
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#define APIC_DEFINITION 1 #define APIC_DEFINITION 1
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <asm/smp.h>
#include <asm/mpspec.h> #include <asm/mpspec.h>
#include <asm/genapic.h> #include <asm/genapic.h>
#include <asm/fixmap.h> #include <asm/fixmap.h>
......
#ifndef _ASM_GENAPIC_H #ifndef _ASM_GENAPIC_H
#define _ASM_GENAPIC_H 1 #define _ASM_GENAPIC_H 1
#include <asm/mpspec.h>
/* /*
* Generic APIC driver interface. * Generic APIC driver interface.
* *
...@@ -63,14 +65,25 @@ struct genapic { ...@@ -63,14 +65,25 @@ struct genapic {
unsigned (*get_apic_id)(unsigned long x); unsigned (*get_apic_id)(unsigned long x);
unsigned long apic_id_mask; unsigned long apic_id_mask;
unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask); unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask);
#ifdef CONFIG_SMP
/* ipi */ /* ipi */
void (*send_IPI_mask)(cpumask_t mask, int vector); void (*send_IPI_mask)(cpumask_t mask, int vector);
void (*send_IPI_allbutself)(int vector); void (*send_IPI_allbutself)(int vector);
void (*send_IPI_all)(int vector); void (*send_IPI_all)(int vector);
#endif
}; };
#define APICFUNC(x) .x = x #define APICFUNC(x) .x = x,
/* More functions could be probably marked IPIFUNC and save some space
in UP GENERICARCH kernels, but I don't have the nerve right now
to untangle this mess. -AK */
#ifdef CONFIG_SMP
#define IPIFUNC(x) APICFUNC(x)
#else
#define IPIFUNC(x)
#endif
#define APIC_INIT(aname, aprobe) { \ #define APIC_INIT(aname, aprobe) { \
.name = aname, \ .name = aname, \
...@@ -80,33 +93,33 @@ struct genapic { ...@@ -80,33 +93,33 @@ struct genapic {
.no_balance_irq = NO_BALANCE_IRQ, \ .no_balance_irq = NO_BALANCE_IRQ, \
.ESR_DISABLE = esr_disable, \ .ESR_DISABLE = esr_disable, \
.apic_destination_logical = APIC_DEST_LOGICAL, \ .apic_destination_logical = APIC_DEST_LOGICAL, \
APICFUNC(apic_id_registered), \ APICFUNC(apic_id_registered) \
APICFUNC(target_cpus), \ APICFUNC(target_cpus) \
APICFUNC(check_apicid_used), \ APICFUNC(check_apicid_used) \
APICFUNC(check_apicid_present), \ APICFUNC(check_apicid_present) \
APICFUNC(init_apic_ldr), \ APICFUNC(init_apic_ldr) \
APICFUNC(ioapic_phys_id_map), \ APICFUNC(ioapic_phys_id_map) \
APICFUNC(clustered_apic_check), \ APICFUNC(clustered_apic_check) \
APICFUNC(multi_timer_check), \ APICFUNC(multi_timer_check) \
APICFUNC(apicid_to_node), \ APICFUNC(apicid_to_node) \
APICFUNC(cpu_to_logical_apicid), \ APICFUNC(cpu_to_logical_apicid) \
APICFUNC(cpu_present_to_apicid), \ APICFUNC(cpu_present_to_apicid) \
APICFUNC(apicid_to_cpu_present), \ APICFUNC(apicid_to_cpu_present) \
APICFUNC(mpc_apic_id), \ APICFUNC(mpc_apic_id) \
APICFUNC(setup_portio_remap), \ APICFUNC(setup_portio_remap) \
APICFUNC(check_phys_apicid_present), \ APICFUNC(check_phys_apicid_present) \
APICFUNC(mpc_oem_bus_info), \ APICFUNC(mpc_oem_bus_info) \
APICFUNC(mpc_oem_pci_bus), \ APICFUNC(mpc_oem_pci_bus) \
APICFUNC(mps_oem_check), \ APICFUNC(mps_oem_check) \
APICFUNC(get_apic_id), \ APICFUNC(get_apic_id) \
.apic_id_mask = APIC_ID_MASK, \ .apic_id_mask = APIC_ID_MASK, \
APICFUNC(cpu_mask_to_apicid), \ APICFUNC(cpu_mask_to_apicid) \
APICFUNC(acpi_madt_oem_check), \ APICFUNC(acpi_madt_oem_check) \
APICFUNC(send_IPI_mask), \ IPIFUNC(send_IPI_mask) \
APICFUNC(send_IPI_allbutself), \ IPIFUNC(send_IPI_allbutself) \
APICFUNC(send_IPI_all), \ IPIFUNC(send_IPI_all) \
APICFUNC(enable_apic_mode), \ APICFUNC(enable_apic_mode) \
APICFUNC(phys_pkg_id), \ APICFUNC(phys_pkg_id) \
} }
extern struct genapic *genapic; extern struct genapic *genapic;
......
...@@ -123,9 +123,13 @@ extern u8 cpu_2_logical_apicid[]; ...@@ -123,9 +123,13 @@ extern u8 cpu_2_logical_apicid[];
/* Mapping from cpu number to logical apicid */ /* Mapping from cpu number to logical apicid */
static inline int cpu_to_logical_apicid(int cpu) static inline int cpu_to_logical_apicid(int cpu)
{ {
#ifdef CONFIG_SMP
if (cpu >= NR_CPUS) if (cpu >= NR_CPUS)
return BAD_APICID; return BAD_APICID;
return (int)cpu_2_logical_apicid[cpu]; return (int)cpu_2_logical_apicid[cpu];
#else
return logical_smp_processor_id();
#endif
} }
static inline int mpc_apic_id(struct mpc_config_processor *m, struct mpc_config_translation *unused) static inline int mpc_apic_id(struct mpc_config_processor *m, struct mpc_config_translation *unused)
......
...@@ -46,10 +46,12 @@ extern u8 cpu_2_logical_apicid[]; ...@@ -46,10 +46,12 @@ extern u8 cpu_2_logical_apicid[];
static inline void init_apic_ldr(void) static inline void init_apic_ldr(void)
{ {
unsigned long val, id; unsigned long val, id;
int i, count; int count = 0;
u8 lid;
u8 my_id = (u8)hard_smp_processor_id(); u8 my_id = (u8)hard_smp_processor_id();
u8 my_cluster = (u8)apicid_cluster(my_id); u8 my_cluster = (u8)apicid_cluster(my_id);
#ifdef CONFIG_SMP
u8 lid;
int i;
/* Create logical APIC IDs by counting CPUs already in cluster. */ /* Create logical APIC IDs by counting CPUs already in cluster. */
for (count = 0, i = NR_CPUS; --i >= 0; ) { for (count = 0, i = NR_CPUS; --i >= 0; ) {
...@@ -57,6 +59,7 @@ static inline void init_apic_ldr(void) ...@@ -57,6 +59,7 @@ static inline void init_apic_ldr(void)
if (lid != BAD_APICID && apicid_cluster(lid) == my_cluster) if (lid != BAD_APICID && apicid_cluster(lid) == my_cluster)
++count; ++count;
} }
#endif
/* We only have a 4 wide bitmap in cluster mode. If a deranged /* We only have a 4 wide bitmap in cluster mode. If a deranged
* BIOS puts 5 CPUs in one APIC cluster, we're hosed. */ * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */
BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT); BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT);
...@@ -91,9 +94,13 @@ static inline int apicid_to_node(int logical_apicid) ...@@ -91,9 +94,13 @@ static inline int apicid_to_node(int logical_apicid)
/* Mapping from cpu number to logical apicid */ /* Mapping from cpu number to logical apicid */
static inline int cpu_to_logical_apicid(int cpu) static inline int cpu_to_logical_apicid(int cpu)
{ {
#ifdef CONFIG_SMP
if (cpu >= NR_CPUS) if (cpu >= NR_CPUS)
return BAD_APICID; return BAD_APICID;
return (int)cpu_2_logical_apicid[cpu]; return (int)cpu_2_logical_apicid[cpu];
#else
return logical_smp_processor_id();
#endif
} }
static inline int cpu_present_to_apicid(int mps_cpu) static inline int cpu_present_to_apicid(int mps_cpu)
......
...@@ -80,17 +80,11 @@ static inline int hard_smp_processor_id(void) ...@@ -80,17 +80,11 @@ static inline int hard_smp_processor_id(void)
return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID)); return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
} }
#endif #endif
static __inline int logical_smp_processor_id(void)
{
/* we don't want to mark this access volatile - bad code generation */
return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
}
#endif #endif
extern int __cpu_disable(void); extern int __cpu_disable(void);
extern void __cpu_die(unsigned int cpu); extern void __cpu_die(unsigned int cpu);
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
#else /* CONFIG_SMP */ #else /* CONFIG_SMP */
...@@ -100,4 +94,15 @@ extern void __cpu_die(unsigned int cpu); ...@@ -100,4 +94,15 @@ extern void __cpu_die(unsigned int cpu);
#define NO_PROC_ID 0xFF /* No processor magic marker */ #define NO_PROC_ID 0xFF /* No processor magic marker */
#endif #endif
#ifndef __ASSEMBLY__
#ifdef CONFIG_X86_LOCAL_APIC
static __inline int logical_smp_processor_id(void)
{
/* we don't want to mark this access volatile - bad code generation */
return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
}
#endif
#endif
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment