mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
bitkeeper revision 1.22.2.20 (3e4bb0deGlYf76D1jtppEmaeeRJyVQ)
Pulled in IO APIC stuff from linux-2.4.21-pre4
This commit is contained in:
1 parent
1381738b9a
commit
4b929a32df
12 files changed
+1124
-477
No files matched your search
+210
-18
@@ -28,11 +28,23 @@
|
||||
#include <xeno/config.h>
|
||||
#include <asm/mc146818rtc.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/smpboot.h>
|
||||
|
||||
|
||||
static unsigned int nmi_watchdog; /* XXXX XEN */
|
||||
|
||||
#undef APIC_LOCKUP_DEBUG
|
||||
|
||||
#define APIC_LOCKUP_DEBUG
|
||||
|
||||
static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
unsigned int int_dest_addr_mode = APIC_DEST_LOGICAL;
|
||||
unsigned char int_delivery_mode = dest_LowestPrio;
|
||||
|
||||
|
||||
/*
|
||||
* # of IRQ routing registers
|
||||
*/
|
||||
@@ -47,6 +59,7 @@ int nr_ioapic_registers[MAX_IO_APICS];
|
||||
|
||||
/*
|
||||
* This is performance-critical, we want to do it O(1)
|
||||
*
|
||||
* the indexing order of this array favors 1:1 mappings
|
||||
* between pins and IRQs.
|
||||
*/
|
||||
@@ -60,7 +73,7 @@ static struct irq_pin_list {
|
||||
* shared ISA-space IRQs, so we have to support them. We are super
|
||||
* fast in the common case, and fast for shared ISA-space IRQs.
|
||||
*/
|
||||
static void add_pin_to_irq(unsigned int irq, int apic, int pin)
|
||||
static void __init add_pin_to_irq(unsigned int irq, int apic, int pin)
|
||||
{
|
||||
static int first_free_entry = NR_IRQS;
|
||||
struct irq_pin_list *entry = irq_2_pin + irq;
|
||||
@@ -78,6 +91,26 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
|
||||
entry->pin = pin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reroute an IRQ to a different pin.
|
||||
*/
|
||||
static void __init replace_pin_at_irq(unsigned int irq,
|
||||
int oldapic, int oldpin,
|
||||
int newapic, int newpin)
|
||||
{
|
||||
struct irq_pin_list *entry = irq_2_pin + irq;
|
||||
|
||||
while (1) {
|
||||
if (entry->apic == oldapic && entry->pin == oldpin) {
|
||||
entry->apic = newapic;
|
||||
entry->pin = newpin;
|
||||
}
|
||||
if (!entry->next)
|
||||
break;
|
||||
entry = irq_2_pin + entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
#define __DO_ACTION(R, ACTION, FINAL) \
|
||||
\
|
||||
{ \
|
||||
@@ -156,6 +189,66 @@ static void clear_IO_APIC (void)
|
||||
clear_IO_APIC_pin(apic, pin);
|
||||
}
|
||||
|
||||
/*
|
||||
* support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
|
||||
* specific CPU-side IRQs.
|
||||
*/
|
||||
|
||||
#define MAX_PIRQS 8
|
||||
int pirq_entries [MAX_PIRQS];
|
||||
int pirqs_enabled;
|
||||
|
||||
int skip_ioapic_setup;
|
||||
#if 0
|
||||
|
||||
static int __init noioapic_setup(char *str)
|
||||
{
|
||||
skip_ioapic_setup = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("noapic", noioapic_setup);
|
||||
|
||||
static int __init ioapic_setup(char *str)
|
||||
{
|
||||
skip_ioapic_setup = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("apic", ioapic_setup);
|
||||
|
||||
|
||||
|
||||
static int __init ioapic_pirq_setup(char *str)
|
||||
{
|
||||
int i, max;
|
||||
int ints[MAX_PIRQS+1];
|
||||
|
||||
get_options(str, ARRAY_SIZE(ints), ints);
|
||||
|
||||
for (i = 0; i < MAX_PIRQS; i++)
|
||||
pirq_entries[i] = -1;
|
||||
|
||||
pirqs_enabled = 1;
|
||||
printk(KERN_INFO "PIRQ redirection, working around broken MP-BIOS.\n");
|
||||
max = MAX_PIRQS;
|
||||
if (ints[0] < MAX_PIRQS)
|
||||
max = ints[0];
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
printk(KERN_DEBUG "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
|
||||
/*
|
||||
* PIRQs are mapped upside down, usually.
|
||||
*/
|
||||
pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("pirq=", ioapic_pirq_setup);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Find the IRQ entry number of a certain pin.
|
||||
*/
|
||||
@@ -206,7 +299,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
|
||||
|
||||
Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
|
||||
bus, slot, pin);
|
||||
if (mp_bus_id_to_pci_bus[bus] == -1) {
|
||||
if ((mp_bus_id_to_pci_bus==NULL) || (mp_bus_id_to_pci_bus[bus] == -1)) {
|
||||
printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
|
||||
return -1;
|
||||
}
|
||||
@@ -466,6 +559,20 @@ static int pin_2_irq(int idx, int apic, int pin)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PCI IRQ command line redirection. Yes, limits are hardcoded.
|
||||
*/
|
||||
if ((pin >= 16) && (pin <= 23)) {
|
||||
if (pirq_entries[pin-16] != -1) {
|
||||
if (!pirq_entries[pin-16]) {
|
||||
printk(KERN_DEBUG "disabling PIRQ%d\n", pin-16);
|
||||
} else {
|
||||
irq = pirq_entries[pin-16];
|
||||
printk(KERN_DEBUG "using PIRQ%d -> IRQ %d\n",
|
||||
pin-16, irq);
|
||||
}
|
||||
}
|
||||
}
|
||||
return irq;
|
||||
}
|
||||
|
||||
@@ -495,11 +602,17 @@ static int __init assign_irq_vector(int irq)
|
||||
return IO_APIC_VECTOR(irq);
|
||||
next:
|
||||
current_vector += 8;
|
||||
|
||||
/* XXX Skip the guestOS -> Xen syscall vector! XXX */
|
||||
if (current_vector == HYPERVISOR_CALL_VECTOR) goto next;
|
||||
/* XXX Skip the Linux/BSD fast-trap vector! XXX */
|
||||
if (current_vector == 0x80) goto next;
|
||||
|
||||
#if 0
|
||||
if (current_vector == SYSCALL_VECTOR)
|
||||
goto next;
|
||||
#endif
|
||||
|
||||
if (current_vector > FIRST_SYSTEM_VECTOR) {
|
||||
offset++;
|
||||
current_vector = FIRST_DEVICE_VECTOR + offset;
|
||||
@@ -532,10 +645,10 @@ void __init setup_IO_APIC_irqs(void)
|
||||
*/
|
||||
memset(&entry,0,sizeof(entry));
|
||||
|
||||
entry.delivery_mode = dest_LowestPrio;
|
||||
entry.dest_mode = INT_DELIVERY_MODE;
|
||||
entry.delivery_mode = INT_DELIVERY_MODE;
|
||||
entry.dest_mode = (INT_DEST_ADDR_MODE != 0);
|
||||
entry.mask = 0; /* enable IRQ */
|
||||
entry.dest.logical.logical_dest = TARGET_CPUS;
|
||||
entry.dest.logical.logical_dest = target_cpus();
|
||||
|
||||
idx = find_irq_entry(apic,pin,mp_INT);
|
||||
if (idx == -1) {
|
||||
@@ -553,11 +666,18 @@ void __init setup_IO_APIC_irqs(void)
|
||||
if (irq_trigger(idx)) {
|
||||
entry.trigger = 1;
|
||||
entry.mask = 1;
|
||||
entry.dest.logical.logical_dest = TARGET_CPUS;
|
||||
}
|
||||
|
||||
irq = pin_2_irq(idx, apic, pin);
|
||||
add_pin_to_irq(irq, apic, pin);
|
||||
/*
|
||||
* skip adding the timer int on secondary nodes, which causes
|
||||
* a small but painful rift in the time-space continuum
|
||||
*/
|
||||
if ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)
|
||||
&& (apic != 0) && (irq == 0))
|
||||
continue;
|
||||
else
|
||||
add_pin_to_irq(irq, apic, pin);
|
||||
|
||||
if (!apic && !IO_APIC_IRQ(irq))
|
||||
continue;
|
||||
@@ -607,16 +727,16 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
|
||||
* We use logical delivery to get the timer IRQ
|
||||
* to the first CPU.
|
||||
*/
|
||||
entry.dest_mode = INT_DELIVERY_MODE;
|
||||
entry.dest_mode = (INT_DEST_ADDR_MODE != 0);
|
||||
entry.mask = 0; /* unmask IRQ now */
|
||||
entry.dest.logical.logical_dest = TARGET_CPUS;
|
||||
entry.delivery_mode = dest_LowestPrio;
|
||||
entry.dest.logical.logical_dest = target_cpus();
|
||||
entry.delivery_mode = INT_DELIVERY_MODE;
|
||||
entry.polarity = 0;
|
||||
entry.trigger = 0;
|
||||
entry.vector = vector;
|
||||
|
||||
/*
|
||||
* The timer IRQ doesnt have to know that behind the
|
||||
* The timer IRQ doesn't have to know that behind the
|
||||
* scene we have a 8259A-master in AEOI mode ...
|
||||
*/
|
||||
irq_desc[0].handler = &ioapic_edge_irq_type;
|
||||
@@ -634,8 +754,9 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
|
||||
|
||||
void __init UNEXPECTED_IO_APIC(void)
|
||||
{
|
||||
printk(KERN_WARNING " WARNING: unexpected IO-APIC, please mail\n");
|
||||
printk(KERN_WARNING " to linux-smp@vger.kernel.org\n");
|
||||
printk(KERN_WARNING
|
||||
"An unexpected IO-APIC was found. If this kernel release is less than\n"
|
||||
"three months old please report this to linux-smp@vger.kernel.org\n");
|
||||
}
|
||||
|
||||
void __init print_IO_APIC(void)
|
||||
@@ -667,7 +788,7 @@ void __init print_IO_APIC(void)
|
||||
spin_unlock_irqrestore(&ioapic_lock, flags);
|
||||
|
||||
printk("\n");
|
||||
printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);
|
||||
printk(KERN_DEBUG "IO APIC #%d..XXXX....\n", mp_ioapics[apic].mpc_apicid);
|
||||
printk(KERN_DEBUG ".... register #00: %08X\n", *(int *)®_00);
|
||||
printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.ID);
|
||||
if (reg_00.__reserved_1 || reg_00.__reserved_2)
|
||||
@@ -688,6 +809,7 @@ void __init print_IO_APIC(void)
|
||||
printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.PRQ);
|
||||
printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.version);
|
||||
if ( (reg_01.version != 0x01) && /* 82489DX IO-APICs */
|
||||
(reg_01.version != 0x02) && /* VIA */
|
||||
(reg_01.version != 0x10) && /* oldest IO-APICs */
|
||||
(reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */
|
||||
(reg_01.version != 0x13) && /* Xeon IO-APICs */
|
||||
@@ -898,6 +1020,9 @@ static void __init enable_IO_APIC(void)
|
||||
irq_2_pin[i].pin = -1;
|
||||
irq_2_pin[i].next = 0;
|
||||
}
|
||||
if (!pirqs_enabled)
|
||||
for (i = 0; i < MAX_PIRQS; i++)
|
||||
pirq_entries[i] = -1;
|
||||
|
||||
/*
|
||||
* The number of IO-APIC IRQ registers (== #pins):
|
||||
@@ -944,6 +1069,9 @@ static void __init setup_ioapic_ids_from_mpc (void)
|
||||
unsigned char old_id;
|
||||
unsigned long flags;
|
||||
|
||||
if (clustered_apic_mode)
|
||||
/* We don't have a good way to do this yet - hack */
|
||||
phys_id_present_map = (u_long) 0xf;
|
||||
/*
|
||||
* Set the IOAPIC ID to the value stored in the MPC table.
|
||||
*/
|
||||
@@ -956,7 +1084,7 @@ static void __init setup_ioapic_ids_from_mpc (void)
|
||||
|
||||
old_id = mp_ioapics[apic].mpc_apicid;
|
||||
|
||||
if (mp_ioapics[apic].mpc_apicid >= 0xf) {
|
||||
if (mp_ioapics[apic].mpc_apicid >= apic_broadcast_id) {
|
||||
printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
|
||||
apic, mp_ioapics[apic].mpc_apicid);
|
||||
printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
|
||||
@@ -968,14 +1096,16 @@ static void __init setup_ioapic_ids_from_mpc (void)
|
||||
* Sanity check, is the ID really free? Every APIC in a
|
||||
* system must have a unique ID or we get lots of nice
|
||||
* 'stuck on smp_invalidate_needed IPI wait' messages.
|
||||
* I/O APIC IDs no longer have any meaning for xAPICs and SAPICs.
|
||||
*/
|
||||
if (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid)) {
|
||||
if ((clustered_apic_mode != CLUSTERED_APIC_XAPIC) &&
|
||||
(phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid))) {
|
||||
printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
|
||||
apic, mp_ioapics[apic].mpc_apicid);
|
||||
for (i = 0; i < 0xf; i++)
|
||||
if (!(phys_id_present_map & (1 << i)))
|
||||
break;
|
||||
if (i >= 0xf)
|
||||
if (i >= apic_broadcast_id)
|
||||
panic("Max APIC ID exceeded!\n");
|
||||
printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
|
||||
i);
|
||||
@@ -1170,6 +1300,10 @@ static void end_level_ioapic_irq (unsigned int irq)
|
||||
#ifdef APIC_LOCKUP_DEBUG
|
||||
struct irq_pin_list *entry;
|
||||
#endif
|
||||
|
||||
#ifdef APIC_MISMATCH_DEBUG
|
||||
atomic_inc(&irq_mis_count);
|
||||
#endif
|
||||
spin_lock(&ioapic_lock);
|
||||
__mask_and_edge_IO_APIC_irq(irq);
|
||||
#ifdef APIC_LOCKUP_DEBUG
|
||||
@@ -1302,6 +1436,36 @@ static struct hw_interrupt_type lapic_irq_type = {
|
||||
end_lapic_irq
|
||||
};
|
||||
|
||||
static void enable_NMI_through_LVT0 (void * dummy)
|
||||
{
|
||||
unsigned int v, ver;
|
||||
|
||||
ver = apic_read(APIC_LVR);
|
||||
ver = GET_APIC_VERSION(ver);
|
||||
v = APIC_DM_NMI; /* unmask and set to NMI */
|
||||
if (!APIC_INTEGRATED(ver)) /* 82489DX */
|
||||
v |= APIC_LVT_LEVEL_TRIGGER;
|
||||
apic_write_around(APIC_LVT0, v);
|
||||
}
|
||||
|
||||
static void setup_nmi (void)
|
||||
{
|
||||
/*
|
||||
* Dirty trick to enable the NMI watchdog ...
|
||||
* We put the 8259A master into AEOI mode and
|
||||
* unmask on all local APICs LVT0 as NMI.
|
||||
*
|
||||
* The idea to use the 8259A in AEOI mode ('8259A Virtual Wire')
|
||||
* is from Maciej W. Rozycki - so we do not have to EOI from
|
||||
* the NMI handler or the timer interrupt.
|
||||
*/
|
||||
printk(KERN_INFO "activating NMI Watchdog ...");
|
||||
|
||||
smp_call_function(enable_NMI_through_LVT0, NULL, 1, 1);
|
||||
enable_NMI_through_LVT0(NULL);
|
||||
|
||||
printk(" done.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* This looks a bit hackish but it's about the only one way of sending
|
||||
@@ -1407,6 +1571,12 @@ static inline void check_timer(void)
|
||||
*/
|
||||
unmask_IO_APIC_irq(0);
|
||||
if (timer_irq_works()) {
|
||||
if (nmi_watchdog == NMI_IO_APIC) {
|
||||
disable_8259A_irq(0);
|
||||
setup_nmi();
|
||||
enable_8259A_irq(0);
|
||||
// XXX Xen check_nmi_watchdog();
|
||||
}
|
||||
return;
|
||||
}
|
||||
clear_IO_APIC_pin(0, pin1);
|
||||
@@ -1422,6 +1592,14 @@ static inline void check_timer(void)
|
||||
setup_ExtINT_IRQ0_pin(pin2, vector);
|
||||
if (timer_irq_works()) {
|
||||
printk("works.\n");
|
||||
if (pin1 != -1)
|
||||
replace_pin_at_irq(0, 0, pin1, 0, pin2);
|
||||
else
|
||||
add_pin_to_irq(0, 0, pin2);
|
||||
if (nmi_watchdog == NMI_IO_APIC) {
|
||||
setup_nmi();
|
||||
// XXX Xen check_nmi_watchdog();
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*
|
||||
@@ -1431,6 +1609,11 @@ static inline void check_timer(void)
|
||||
}
|
||||
printk(" failed.\n");
|
||||
|
||||
if (nmi_watchdog) {
|
||||
printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
|
||||
nmi_watchdog = 0;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
|
||||
|
||||
disable_8259A_irq(0);
|
||||
@@ -1462,10 +1645,19 @@ static inline void check_timer(void)
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* IRQ's that are handled by the old PIC in all cases:
|
||||
* - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
|
||||
* Linux doesn't really care, as it's not actually used
|
||||
* for any interrupt handling anyway.
|
||||
* - There used to be IRQ13 here as well, but all
|
||||
* MPS-compliant must not use it for FPU coupling and we
|
||||
* want to use exception 16 anyway. And there are
|
||||
* systems who connect it to an I/O APIC for other uses.
|
||||
* Thus we don't mark it special any longer.
|
||||
*
|
||||
* Additionally, something is definitely wrong with irq9
|
||||
* on PIIX4 boards.
|
||||
*/
|
||||
#define PIC_IRQS (1<<2)
|
||||
|
||||
|
||||
+742
-428
File diff suppressed because it is too large.
Load diff
@@ -4,7 +4,8 @@ include $(BASEDIR)/Rules.mk
|
||||
default: $(OBJS)
|
||||
$(MAKE) -C ne
|
||||
$(MAKE) -C tulip
|
||||
$(LD) -r -o driver.o $(OBJS) tulip/tulip.o ne/ne_drv.o
|
||||
$(MAKE) -C e1000
|
||||
$(LD) -r -o driver.o e1000/e1000.o $(OBJS) tulip/tulip.o ne/ne_drv.o
|
||||
|
||||
clean:
|
||||
$(MAKE) -C ne clean
|
||||
|
||||
@@ -77,14 +77,13 @@
|
||||
struct e1000_adapter;
|
||||
|
||||
// XEN XXX
|
||||
#define DBG 1
|
||||
// #define DBG 1
|
||||
|
||||
#include "e1000_hw.h"
|
||||
|
||||
#if DBG
|
||||
#define E1000_DBG(args...) printk(KERN_DEBUG "e1000: " args)
|
||||
#else
|
||||
XXX
|
||||
#define E1000_DBG(args...)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1879,7 +1879,7 @@ e1000_read_phy_reg(struct e1000_hw *hw,
|
||||
uint32_t mdic = 0;
|
||||
const uint32_t phy_addr = 1;
|
||||
|
||||
DEBUGFUNC("e1000_read_phy_reg");
|
||||
DEBUGFUNC("XXXXe1000_read_phy_reg");
|
||||
|
||||
if(reg_addr > MAX_PHY_REG_ADDRESS) {
|
||||
DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
|
||||
|
||||
@@ -301,11 +301,9 @@ e1000_reset(struct e1000_adapter *adapter)
|
||||
|
||||
adapter->hw.fc = adapter->hw.original_fc;
|
||||
e1000_reset_hw(&adapter->hw);
|
||||
printk("RESET_H/W\n");
|
||||
if(adapter->hw.mac_type >= e1000_82544)
|
||||
E1000_WRITE_REG(&adapter->hw, WUC, 0);
|
||||
e1000_init_hw(&adapter->hw);
|
||||
printk("INIT H/W\n");
|
||||
e1000_reset_adaptive(&adapter->hw);
|
||||
e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
|
||||
}
|
||||
@@ -470,14 +468,12 @@ e1000_probe(struct pci_dev *pdev,
|
||||
|
||||
printk(KERN_INFO "%s: %s\n", netdev->name, adapter->id_string);
|
||||
e1000_check_options(adapter);
|
||||
printk("OPTIONS OVER\n");
|
||||
/* Initial Wake on LAN setting
|
||||
* If APM wake is enabled in the EEPROM,
|
||||
* enable the ACPI Magic Packet filter
|
||||
*/
|
||||
|
||||
e1000_read_eeprom(&adapter->hw, EEPROM_INIT_CONTROL2_REG, &eeprom_data);
|
||||
printk("EPROM OVER\n");
|
||||
if((adapter->hw.mac_type >= e1000_82544) &&
|
||||
(eeprom_data & E1000_EEPROM_APME))
|
||||
adapter->wol |= E1000_WUFC_MAG;
|
||||
@@ -485,7 +481,6 @@ printk("EPROM OVER\n");
|
||||
/* reset the hardware with the new settings */
|
||||
|
||||
e1000_reset(adapter);
|
||||
printk("PROBE OVER\n");
|
||||
cards_found++;
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#define msec_delay(x) {\
|
||||
int s=jiffies+1+((x*HZ)/1000); \
|
||||
printk("mdelay(%d) called -- spin\n",x); \
|
||||
while(jiffies<s); printk("mdelay over\n");}
|
||||
while(jiffies<s); }
|
||||
|
||||
#if 0
|
||||
/******************** NOT in XEN ! *******/
|
||||
@@ -73,7 +73,7 @@ typedef enum {
|
||||
#define ASSERT(x) if(!(x)) BUG()
|
||||
#define MSGOUT(S, A, B) printk(KERN_DEBUG S "\n", A, B)
|
||||
|
||||
#define DBG 1
|
||||
//#define DBG 1
|
||||
|
||||
#if DBG
|
||||
#define DEBUGOUT(S) printk(KERN_DEBUG S "\n")
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#ifndef __ASM_APIC_H
|
||||
#define __ASM_APIC_H
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/ptrace.h>
|
||||
//#include <linux/config.h>
|
||||
//#include <linux/pm.h>
|
||||
#include <asm/apicdef.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
|
||||
#define APIC_DEBUG 0
|
||||
|
||||
@@ -37,9 +40,15 @@ static __inline__ void apic_wait_icr_idle(void)
|
||||
do { } while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY );
|
||||
}
|
||||
|
||||
#define FORCE_READ_AROUND_WRITE 0
|
||||
#define apic_read_around(x)
|
||||
#define apic_write_around(x,y) apic_write((x),(y))
|
||||
#ifdef CONFIG_X86_GOOD_APIC
|
||||
# define FORCE_READ_AROUND_WRITE 0
|
||||
# define apic_read_around(x)
|
||||
# define apic_write_around(x,y) apic_write((x),(y))
|
||||
#else
|
||||
# define FORCE_READ_AROUND_WRITE 1
|
||||
# define apic_read_around(x) apic_read(x)
|
||||
# define apic_write_around(x,y) apic_write_atomic((x),(y))
|
||||
#endif
|
||||
|
||||
static inline void ack_APIC_irq(void)
|
||||
{
|
||||
@@ -67,8 +76,24 @@ extern void setup_local_APIC (void);
|
||||
extern void init_apic_mappings (void);
|
||||
extern void smp_local_timer_interrupt (struct pt_regs * regs);
|
||||
extern void setup_APIC_clocks (void);
|
||||
extern void setup_apic_nmi_watchdog (void);
|
||||
extern inline void nmi_watchdog_tick (struct pt_regs * regs);
|
||||
extern int APIC_init_uniprocessor (void);
|
||||
extern void disable_APIC_timer(void);
|
||||
extern void enable_APIC_timer(void);
|
||||
|
||||
//extern struct pm_dev *apic_pm_register(pm_dev_t, unsigned long, pm_callback);
|
||||
//extern void apic_pm_unregister(struct pm_dev*);
|
||||
|
||||
extern unsigned int apic_timer_irqs [NR_CPUS];
|
||||
extern int check_nmi_watchdog (void);
|
||||
|
||||
extern unsigned int nmi_watchdog;
|
||||
#define NMI_NONE 0
|
||||
#define NMI_IO_APIC 1
|
||||
#define NMI_LOCAL_APIC 2
|
||||
#define NMI_INVALID 3
|
||||
|
||||
#endif /* CONFIG_X86_LOCAL_APIC */
|
||||
|
||||
#endif /* __ASM_APIC_H */
|
||||
@@ -32,6 +32,8 @@
|
||||
#define SET_APIC_LOGICAL_ID(x) (((x)<<24))
|
||||
#define APIC_ALL_CPUS 0xFF
|
||||
#define APIC_DFR 0xE0
|
||||
#define APIC_DFR_CLUSTER 0x0FFFFFFFul /* Clustered */
|
||||
#define APIC_DFR_FLAT 0xFFFFFFFFul /* Flat mode */
|
||||
#define APIC_SPIV 0xF0
|
||||
#define APIC_SPIV_FOCUS_DISABLED (1<<9)
|
||||
#define APIC_SPIV_APIC_ENABLED (1<<8)
|
||||
@@ -57,6 +59,7 @@
|
||||
#define APIC_INT_LEVELTRIG 0x08000
|
||||
#define APIC_INT_ASSERT 0x04000
|
||||
#define APIC_ICR_BUSY 0x01000
|
||||
#define APIC_DEST_PHYSICAL 0x00000
|
||||
#define APIC_DEST_LOGICAL 0x00800
|
||||
#define APIC_DM_FIXED 0x00000
|
||||
#define APIC_DM_LOWEST 0x00100
|
||||
@@ -107,7 +110,19 @@
|
||||
|
||||
#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
|
||||
|
||||
#ifdef CONFIG_X86_CLUSTERED_APIC
|
||||
#define MAX_IO_APICS 32
|
||||
#else
|
||||
#define MAX_IO_APICS 8
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The broadcast ID is 0xF for old APICs and 0xFF for xAPICs. SAPICs
|
||||
* don't broadcast (yet?), but if they did, they might use 0xFFFF.
|
||||
*/
|
||||
#define APIC_BROADCAST_ID_XAPIC (0xFF)
|
||||
#define APIC_BROADCAST_ID_APIC (0x0F)
|
||||
|
||||
/*
|
||||
* the local APIC register structure, memory mapped. Not terribly well
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
#define APIC_MISMATCH_DEBUG
|
||||
|
||||
#define IO_APIC_BASE(idx) \
|
||||
((volatile int *)__fix_to_virt(FIX_IO_APIC_BASE_0 + idx))
|
||||
((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \
|
||||
+ (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK)))
|
||||
|
||||
/*
|
||||
* The structure of the IO-APIC:
|
||||
@@ -96,7 +97,7 @@ extern struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
|
||||
extern int mp_irq_entries;
|
||||
|
||||
/* MP IRQ source entries */
|
||||
extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
|
||||
extern struct mpc_config_intsrc *mp_irqs;
|
||||
|
||||
/* non-0 if default (table-less) MP configuration */
|
||||
extern int mpc_default_type;
|
||||
@@ -132,8 +133,7 @@ static inline void io_apic_sync(unsigned int apic)
|
||||
}
|
||||
|
||||
/* 1 if "noapic" boot option passed */
|
||||
//extern int skip_ioapic_setup;
|
||||
#define skip_ioapic_setup 0
|
||||
extern int skip_ioapic_setup;
|
||||
|
||||
/*
|
||||
* If we use the IO-APIC for IRQ routing, disable automatic
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef __ASM_MPSPEC_H
|
||||
#define __ASM_MPSPEC_H
|
||||
|
||||
|
||||
/*
|
||||
* Structure definitions for SMP machines following the
|
||||
* Intel Multiprocessing Specification 1.1 and 1.4.
|
||||
@@ -13,8 +14,15 @@
|
||||
|
||||
#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_')
|
||||
|
||||
/* Maximum of 16 APICs with the current APIC ID architecture. */
|
||||
/*
|
||||
* a maximum of 16 APICs with the current APIC ID architecture.
|
||||
* xAPICs can have up to 256. SAPICs have 16 ID bits.
|
||||
*/
|
||||
#ifdef CONFIG_X86_CLUSTERED_APIC
|
||||
#define MAX_APICS 256
|
||||
#else
|
||||
#define MAX_APICS 16
|
||||
#endif
|
||||
|
||||
#define MAX_MPC_ENTRY 1024
|
||||
|
||||
@@ -178,7 +186,11 @@ struct mpc_config_translation
|
||||
* 7 2 CPU MCA+PCI
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_MULTIQUAD
|
||||
#define MAX_IRQ_SOURCES 512
|
||||
#else /* !CONFIG_MULTIQUAD */
|
||||
#define MAX_IRQ_SOURCES 256
|
||||
#endif /* CONFIG_MULTIQUAD */
|
||||
|
||||
#define MAX_MP_BUSSES 32
|
||||
enum mp_bustype {
|
||||
@@ -187,8 +199,11 @@ enum mp_bustype {
|
||||
MP_BUS_PCI,
|
||||
MP_BUS_MCA
|
||||
};
|
||||
extern int mp_bus_id_to_type [MAX_MP_BUSSES];
|
||||
extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
|
||||
extern int *mp_bus_id_to_type;
|
||||
extern int *mp_bus_id_to_node;
|
||||
extern int *mp_bus_id_to_local;
|
||||
extern int *mp_bus_id_to_pci_bus;
|
||||
extern int quad_local_to_mp_bus_id [NR_CPUS/4][4];
|
||||
|
||||
extern unsigned int boot_cpu_physical_apicid;
|
||||
extern unsigned long phys_cpu_present_map;
|
||||
@@ -197,11 +212,9 @@ extern void find_smp_config (void);
|
||||
extern void get_smp_config (void);
|
||||
extern int nr_ioapics;
|
||||
extern int apic_version [MAX_APICS];
|
||||
extern int mp_bus_id_to_type [MAX_MP_BUSSES];
|
||||
extern int mp_irq_entries;
|
||||
extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
|
||||
extern struct mpc_config_intsrc *mp_irqs;
|
||||
extern int mpc_default_type;
|
||||
extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
|
||||
extern int mp_current_pci_id;
|
||||
extern unsigned long mp_lapic_addr;
|
||||
extern int pic_mode;
|
||||
|
||||
@@ -1,13 +1,82 @@
|
||||
#ifndef __ASM_SMPBOOT_H
|
||||
#define __ASM_SMPBOOT_H
|
||||
|
||||
#define TRAMPOLINE_LOW phys_to_virt(0x467)
|
||||
#define TRAMPOLINE_HIGH phys_to_virt(0x469)
|
||||
/*emum for clustered_apic_mode values*/
|
||||
enum{
|
||||
CLUSTERED_APIC_NONE = 0,
|
||||
CLUSTERED_APIC_XAPIC,
|
||||
CLUSTERED_APIC_NUMAQ
|
||||
};
|
||||
|
||||
#define boot_cpu_apicid boot_cpu_physical_apicid
|
||||
#ifdef CONFIG_X86_CLUSTERED_APIC
|
||||
extern unsigned int apic_broadcast_id;
|
||||
extern unsigned char clustered_apic_mode;
|
||||
extern unsigned char esr_disable;
|
||||
extern unsigned char int_delivery_mode;
|
||||
extern unsigned int int_dest_addr_mode;
|
||||
extern int cyclone_setup(char*);
|
||||
|
||||
/* How to map from the cpu_present_map. */
|
||||
#define cpu_present_to_apicid(apicid) (apicid)
|
||||
static inline void detect_clustered_apic(char* oem, char* prod)
|
||||
{
|
||||
/*
|
||||
* Can't recognize Summit xAPICs at present, so use the OEM ID.
|
||||
*/
|
||||
if (!strncmp(oem, "IBM ENSW", 8) && !strncmp(prod, "VIGIL SMP", 9)){
|
||||
clustered_apic_mode = CLUSTERED_APIC_XAPIC;
|
||||
apic_broadcast_id = APIC_BROADCAST_ID_XAPIC;
|
||||
int_dest_addr_mode = APIC_DEST_PHYSICAL;
|
||||
int_delivery_mode = dest_Fixed;
|
||||
esr_disable = 1;
|
||||
/*Start cyclone clock*/
|
||||
cyclone_setup(0);
|
||||
}
|
||||
else if (!strncmp(oem, "IBM NUMA", 8)){
|
||||
clustered_apic_mode = CLUSTERED_APIC_NUMAQ;
|
||||
apic_broadcast_id = APIC_BROADCAST_ID_APIC;
|
||||
int_dest_addr_mode = APIC_DEST_LOGICAL;
|
||||
int_delivery_mode = dest_LowestPrio;
|
||||
esr_disable = 1;
|
||||
}
|
||||
}
|
||||
#define INT_DEST_ADDR_MODE (int_dest_addr_mode)
|
||||
#define INT_DELIVERY_MODE (int_delivery_mode)
|
||||
#else /* CONFIG_X86_CLUSTERED_APIC */
|
||||
#define apic_broadcast_id (APIC_BROADCAST_ID_APIC)
|
||||
#define clustered_apic_mode (CLUSTERED_APIC_NONE)
|
||||
#define esr_disable (0)
|
||||
#define detect_clustered_apic(x,y)
|
||||
#define INT_DEST_ADDR_MODE (APIC_DEST_LOGICAL) /* logical delivery */
|
||||
#define INT_DELIVERY_MODE (dest_LowestPrio)
|
||||
#endif /* CONFIG_X86_CLUSTERED_APIC */
|
||||
#define BAD_APICID 0xFFu
|
||||
|
||||
#define TRAMPOLINE_LOW phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0x8:0x467)
|
||||
#define TRAMPOLINE_HIGH phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0xa:0x469)
|
||||
|
||||
#define boot_cpu_apicid ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?boot_cpu_logical_apicid:boot_cpu_physical_apicid)
|
||||
|
||||
extern unsigned char raw_phys_apicid[NR_CPUS];
|
||||
|
||||
/*
|
||||
* How to map from the cpu_present_map
|
||||
*/
|
||||
static inline int cpu_present_to_apicid(int mps_cpu)
|
||||
{
|
||||
if (clustered_apic_mode == CLUSTERED_APIC_XAPIC)
|
||||
return raw_phys_apicid[mps_cpu];
|
||||
if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ)
|
||||
return (mps_cpu/4)*16 + (1<<(mps_cpu%4));
|
||||
return mps_cpu;
|
||||
}
|
||||
|
||||
static inline unsigned long apicid_to_phys_cpu_present(int apicid)
|
||||
{
|
||||
if(clustered_apic_mode)
|
||||
return 1UL << (((apicid >> 4) << 2) + (apicid & 0x3));
|
||||
return 1UL << apicid;
|
||||
}
|
||||
|
||||
#define physical_to_logical_apicid(phys_apic) ( (1ul << (phys_apic & 0x3)) | (phys_apic & 0xF0u) )
|
||||
|
||||
/*
|
||||
* Mappings between logical cpu number and logical / physical apicid
|
||||
@@ -22,7 +91,31 @@ extern volatile int cpu_2_physical_apicid[];
|
||||
#define cpu_to_logical_apicid(cpu) cpu_2_logical_apicid[cpu]
|
||||
#define physical_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid]
|
||||
#define cpu_to_physical_apicid(cpu) cpu_2_physical_apicid[cpu]
|
||||
#ifdef CONFIG_MULTIQUAD /* use logical IDs to bootstrap */
|
||||
#define boot_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid]
|
||||
#define cpu_to_boot_apicid(cpu) cpu_2_logical_apicid[cpu]
|
||||
#else /* !CONFIG_MULTIQUAD */ /* use physical IDs to bootstrap */
|
||||
#define boot_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid]
|
||||
#define cpu_to_boot_apicid(cpu) cpu_2_physical_apicid[cpu]
|
||||
#endif /* CONFIG_MULTIQUAD */
|
||||
|
||||
#ifdef CONFIG_X86_CLUSTERED_APIC
|
||||
static inline int target_cpus(void)
|
||||
{
|
||||
static int cpu;
|
||||
switch(clustered_apic_mode){
|
||||
case CLUSTERED_APIC_NUMAQ:
|
||||
/* Broadcast intrs to local quad only. */
|
||||
return APIC_BROADCAST_ID_APIC;
|
||||
case CLUSTERED_APIC_XAPIC:
|
||||
/*round robin the interrupts*/
|
||||
cpu = (cpu+1)%smp_num_cpus;
|
||||
return cpu_to_physical_apicid(cpu);
|
||||
default:
|
||||
}
|
||||
return cpu_online_map;
|
||||
}
|
||||
#else
|
||||
#define target_cpus() (0x01)
|
||||
#endif
|
||||
#endif
|
||||