[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: Andi Kleen <ak@suse.de>
This commit is contained in:
parent
9142e0c839
commit
874c4fe389
|
@ -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"
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
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 @@
|
||||||
#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 @@
|
||||||
#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 @@
|
||||||
#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 @@
|
||||||
#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)
|
||||||
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 @@
|
||||||
#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>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#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 {
|
||||||
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 {
|
||||||
.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[];
|
||||||
/* 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[];
|
||||||
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)
|
||||||
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)
|
||||||
/* 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)
|
||||||
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);
|
||||||
#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
|
||||||
|
|
Loading…
Reference in New Issue