CFLAGS += -mcmodel=kernel
CFLAGS += -pipe
# this makes reading assembly source easier, but produces worse code
-# disable for production kernel
CFLAGS += -fno-reorder-blocks
# should lower this a lot and see how much .text is saves
CFLAGS += -finline-limit=2000
.section .text.rtsigreturn,"ax"
.balign 32
- .globl __kernel_rt_sigreturn,"ax"
+ .globl __kernel_rt_sigreturn
.type __kernel_rt_sigreturn,@function
__kernel_rt_sigreturn:
.LSTART_rt_sigreturn:
$(obj)/bootflag.c:
@ln -sf ../../i386/kernel/bootflag.c $(obj)/bootflag.c
+$(obj)/cpuid.c:
+ @ln -sf ../../i386/kernel/cpuid.c $(obj)/cpuid.c
-clean-files += bootflag.c
+clean-files += bootflag.c cpuid.c
int fallback_aper_order __initdata = 1; /* 64MB */
int fallback_aper_force __initdata = 0;
-extern int no_iommu, force_mmu;
-
/* This code runs before the PCI subsystem is initialized, so just
access the northbridge directly. */
#include <linux/interrupt.h>
#include <linux/mc146818rtc.h>
#include <linux/kernel_stat.h>
+#include <linux/sysdev.h>
#include <asm/atomic.h>
#include <asm/smp.h>
unsigned int apic_thmr;
} apic_pm_state;
-static int lapic_suspend(struct device *dev, u32 state, u32 level)
+static int lapic_suspend(struct sys_device *dev, u32 state)
{
unsigned int l, h;
unsigned long flags;
- if (level != SUSPEND_POWER_DOWN)
- return 0;
if (!apic_pm_state.active)
return 0;
return 0;
}
-static int lapic_resume(struct device *dev, u32 level)
+static int lapic_resume(struct sys_device *dev)
{
unsigned int l, h;
unsigned long flags;
- if (level != RESUME_POWER_ON)
- return 0;
if (!apic_pm_state.active)
return 0;
return 0;
}
-static struct device_driver lapic_driver = {
- .name = "lapic",
- .bus = &system_bus_type,
+static struct sysdev_class lapic_sysclass = {
+ set_kset_name("lapic"),
.resume = lapic_resume,
.suspend = lapic_suspend,
};
/* not static, needed by child devices */
-struct sys_device device_lapic = {
- .name = "lapic",
+static struct sys_device device_lapic = {
.id = 0,
- .dev = {
- .name = "lapic",
- .driver = &lapic_driver,
- },
+ .cls = &lapic_sysclass,
};
-EXPORT_SYMBOL(device_lapic);
static void __init apic_pm_activate(void)
{
apic_pm_state.active = 1;
}
-static int __init init_lapic_devicefs(void)
+static int __init init_lapic_sysfs(void)
{
+ int error;
if (!cpu_has_apic)
return 0;
/* XXX: remove suspend/resume procs if !apic_pm_state.active? */
- driver_register(&lapic_driver);
- return sys_device_register(&device_lapic);
+ error = sysdev_class_register(&lapic_sysclass);
+ if (!error)
+ error = sys_device_register(&device_lapic);
+ return error;
}
-device_initcall(init_lapic_devicefs);
+device_initcall(init_lapic_sysfs);
#else /* CONFIG_PM */
wrmsrl(MSR_IA32_MCG_STATUS, 0);
if (regs && (status & (1<<1)))
- printk(KERN_EMERG "MCE at EIP %lx ESP %lx\n", regs->rip, regs->rsp);
+ printk(KERN_EMERG "MCE at RIP %lx RSP %lx\n", regs->rip, regs->rsp);
others:
generic_machine_check(regs, error_code);
{
u64 cap;
int i;
- struct pci_dev *nb;
if (!test_bit(X86_FEATURE_MCE, &c->x86_capability) ||
!test_bit(X86_FEATURE_MCA, &c->x86_capability))
+++ /dev/null
-#ident "$Id: cpuid.c,v 1.4 2001/10/24 23:58:53 ak Exp $"
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2000 H. Peter Anvin - All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
- * USA; either version 2 of the License, or (at your option) any later
- * version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-
-/*
- * cpuid.c
- *
- * x86 CPUID access device
- *
- * This device is accessed by lseek() to the appropriate CPUID level
- * and then read in chunks of 16 bytes. A larger size means multiple
- * reads of consecutive levels.
- *
- * This driver uses /dev/cpu/%d/cpuid where %d is the minor number, and on
- * an SMP box will direct the access to CPU %d.
- */
-
-#include <linux/module.h>
-#include <linux/config.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/smp.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-#include <linux/smp_lock.h>
-#include <linux/fs.h>
-
-#include <asm/processor.h>
-#include <asm/msr.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#ifdef CONFIG_SMP
-
-struct cpuid_command {
- int cpu;
- u32 reg;
- u32 *data;
-};
-
-static void cpuid_smp_cpuid(void *cmd_block)
-{
- struct cpuid_command *cmd = (struct cpuid_command *) cmd_block;
-
- if ( cmd->cpu == smp_processor_id() )
- cpuid(cmd->reg, &cmd->data[0], &cmd->data[1], &cmd->data[2], &cmd->data[3]);
-}
-
-static inline void do_cpuid(int cpu, u32 reg, u32 *data)
-{
- struct cpuid_command cmd;
-
- preempt_disable();
- if ( cpu == smp_processor_id() ) {
- cpuid(reg, &data[0], &data[1], &data[2], &data[3]);
- } else {
- cmd.cpu = cpu;
- cmd.reg = reg;
- cmd.data = data;
-
- smp_call_function(cpuid_smp_cpuid, &cmd, 1, 1);
- }
- preempt_enable();
-}
-#else /* ! CONFIG_SMP */
-
-static inline void do_cpuid(int cpu, u32 reg, u32 *data)
-{
- cpuid(reg, &data[0], &data[1], &data[2], &data[3]);
-}
-
-#endif /* ! CONFIG_SMP */
-
-static loff_t cpuid_seek(struct file *file, loff_t offset, int orig)
-{
- loff_t ret;
-
- lock_kernel();
-
- switch (orig) {
- case 0:
- file->f_pos = offset;
- ret = file->f_pos;
- break;
- case 1:
- file->f_pos += offset;
- ret = file->f_pos;
- break;
- default:
- ret = -EINVAL;
- }
-
- unlock_kernel();
- return ret;
-}
-
-static ssize_t cpuid_read(struct file * file, char * buf,
- size_t count, loff_t *ppos)
-{
- u32 *tmp = (u32 *)buf;
- u32 data[4];
- size_t rv;
- u32 reg = *ppos;
- int cpu = minor(file->f_dentry->d_inode->i_rdev);
-
- if ( count % 16 )
- return -EINVAL; /* Invalid chunk size */
-
- for ( rv = 0 ; count ; count -= 16 ) {
- do_cpuid(cpu, reg, data);
- if ( copy_to_user(tmp,&data,16) )
- return -EFAULT;
- tmp += 4;
- *ppos = reg++;
- }
-
- return ((char *)tmp) - buf;
-}
-
-static int cpuid_open(struct inode *inode, struct file *file)
-{
- int cpu = minor(file->f_dentry->d_inode->i_rdev);
- struct cpuinfo_x86 *c = &(cpu_data)[cpu];
-
- if ( !(cpu_online_map & (1UL << cpu)) )
- return -ENXIO; /* No such CPU */
- if ( c->cpuid_level < 0 )
- return -EIO; /* CPUID not supported */
-
- return 0;
-}
-
-/*
- * File operations we support
- */
-static struct file_operations cpuid_fops = {
- .owner = THIS_MODULE,
- .llseek = cpuid_seek,
- .read = cpuid_read,
- .open = cpuid_open,
-};
-
-int __init cpuid_init(void)
-{
- if (register_chrdev(CPUID_MAJOR, "cpu/cpuid", &cpuid_fops)) {
- printk(KERN_ERR "cpuid: unable to get major %d for cpuid\n",
- CPUID_MAJOR);
- return -EBUSY;
- }
-
- return 0;
-}
-
-void __exit cpuid_exit(void)
-{
- unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
-}
-
-module_init(cpuid_init);
-module_exit(cpuid_exit)
-
-MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
-MODULE_DESCRIPTION("x86 generic CPUID driver");
-MODULE_LICENSE("GPL");
#include <asm/system.h>
#include <asm/ldt.h>
#include <asm/desc.h>
-
-extern void load_gs_index(unsigned gs);
+#include <asm/proto.h>
#ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
static void flush_ldt(void *null)
-#ident "$Id: msr.c,v 1.6 2001/10/24 23:58:53 ak Exp $"
+#ident "$Id$"
/* ----------------------------------------------------------------------- *
*
* Copyright 2000 H. Peter Anvin - All Rights Reserved
*
* This driver uses /dev/cpu/%d/msr where %d is the minor number, and on
* an SMP box will direct the access to CPU %d.
-
-RED-PEN: need to get power management for S3 restore
-
*/
#include <linux/module.h>
#include <asm/msr.h>
#include <asm/uaccess.h>
#include <asm/system.h>
-#include <asm/cpufeature.h>
/* Note: "err" is handled in a funny way below. Otherwise one version
of gcc or another breaks. */
static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
{
struct msr_command cmd;
+ int ret;
preempt_disable();
if ( cpu == smp_processor_id() ) {
- int ret = wrmsr_eio(reg, eax, edx);
- preempt_enable();
- return ret;
+ ret = wrmsr_eio(reg, eax, edx);
} else {
cmd.cpu = cpu;
cmd.reg = reg;
cmd.data[1] = edx;
smp_call_function(msr_smp_wrmsr, &cmd, 1, 1);
- preempt_enable();
- return cmd.err;
+ ret = cmd.err;
}
+ preempt_enable();
+ return ret;
}
static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx)
{
struct msr_command cmd;
+ int ret;
+ preempt_disable();
if ( cpu == smp_processor_id() ) {
- return rdmsr_eio(reg, eax, edx);
+ ret = rdmsr_eio(reg, eax, edx);
} else {
cmd.cpu = cpu;
cmd.reg = reg;
*eax = cmd.data[0];
*edx = cmd.data[1];
- return cmd.err;
+ ret = cmd.err;
}
+ preempt_enable();
+ return ret;
}
#else /* ! CONFIG_SMP */
#include <linux/mc146818rtc.h>
#include <linux/kernel_stat.h>
#include <linux/module.h>
+#include <linux/sysdev.h>
#include <asm/smp.h>
#include <asm/mtrr.h>
#include <linux/device.h>
-static int lapic_nmi_suspend(struct device *dev, u32 state, u32 level)
- {
- if (level != SUSPEND_POWER_DOWN)
- return 0;
+static int lapic_nmi_suspend(struct sys_device *dev, u32 state)
+{
disable_lapic_nmi_watchdog();
return 0;
- }
+}
-static int lapic_nmi_resume(struct device *dev, u32 level)
- {
- if (level != RESUME_POWER_ON)
- return 0;
+static int lapic_nmi_resume(struct sys_device *dev)
+{
#if 0
enable_lapic_nmi_watchdog();
#endif
return 0;
- }
+}
-static struct device_driver lapic_nmi_driver = {
- .name = "lapic_nmi",
- .bus = &system_bus_type,
+static struct sysdev_class nmi_sysclass = {
+ set_kset_name("lapic_nmi"),
.resume = lapic_nmi_resume,
.suspend = lapic_nmi_suspend,
};
static struct sys_device device_lapic_nmi = {
- .name = "lapic_nmi",
.id = 0,
- .dev = {
- .name = "lapic_nmi",
- .driver = &lapic_nmi_driver,
- .parent = &device_lapic.dev,
- },
+ .cls = &nmi_sysclass,
};
-static int __init init_lapic_nmi_devicefs(void)
+static int __init init_lapic_nmi_sysfs(void)
{
+ int error;
+
if (nmi_active == 0)
return 0;
- driver_register(&lapic_nmi_driver);
- return sys_device_register(&device_lapic_nmi);
+
+ error = sysdev_class_register(&nmi_sysclass);
+ if (!error)
+ error = sys_device_register(&device_lapic_nmi);
+ return error;
}
/* must come after the local APIC's device_initcall() */
-late_initcall(init_lapic_nmi_devicefs);
+late_initcall(init_lapic_nmi_sysfs);
#endif /* CONFIG_PM */
{
int cpu = safe_smp_processor_id();
- init_tss[cpu].ist[NMI_STACK] -= 2048; /* this shouldn't be needed. */
nmi_enter();
add_pda(__nmi_count,1);
if (!nmi_callback(regs, cpu))
default_do_nmi(regs);
nmi_exit();
- init_tss[cpu].ist[NMI_STACK] += 2048;
}
void set_nmi_callback(nmi_callback_t callback)
#include <asm/pgtable.h>
#include <asm/proto.h>
#include <asm/cacheflush.h>
+#include <asm/kdebug.h>
+#include <asm/proto.h>
unsigned long iommu_bus_base; /* GART remapping area (physical) */
static unsigned long iommu_size; /* size of remapping area bytes */
int force_mmu = 0;
#endif
-extern int fallback_aper_order;
-extern int fallback_aper_force;
-
/* Allocation bitmap for the remapping area */
static spinlock_t iommu_bitmap_lock = SPIN_LOCK_UNLOCKED;
static unsigned long *iommu_gart_bitmap; /* guarded by iommu_bitmap_lock */
void *memory;
int gfp = GFP_ATOMIC;
int i;
- unsigned long iommu_page;
int flush = 0;
+ unsigned long iommu_page;
+ unsigned long dma_mask;
- if (hwdev == NULL || hwdev->dma_mask < 0xffffffff || no_iommu)
+ if (hwdev == NULL) {
+ gfp |= GFP_DMA;
+ dma_mask = 0xffffffff;
+ } else {
+ dma_mask = hwdev->consistent_dma_mask;
+ }
+ if (dma_mask == 0)
+ dma_mask = 0xffffffff;
+ if (dma_mask < 0xffffffff || no_iommu)
gfp |= GFP_DMA;
/*
return NULL;
} else {
int high = 0, mmu;
- if (((unsigned long)virt_to_bus(memory) + size) > 0xffffffffUL)
+ if (((unsigned long)virt_to_bus(memory) + size) > dma_mask)
high = 1;
mmu = 1;
if (force_mmu && !(gfp & GFP_DMA))
static void **iommu_leak_tab;
static int leak_trace;
int iommu_leak_pages = 20;
-extern unsigned long printk_address(unsigned long);
void dump_leak(void)
{
int i;
extern int agp_amdk8_init(void);
-void __init pci_iommu_init(void)
+int __init pci_iommu_init(void)
{
struct agp_kern_info info;
unsigned long aper_size;
#ifndef CONFIG_AGP_AMD_8151
no_agp = 1;
#else
+ /* Makefile puts PCI initialization via subsys_initcall first. */
/* Add other K8 AGP bridge drivers here */
no_agp = no_agp ||
(agp_amdk8_init() < 0) ||
if (no_iommu || (!force_mmu && end_pfn < 0xffffffff>>PAGE_SHIFT)) {
printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n");
no_iommu = 1;
- return;
+ return -1;
}
if (no_agp) {
if (err < 0) {
printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n");
no_iommu = 1;
- return;
+ return -1;
}
}
clear_kernel_mapping((unsigned long)__va(iommu_bus_base), iommu_size);
flush_gart();
+
+ return 0;
}
+/* Must execute after PCI subsystem */
+fs_initcall(pci_iommu_init);
+
/* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]]
size set size of iommu (in bytes)
noagp don't initialize the AGP driver and use full aperture.
}
return 1;
}
-
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/string.h>
+#include <asm/proto.h>
/*
* Dummy IO MMU functions
*/
-extern unsigned long end_pfn;
-
void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle)
{
show_trace(®s->rsp);
}
-extern void load_gs_index(unsigned);
-
/*
* Free current thread data structures etc..
*/
void __init print_cpu_info(struct cpuinfo_x86 *c)
{
if (c->x86_model_id[0])
- printk("AMD %s", c->x86_model_id);
+ printk("%s", c->x86_model_id);
if (c->x86_mask || c->cpuid_level >= 0)
printk(" stepping %02x\n", c->x86_mask);
do_signal(regs,oldset);
}
-extern int exception_trace;
-
void signal_fault(struct pt_regs *regs, void *frame, char *where)
{
struct task_struct *me = current;
#include <asm/desc.h>
#include <asm/kdebug.h>
#include <asm/tlbflush.h>
-
-extern int disable_apic;
+#include <asm/proto.h>
/* Bitmask of currently online CPUs */
unsigned long cpu_online_map = 1;
/* Set when the idlers are all forked */
int smp_threads_ready;
-extern void time_init_smp(void);
-
/*
* Trampoline 80x86 program as an array.
*/
long long delta;
long one_usec;
int buggy = 0;
- extern unsigned cpu_khz;
printk(KERN_INFO "checking TSC synchronization across %u CPUs: ",num_booting_cpus());
}
#undef NR_LOOPS
-extern void calibrate_delay(void);
-
static atomic_t init_deasserted;
void __init smp_callin(void)
int cpucount;
-extern int cpu_idle(void);
-
/*
* Activate a secondary processor.
*/
return (send_status | accept_status);
}
-extern unsigned long cpu_initialized;
-
static void __init do_boot_cpu (int apicid)
{
struct task_struct *idle;
#include <asm/pgtable.h>
#include <asm/vsyscall.h>
#include <asm/timex.h>
+#include <asm/proto.h>
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/apic.h>
#endif
spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
-extern int using_apic_timer;
-extern void smp_local_timer_interrupt(struct pt_regs * regs);
-
#undef HPET_HACK_ENABLE_DANGEROUS
#include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/pda.h>
+#include <asm/proto.h>
#include <linux/irq.h>
-asmlinkage int system_call(void);
-asmlinkage int kernel_syscall(void);
-extern void ia32_syscall(void);
-
extern struct gate_struct idt_table[256];
asmlinkage void divide_error(void);
asmlinkage void spurious_interrupt_bug(void);
asmlinkage void call_debug(void);
-extern int exception_trace;
-
struct notifier_block *die_chain;
static inline void conditional_sti(struct pt_regs *regs)
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2())
DO_ERROR(18, SIGSEGV, "reserved", reserved)
-extern void dump_pagetable(unsigned long);
-
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{
conditional_sti(regs);
+++ /dev/null
-/*
- * ACPI S3 entry/exit handling.
- *
- * Notes:
- * Relies on kernel being loaded below 4GB.
- * Needs restore_low_mappings called before.
- *
- * Copyright 2003 by Andi Kleen, SuSE Labs.
- *
- * Long mode entry loosely based on example code in chapter 14 of the x86-64 system
- * programmer's manual.
- *
- * Notebook:
-
- FIXME need to interface with suspend.c properly. do_magic. check i386. rename to suspend64.S
-
- Need to fix vgacon,mtrr,bluesmoke to do resume
-
- Interrupts should be off until the io-apic code has reinited the APIC.
- Need support for that in the pm frame work or a special hack?
-
- SMP support is non existent. Need to somehow restart the other CPUs again.
- If CPU hotplug was working it could be used. Save/Restore needs to run on the same CPU.
-
- Should check magic like i386 code
-
- suspend code copies something. check what it is.
- */
-
-#include <linux/linkage.h>
-
-#include <asm/msr.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-
-#define O(x) (x-acpi_wakeup)
-
- .text
- .code16
-ENTRY(acpi_wakeup)
- /* 16bit real mode entered from ACPI BIOS */
- /* The machine is just through BIOS setup after power down and everything set up
- by Linux needs to be restored. */
- /* The code here needs to be position independent or manually relocated,
- because it is copied to a <1MB page for real mode execution */
-
- /* A20 enabled (according to ACPI spec) */
- /* cs = acpi_wakeup >> 4 ; eip = acpi_wakeup & 0xF */
-
- movw %cs,%ax
- movw %ax,%ds /* make %ds point to acpi_wakeup */
- movw %ax,%ss
- movw $O(wakeup_stack),%sp /* setup stack */
-
- pushl $0
- popfl /* clear EFLAGS */
-
- lgdt %ds:O(pGDT) /* load kernel GDT */
-
- movl $0x1,%eax /* enable protected mode */
- movl %eax,%cr0
-
- movl %ds:O(wakeup_page_table),%edi
- ljmpl $__KERNEL16_CS,$0 /* -> s3_prot16 (filled in earlier by caller) */
-
- /* patched by s3_restore_state below */
-pGDT:
- .short 0
- .quad 0
-
- .align 4
- .globl wakeup_page_table
-wakeup_page_table:
- .long 0
-
- .align 8
-wakeup_stack:
- .fill 128,1,0
- .globl acpi_wakeup_end
-acpi_wakeup_end:
- /* end of real mode trampoline */
-
- /* pointed to by __KERNEL16_CS:0 */
- .code16
-ENTRY(s3_prot16)
- /* Now in 16bit protected mode, still no paging, stack/data segments invalid */
-
- /* Prepare everything for 64bit paging, but still keep it turned off */
- movl %cr4,%eax
- bts $5,%eax /* set PAE bit */
- movl %eax,%cr4
-
- movl %edi,%cr3 /* load kernel page table */
-
- movl $0x80000001,%eax
- cpuid /* no execute supported ? */
- movl %edx,%esi
-
- movl $MSR_EFER,%ecx
- rdmsr
- bts $8,%eax /* long mode */
- bt $20,%esi /* NX supported ? */
- jnc 1f
- bt $_EFER_NX,%eax
-1:
- wrmsr /* set temporary efer - real one is restored a bit later */
-
- movl %cr0,%eax
- bts $31,%eax /* paging */
- movl %eax,%cr0
-
- /* running in identity mapping now */
-
- /* go to 64bit code segment */
- ljmpl $__KERNEL_CS,$s3_restore_state-__START_KERNEL_map
-
- .code64
- .macro SAVEMSR msr,target
- movl $\msr,%ecx
- rdmsr
- shlq $32,%rdx
- orq %rax,%rdx
- movq %rdx,\target(%rip)
- .endm
-
- .macro RESTMSR msr,src
- movl $\msr,%ecx
- movq \src(%rip),%rax
- movq %rax,%rdx
- shrq $32,%rdx
- wrmsr
- .endm
-
- .macro SAVECTL reg
- movq %\reg,%rax
- movq %rax,saved_\reg(%rip)
- .endm
-
- .macro RESTCTL reg
- movq saved_\reg(%rip),%rax
- movq %rax,%\reg
- .endm
-
- /* Running in identity mapping, long mode */
-s3_restore_state_low:
- movq $s3_restore_state,%rax
- jmpq *%rax
-
- /* Running in real kernel mapping now */
-s3_restore_state:
- xorl %eax,%eax
- movl %eax,%ds
- movq saved_rsp(%rip),%rsp
- movw saved_ss(%rip),%ss
- movw saved_fs(%rip),%fs
- movw saved_gs(%rip),%gs
- movw saved_es(%rip),%es
- movw saved_ds(%rip),%ds
-
- lidt saved_idt
- ltr saved_tr
- lldt saved_ldt
- /* gdt is already loaded */
-
- RESTCTL cr0
- RESTCTL cr4
- /* cr3 is already loaded */
-
- RESTMSR MSR_EFER,saved_efer
- RESTMSR MSR_LSTAR,saved_lstar
- RESTMSR MSR_CSTAR,saved_cstar
- RESTMSR MSR_FS_BASE,saved_fs_base
- RESTMSR MSR_GS_BASE,saved_gs_base
- RESTMSR MSR_KERNEL_GS_BASE,saved_kernel_gs_base
- RESTMSR MSR_SYSCALL_MASK,saved_syscall_mask
-
- fxrstor fpustate(%rip)
-
- RESTCTL dr0
- RESTCTL dr1
- RESTCTL dr2
- RESTCTL dr3
- RESTCTL dr6
- RESTCTL dr7
-
- movq saved_rflags(%rip),%rax
- pushq %rax
- popfq
-
- movq saved_rbp(%rip),%rbp
- movq saved_rbx(%rip),%rbx
- movq saved_r12(%rip),%r12
- movq saved_r13(%rip),%r13
- movq saved_r14(%rip),%r14
- movq saved_r15(%rip),%r15
- ret
-
-ENTRY(acpi_prepare_wakeup)
- sgdt saved_gdt
-
- /* copy gdt descr and page table to low level wakeup code so that it can
- reload them early. */
- movq acpi_wakeup_address(%rip),%rax
- movw saved_gdt+8(%rip),%cx
- movw %cx,O(pGDT)+8(%rax)
- movq saved_gdt(%rip),%rcx
- movq %rcx,O(pGDT)(%rax)
-
- movq %cr3,%rdi
- movl %edi,O(wakeup_page_table)(%rax)
- ret
-
- /* Save CPU state. */
- /* Everything saved here needs to be restored above. */
-ENTRY(do_suspend_lowlevel)
- testl %edi,%edi
- jnz s3_restore_state
-
- SAVECTL cr0
- SAVECTL cr4
- SAVECTL cr3
-
- str saved_tr
- sidt saved_idt
- sgdt saved_gdt
- sldt saved_ldt
-
- SAVEMSR MSR_EFER,saved_efer
- SAVEMSR MSR_LSTAR,saved_lstar
- SAVEMSR MSR_CSTAR,saved_cstar
- SAVEMSR MSR_FS_BASE,saved_fs_base
- SAVEMSR MSR_GS_BASE,saved_gs_base
- SAVEMSR MSR_KERNEL_GS_BASE,saved_kernel_gs_base
- SAVEMSR MSR_SYSCALL_MASK,saved_syscall_mask
-
- movw %ds,saved_ds(%rip)
- movw %es,saved_es(%rip)
- movw %fs,saved_fs(%rip)
- movw %gs,saved_gs(%rip)
- movw %ss,saved_ss(%rip)
- movq %rsp,saved_rsp(%rip)
-
- pushfq
- popq %rax
- movq %rax,saved_rflags(%rip)
-
- SAVECTL dr0
- SAVECTL dr1
- SAVECTL dr2
- SAVECTL dr3
- SAVECTL dr6
- SAVECTL dr7
-
- fxsave fpustate(%rip)
-
- /* finally save callee saved registers */
- movq %rbp,saved_rbp(%rip)
- movq %rbx,saved_rbx(%rip)
- movq %r12,saved_r12(%rip)
- movq %r13,saved_r13(%rip)
- movq %r14,saved_r14(%rip)
- movq %r15,saved_r15(%rip)
- movq $3,%rdi
- call acpi_enter_sleep_state
- ret /* should not happen */
-
- .data
- .align 8
-saved_efer: .quad 0
-saved_lstar: .quad 0
-saved_cstar: .quad 0
-saved_cr4: .quad 0
-saved_cr3: .quad 0
-saved_cr0: .quad 0
-saved_rbp: .quad 0
-saved_rbx: .quad 0
-saved_rsp: .quad 0
-saved_r12: .quad 0
-saved_r13: .quad 0
-saved_r14: .quad 0
-saved_r15: .quad 0
-saved_rflags: .quad 0
-saved_gs_base: .quad 0
-saved_fs_base: .quad 0
-saved_kernel_gs_base: .quad 0
-saved_syscall_mask: .quad 0
-saved_dr0: .quad 0
-saved_dr1: .quad 0
-saved_dr2: .quad 0
-saved_dr3: .quad 0
-saved_dr6: .quad 0
-saved_dr7: .quad 0
-saved_ds: .short 0
-saved_fs: .short 0
-saved_gs: .short 0
-saved_es: .short 0
-saved_ss: .short 0
-saved_idt: .short 0
- .quad 0
-saved_ldt: .short 0
-saved_gdt: .short 0
- .quad 0
-saved_tr: .short 0
-
- .align 16
-fpustate: .fill 512,1,0
void __delay(unsigned long loops)
{
-#ifndef CONFIG_SIMNOW
unsigned long bclock, now;
rdtscl(bclock);
rdtscl(now);
}
while((now-bclock) < loops);
-#endif
}
inline void __const_udelay(unsigned long xloops)
#endif
#include <linux/pagemap.h>
#include <linux/bootmem.h>
+#include <linux/proc_fs.h>
#include <asm/processor.h>
#include <asm/system.h>
#define Dprintk(x...)
+extern char _stext;
+
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
/*
return 0;
}
+static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
+ kcore_vsyscall;
+
void __init mem_init(void)
{
int codesize, reservedpages, datasize, initsize;
datasize = (unsigned long) &_edata - (unsigned long) &_etext;
initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
+ /* Register memory areas for /proc/kcore */
+ kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
+ kclist_add(&kcore_vmalloc, (void *)VMALLOC_START,
+ VMALLOC_END-VMALLOC_START);
+ kclist_add(&kcore_kernel, &_stext, &_end - &_stext);
+ kclist_add(&kcore_modules, (void *)MODULES_VADDR, MODULES_LEN);
+ kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START,
+ VSYSCALL_END - VSYSCALL_START);
+
printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
end_pfn << (PAGE_SHIFT-10),
ClearPageReserved(virt_to_page(addr));
set_page_count(virt_to_page(addr), 1);
#ifdef CONFIG_INIT_DEBUG
- memset(addr & ~(PAGE_SIZE-1), 0xcc, PAGE_SIZE);
+ memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE);
#endif
free_page(addr);
totalram_pages++;
reserve_bootmem(phys, len);
#endif
}
+
+int kern_addr_valid(unsigned long addr)
+{
+ unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
+ if (above != 0 && above != -1UL)
+ return 0;
+
+ pml4_t *pml4 = pml4_offset_k(addr);
+ if (pml4_none(*pml4))
+ return 0;
+
+ pgd_t *pgd = pgd_offset_k(addr);
+ if (pgd_none(*pgd))
+ return 0;
+
+ pmd_t *pmd = pmd_offset(pgd, addr);
+ if (pmd_none(*pmd))
+ return 0;
+ if (pmd_large(*pmd))
+ return pfn_valid(pmd_pfn(*pmd));
+
+ pte_t *pte = pte_offset_kernel(pmd, addr);
+ if (pte_none(*pte))
+ return 0;
+ return pfn_valid(pte_pfn(*pte));
+}
#
# Makefile for X86_64 specific PCI routines
#
-obj-y := x86-64.o
+# Reuse the i386 PCI subsystem using symlinks
+#
+obj-y := i386.o
obj-$(CONFIG_PCI_DIRECT)+= direct.o
obj-y += fixup.o
obj-$(CONFIG_ACPI_PCI) += acpi.o
obj-y += legacy.o irq.o common.o
+
+$(obj)/direct.c: $(obj)/pci.h
+ @ln -sf ../../i386/pci/direct.c $(obj)/direct.c
+$(obj)/legacy.c: $(obj)/pci.h
+ @ln -sf ../../i386/pci/legacy.c $(obj)/legacy.c
+$(obj)/common.c: $(obj)/pci.h
+ @ln -sf ../../i386/pci/common.c $(obj)/common.c
+$(obj)/acpi.c: $(obj)/pci.h
+ @ln -sf ../../i386/pci/acpi.c $(obj)/acpi.c
+$(obj)/pci.h:
+ @ln -sf ../../i386/pci/pci.h $(obj)/pci.h
+$(obj)/irq.c: $(obj)/pci.h
+ @ln -sf ../../i386/pci/irq.c $(obj)/irq.c
+$(obj)/fixup.c: $(obj)/pci.h
+ @ln -sf ../../i386/pci/fixup.c $(obj)/fixup.c
+$(obj)/i386.c: $(obj)/pci.h
+ @ln -sf ../../i386/pci/i386.c $(obj)/i386.c
+
+clean-files += i386.c legacy.c fixup.c acpi.c irq.c pci.h common.c direct.c
+++ /dev/null
-#include <linux/pci.h>
-#include <linux/acpi.h>
-#include <linux/init.h>
-#include "pci.h"
-
-static int __init pci_acpi_init(void)
-{
- if (pcibios_scanned)
- return 0;
-
- if (!(pci_probe & PCI_NO_ACPI_ROUTING)) {
- if (!acpi_pci_irq_init()) {
- printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
- printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi'\n");
- pcibios_scanned++;
- pcibios_enable_irq = acpi_pci_irq_enable;
- } else
- printk(KERN_WARNING "PCI: Invalid ACPI-PCI IRQ routing table\n");
-
- /* still scan manually in case ACPI forgot some bus */
- pcibios_fixup_peer_bridges();
- }
-
- return 0;
-}
-
-subsys_initcall(pci_acpi_init);
+++ /dev/null
-See arch/i386/pci/changelog for early changelog.
+++ /dev/null
-/*
- * Low-Level PCI Support for PC
- *
- * (c) 1999--2000 Martin Mares <mj@ucw.cz>
-
- Note: on x86-64 there is no PCI BIOS so there is no way to sort in the
- same order as 32bit Linux. This could cause grief for dualbooting because
- devices may wander. May want to use ACPI for sorting eventually.
-
- */
-
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/cache.h>
-
-#include "pci.h"
-
-unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
-
-int pcibios_last_bus = 0xff; /* XXX */
-struct pci_bus *pci_root_bus = NULL;
-struct pci_ops *pci_root_ops = NULL;
-
-int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL;
-int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL;
-
-/*
- * legacy, numa, and acpi all want to call pcibios_scan_root
- * from their initcalls. This flag prevents that.
- */
-int pcibios_scanned;
-
-/*
- * This interrupt-safe spinlock protects all accesses to PCI
- * configuration space.
- */
-spinlock_t pci_config_lock = SPIN_LOCK_UNLOCKED;
-
-/*
- * Several buggy motherboards address only 16 devices and mirror
- * them to next 16 IDs. We try to detect this `feature' on all
- * primary buses (those containing host bridges as they are
- * expected to be unique) and remove the ghost devices.
- */
-
-static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
-{
- struct list_head *ln, *mn;
- struct pci_dev *d, *e;
- int mirror = PCI_DEVFN(16,0);
- int seen_host_bridge = 0;
- int i;
-
- DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
- for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
- d = pci_dev_b(ln);
- if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
- seen_host_bridge++;
- for (mn=ln->next; mn != &b->devices; mn=mn->next) {
- e = pci_dev_b(mn);
- if (e->devfn != d->devfn + mirror ||
- e->vendor != d->vendor ||
- e->device != d->device ||
- e->class != d->class)
- continue;
- for(i=0; i<PCI_NUM_RESOURCES; i++)
- if (e->resource[i].start != d->resource[i].start ||
- e->resource[i].end != d->resource[i].end ||
- e->resource[i].flags != d->resource[i].flags)
- continue;
- break;
- }
- if (mn == &b->devices)
- return;
- }
- if (!seen_host_bridge)
- return;
- printk(KERN_WARNING "PCI: Ignoring ghost devices on bus %02x\n", b->number);
-
- ln = &b->devices;
- while (ln->next != &b->devices) {
- d = pci_dev_b(ln->next);
- if (d->devfn >= mirror) {
- list_del(&d->global_list);
- list_del(&d->bus_list);
- kfree(d);
- } else
- ln = ln->next;
- }
-}
-
-struct pbus_set_ranges_data;
-
-void __devinit
-pcibios_fixup_pbus_ranges (struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
-{
-}
-
-/*
- * Called after each bus is probed, but before its children
- * are examined.
- */
-
-void __devinit pcibios_fixup_bus(struct pci_bus *b)
-{
- pcibios_fixup_ghosts(b);
- pci_read_bridge_bases(b);
-}
-
-
-struct pci_bus * __devinit pcibios_scan_root(int busnum)
-{
- struct list_head *list;
- struct pci_bus *bus;
-
- list_for_each(list, &pci_root_buses) {
- bus = pci_bus_b(list);
- if (bus->number == busnum) {
- /* Already scanned */
- return bus;
- }
- }
-
- printk("PCI: Probing PCI hardware (bus %02x)\n", busnum);
-
- return pci_scan_bus(busnum, pci_root_ops, NULL);
-}
-
-extern u8 pci_cache_line_size;
-
-static int __init pcibios_init(void)
-{
- if (!pci_root_ops) {
- printk("PCI: System does not support PCI\n");
- return 0;
- }
-
- pci_cache_line_size = boot_cpu_data.x86_clflush_size >> 2;
-
- pcibios_resource_survey();
-
-#ifdef CONFIG_GART_IOMMU
- pci_iommu_init();
-#endif
-
- /* may eventually need to do ACPI sort here. */
- return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-char * __devinit pcibios_setup(char *str)
-{
- if (!strcmp(str, "off")) {
- pci_probe = 0;
- return NULL;
- }
-#ifdef CONFIG_PCI_DIRECT
- else if (!strcmp(str, "conf1")) {
- pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS;
- return NULL;
- }
- else if (!strcmp(str, "conf2")) {
- pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS;
- return NULL;
- }
-#endif
-#ifdef CONFIG_ACPI_PCI
- else if (!strcmp(str, "noacpi")) {
- pci_probe |= PCI_NO_ACPI_ROUTING;
- return NULL;
- }
-#endif
- else if (!strcmp(str, "rom")) {
- pci_probe |= PCI_ASSIGN_ROMS;
- return NULL;
- } else if (!strcmp(str, "assign-busses")) {
- pci_probe |= PCI_ASSIGN_ALL_BUSSES;
- return NULL;
- } else if (!strcmp(str, "usepirqmask")) {
- pci_probe |= PCI_USE_PIRQ_MASK;
- return NULL;
- } else if (!strncmp(str, "irqmask=", 8)) {
- pcibios_irq_mask = simple_strtol(str+8, NULL, 0);
- return NULL;
- } else if (!strncmp(str, "lastbus=", 8)) {
- pcibios_last_bus = simple_strtol(str+8, NULL, 0);
- return NULL;
- }
- return str;
-}
-
-unsigned int pcibios_assign_all_busses(void)
-{
- return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
-}
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
- int err;
-
- if ((err = pcibios_enable_resources(dev, mask)) < 0)
- return err;
-
- return pcibios_enable_irq(dev);
-}
+++ /dev/null
-/*
- * direct.c - Low-level direct PCI config space access
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include "pci.h"
-
-/*
- * Functions for accessing PCI configuration space with type 1 accesses
- */
-
-#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \
- (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3))
-
-static int __pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
-{
- unsigned long flags;
-
- if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
- return -EINVAL;
-
- spin_lock_irqsave(&pci_config_lock, flags);
-
- outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
-
- switch (len) {
- case 1:
- *value = inb(0xCFC + (reg & 3));
- break;
- case 2:
- *value = inw(0xCFC + (reg & 2));
- break;
- case 4:
- *value = inl(0xCFC);
- break;
- }
-
- spin_unlock_irqrestore(&pci_config_lock, flags);
-
- return 0;
-}
-
-static int __pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
-{
- unsigned long flags;
-
- if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
- return -EINVAL;
-
- spin_lock_irqsave(&pci_config_lock, flags);
-
- outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);
-
- switch (len) {
- case 1:
- outb((u8)value, 0xCFC + (reg & 3));
- break;
- case 2:
- outw((u16)value, 0xCFC + (reg & 2));
- break;
- case 4:
- outl((u32)value, 0xCFC);
- break;
- }
-
- spin_unlock_irqrestore(&pci_config_lock, flags);
-
- return 0;
-}
-
-#undef PCI_CONF1_ADDRESS
-
-static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
-{
- return __pci_conf1_read(0, bus->number, PCI_SLOT(devfn),
- PCI_FUNC(devfn), where, size, value);
-}
-
-static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
-{
- return __pci_conf1_write(0, bus->number, PCI_SLOT(devfn),
- PCI_FUNC(devfn), where, size, value);
-}
-
-static struct pci_ops pci_direct_conf1 = {
- .read = pci_conf1_read,
- .write = pci_conf1_write,
-};
-
-
-/*
- * Functions for accessing PCI configuration space with type 2 accesses
- */
-
-#define PCI_CONF2_ADDRESS(dev, reg) (u16)(0xC000 | (dev << 8) | reg)
-
-static int __pci_conf2_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
-{
- unsigned long flags;
-
- if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
- return -EINVAL;
-
- if (dev & 0x10)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- spin_lock_irqsave(&pci_config_lock, flags);
-
- outb((u8)(0xF0 | (fn << 1)), 0xCF8);
- outb((u8)bus, 0xCFA);
-
- switch (len) {
- case 1:
- *value = inb(PCI_CONF2_ADDRESS(dev, reg));
- break;
- case 2:
- *value = inw(PCI_CONF2_ADDRESS(dev, reg));
- break;
- case 4:
- *value = inl(PCI_CONF2_ADDRESS(dev, reg));
- break;
- }
-
- outb (0, 0xCF8);
-
- spin_unlock_irqrestore(&pci_config_lock, flags);
-
- return 0;
-}
-
-static int __pci_conf2_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
-{
- unsigned long flags;
-
- if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
- return -EINVAL;
-
- if (dev & 0x10)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- spin_lock_irqsave(&pci_config_lock, flags);
-
- outb((u8)(0xF0 | (fn << 1)), 0xCF8);
- outb((u8)bus, 0xCFA);
-
- switch (len) {
- case 1:
- outb ((u8)value, PCI_CONF2_ADDRESS(dev, reg));
- break;
- case 2:
- outw ((u16)value, PCI_CONF2_ADDRESS(dev, reg));
- break;
- case 4:
- outl ((u32)value, PCI_CONF2_ADDRESS(dev, reg));
- break;
- }
-
- outb (0, 0xCF8);
-
- spin_unlock_irqrestore(&pci_config_lock, flags);
-
- return 0;
-}
-
-#undef PCI_CONF2_ADDRESS
-
-static int pci_conf2_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
-{
- return __pci_conf2_read(0, bus->number, PCI_SLOT(devfn),
- PCI_FUNC(devfn), where, size, value);
-}
-
-static int pci_conf2_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
-{
- return __pci_conf2_write(0, bus->number, PCI_SLOT(devfn),
- PCI_FUNC(devfn), where, size, value);
-}
-
-static struct pci_ops pci_direct_conf2 = {
- .read = pci_conf2_read,
- .write = pci_conf2_write,
-};
-
-
-/*
- * Before we decide to use direct hardware access mechanisms, we try to do some
- * trivial checks to ensure it at least _seems_ to be working -- we just test
- * whether bus 00 contains a host bridge (this is similar to checking
- * techniques used in XFree86, but ours should be more reliable since we
- * attempt to make use of direct access hints provided by the PCI BIOS).
- *
- * This should be close to trivial, but it isn't, because there are buggy
- * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
- */
-static int __devinit pci_sanity_check(struct pci_ops *o)
-{
- u32 x = 0;
- int retval = 0;
- struct pci_bus *bus; /* Fake bus and device */
- struct pci_dev *dev;
-
- if (pci_probe & PCI_NO_CHECKS)
- return 1;
-
- bus = kmalloc(sizeof(*bus), GFP_ATOMIC);
- dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
- if (!bus || !dev) {
- printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__);
- goto exit;
- }
-
- bus->number = 0;
- dev->bus = bus;
- for(dev->devfn=0; dev->devfn < 0x100; dev->devfn++)
- if ((!o->read(bus, dev->devfn, PCI_CLASS_DEVICE, 2, &x) &&
- (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) ||
- (!o->read(bus, dev->devfn, PCI_VENDOR_ID, 2, &x) &&
- (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) {
- retval = 1;
- goto exit;
- }
- DBG("PCI: Sanity check failed\n");
-exit:
- kfree(dev);
- kfree(bus);
- return retval;
-}
-
-static int __init pci_direct_init(void)
-{
- unsigned int tmp;
- unsigned long flags;
-
- local_irq_save(flags);
-
- /*
- * Check if configuration type 1 works.
- */
- if (pci_probe & PCI_PROBE_CONF1) {
- outb (0x01, 0xCFB);
- tmp = inl (0xCF8);
- outl (0x80000000, 0xCF8);
- if (inl (0xCF8) == 0x80000000 &&
- pci_sanity_check(&pci_direct_conf1)) {
- outl (tmp, 0xCF8);
- local_irq_restore(flags);
- printk(KERN_INFO "PCI: Using configuration type 1\n");
- if (!request_region(0xCF8, 8, "PCI conf1"))
- pci_root_ops = NULL;
- else
- pci_root_ops = &pci_direct_conf1;
- return 0;
- }
- outl (tmp, 0xCF8);
- }
-
- /*
- * Check if configuration type 2 works.
- */
- if (pci_probe & PCI_PROBE_CONF2) {
- outb (0x00, 0xCFB);
- outb (0x00, 0xCF8);
- outb (0x00, 0xCFA);
- if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00 &&
- pci_sanity_check(&pci_direct_conf2)) {
- local_irq_restore(flags);
- printk(KERN_INFO "PCI: Using configuration type 2\n");
- if (!request_region(0xCF8, 4, "PCI conf2"))
- pci_root_ops = NULL;
- else
- pci_root_ops = &pci_direct_conf2;
- return 0;
- }
- }
-
- local_irq_restore(flags);
- return 0;
-}
-
-arch_initcall(pci_direct_init);
+++ /dev/null
-/*
- * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
- *
-
-Short list on x86-64........so far.
-
- */
-
-#include <linux/pci.h>
-#include <linux/init.h>
-#include "pci.h"
-
-static void __devinit pci_fixup_ncr53c810(struct pci_dev *d)
-{
- /*
- * NCR 53C810 returns class code 0 (at least on some systems).
- * Fix class to be PCI_CLASS_STORAGE_SCSI
- */
- if (!d->class) {
- printk(KERN_WARNING "PCI: fixing NCR 53C810 class code for %s\n", d->slot_name);
- d->class = PCI_CLASS_STORAGE_SCSI << 8;
- }
-}
-
-static void __devinit pci_fixup_ide_bases(struct pci_dev *d)
-{
- int i;
-
- /*
- * PCI IDE controllers use non-standard I/O port decoding, respect it.
- */
- if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
- return;
- DBG("PCI: IDE base address fixup for %s\n", d->slot_name);
- for(i=0; i<4; i++) {
- struct resource *r = &d->resource[i];
- if ((r->start & ~0x80) == 0x374) {
- r->start |= 2;
- r->end = r->start;
- }
- }
-}
-
-struct pci_fixup pcibios_fixups[] = {
- { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases },
- { PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810 },
- { 0 }
-};
+++ /dev/null
-/*
- * Low-Level PCI Support for PC -- Routing of Interrupts
- *
- * (c) 1999--2000 Martin Mares <mj@ucw.cz>
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/io_apic.h>
-
-#include "pci.h"
-
-#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
-#define PIRQ_VERSION 0x0100
-
-int broken_hp_bios_irq9;
-
-static struct irq_routing_table *pirq_table;
-
-/*
- * Never use: 0, 1, 2 (timer, keyboard, and cascade)
- * Avoid using: 13, 14 and 15 (FP error and IDE).
- * Penalize: 3, 4, 6, 7, 12 (known ISA uses: serial, floppy, parallel and mouse)
- */
-unsigned int pcibios_irq_mask = 0xfff8;
-
-static int pirq_penalty[16] = {
- 1000000, 1000000, 1000000, 1000, 1000, 0, 1000, 1000,
- 0, 0, 0, 0, 1000, 100000, 100000, 100000
-};
-
-struct irq_router {
- char *name;
- u16 vendor, device;
- int (*get)(struct pci_dev *router, struct pci_dev *dev, int pirq);
- int (*set)(struct pci_dev *router, struct pci_dev *dev, int pirq, int new);
-};
-
-int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
-
-/*
- * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
- */
-
-static struct irq_routing_table * __init pirq_find_routing_table(void)
-{
- u8 *addr;
- struct irq_routing_table *rt;
- int i;
- u8 sum;
-
- for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
- rt = (struct irq_routing_table *) addr;
- if (rt->signature != PIRQ_SIGNATURE ||
- rt->version != PIRQ_VERSION ||
- rt->size % 16 ||
- rt->size < sizeof(struct irq_routing_table))
- continue;
- sum = 0;
- for(i=0; i<rt->size; i++)
- sum += addr[i];
- if (!sum) {
- DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
- return rt;
- }
- }
- return NULL;
-}
-
-/*
- * If we have a IRQ routing table, use it to search for peer host
- * bridges. It's a gross hack, but since there are no other known
- * ways how to get a list of buses, we have to go this way.
- */
-
-static void __init pirq_peer_trick(void)
-{
- struct irq_routing_table *rt = pirq_table;
- u8 busmap[256];
- int i;
- struct irq_info *e;
-
- memset(busmap, 0, sizeof(busmap));
- for(i=0; i < (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); i++) {
- e = &rt->slots[i];
-#ifdef DEBUG
- {
- int j;
- DBG("%02x:%02x slot=%02x", e->bus, e->devfn/8, e->slot);
- for(j=0; j<4; j++)
- DBG(" %d:%02x/%04x", j, e->irq[j].link, e->irq[j].bitmap);
- DBG("\n");
- }
-#endif
- busmap[e->bus] = 1;
- }
- for(i=1; i<256; i++)
- /*
- * It might be a secondary bus, but in this case its parent is already
- * known (ascending bus order) and therefore pci_scan_bus returns immediately.
- */
- if (busmap[i] && pci_scan_bus(i, pci_root_bus->ops, NULL))
- printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
- //pcibios_last_bus = -1;
-}
-
-/*
- * Code for querying and setting of IRQ routes on various interrupt routers.
- */
-
-void eisa_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)) {
- DBG(" -> edge");
- outb(val | mask, port);
- }
-}
-
-/*
- * Common IRQ routing practice: nybbles in config space,
- * offset by some magic constant.
- */
-static unsigned int read_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr)
-{
- u8 x;
- unsigned reg = offset + (nr >> 1);
-
- pci_read_config_byte(router, reg, &x);
- return (nr & 1) ? (x >> 4) : (x & 0xf);
-}
-
-static void write_config_nybble(struct pci_dev *router, unsigned offset, unsigned nr, unsigned int val)
-{
- u8 x;
- unsigned reg = offset + (nr >> 1);
-
- pci_read_config_byte(router, reg, &x);
- x = (nr & 1) ? ((x & 0x0f) | (val << 4)) : ((x & 0xf0) | val);
- pci_write_config_byte(router, reg, x);
-}
-
-#if 0 /* enable when pci ids ae known */
-/*
- * The VIA pirq rules are nibble-based, like ALI,
- * but without the ugly irq number munging.
- */
-static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
- return read_config_nybble(router, 0x55, pirq);
-}
-
-static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
- write_config_nybble(router, 0x55, pirq, irq);
- return 1;
-}
-
-/*
- * PIRQ routing for SiS 85C503 router used in several SiS chipsets
- * According to the SiS 5595 datasheet (preliminary V1.0, 12/24/1997)
- * the related registers work as follows:
- *
- * general: one byte per re-routable IRQ,
- * bit 7 IRQ mapping enabled (0) or disabled (1)
- * bits [6:4] reserved
- * bits [3:0] IRQ to map to
- * allowed: 3-7, 9-12, 14-15
- * reserved: 0, 1, 2, 8, 13
- *
- * individual registers in device config space:
- *
- * 0x41/0x42/0x43/0x44: PCI INT A/B/C/D - bits as in general case
- *
- * 0x61: IDEIRQ: bits as in general case - but:
- * bits [6:5] must be written 01
- * bit 4 channel-select primary (0), secondary (1)
- *
- * 0x62: USBIRQ: bits as in general case - but:
- * bit 4 OHCI function disabled (0), enabled (1)
- *
- * 0x6a: ACPI/SCI IRQ - bits as in general case
- *
- * 0x7e: Data Acq. Module IRQ - bits as in general case
- *
- * Apparently there are systems implementing PCI routing table using both
- * link values 0x01-0x04 and 0x41-0x44 for PCI INTA..D, but register offsets
- * like 0x62 as link values for USBIRQ e.g. So there is no simple
- * "register = offset + pirq" relation.
- * Currently we support PCI INTA..D and USBIRQ and try our best to handle
- * both link mappings.
- * IDE/ACPI/DAQ mapping is currently unsupported (left untouched as set by BIOS).
- */
-
-static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
- u8 x;
- int reg = pirq;
-
- switch(pirq) {
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- reg += 0x40;
- case 0x41:
- case 0x42:
- case 0x43:
- case 0x44:
- case 0x62:
- pci_read_config_byte(router, reg, &x);
- if (reg != 0x62)
- break;
- if (!(x & 0x40))
- return 0;
- break;
- case 0x61:
- case 0x6a:
- case 0x7e:
- printk(KERN_INFO "SiS pirq: advanced IDE/ACPI/DAQ mapping not yet implemented\n");
- return 0;
- default:
- printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq);
- return 0;
- }
- return (x & 0x80) ? 0 : (x & 0x0f);
-}
-
-static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
- u8 x;
- int reg = pirq;
-
- switch(pirq) {
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- reg += 0x40;
- case 0x41:
- case 0x42:
- case 0x43:
- case 0x44:
- case 0x62:
- x = (irq&0x0f) ? (irq&0x0f) : 0x80;
- if (reg != 0x62)
- break;
- /* always mark OHCI enabled, as nothing else knows about this */
- x |= 0x40;
- break;
- case 0x61:
- case 0x6a:
- case 0x7e:
- printk(KERN_INFO "advanced SiS pirq mapping not yet implemented\n");
- return 0;
- default:
- printk(KERN_INFO "SiS router pirq escape (%d)\n", pirq);
- return 0;
- }
- pci_write_config_byte(router, reg, x);
-
- return 1;
-}
-
-#endif
-
-/* Support for AMD756 PCI IRQ Routing
- * Jhon H. Caicedo <jhcaiced@osso.org.co>
- * Jun/21/2001 0.2.0 Release, fixed to use "nybble" functions... (jhcaiced)
- * Jun/19/2001 Alpha Release 0.1.0 (jhcaiced)
- * The AMD756 pirq rules are nibble-based
- * offset 0x56 0-3 PIRQA 4-7 PIRQB
- * offset 0x57 0-3 PIRQC 4-7 PIRQD
- */
-static int pirq_amd756_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
-{
- u8 irq;
- irq = 0;
- if (pirq <= 4)
- {
- irq = read_config_nybble(router, 0x56, pirq - 1);
- }
- printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n",
- dev->vendor, dev->device, pirq, irq);
- return irq;
-}
-
-static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
-{
- printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n",
- dev->vendor, dev->device, pirq, irq);
- if (pirq <= 4)
- {
- write_config_nybble(router, 0x56, pirq - 1, irq);
- }
- return 1;
-}
-
-static struct irq_router pirq_routers[] = {
-#if 0 /* all these do not exist on Hammer currently, but keep one example
- for each. All these vendors have announced K8 chipsets, so we'll
- eventually need a router for them. Luckily they tend to use the
- same ones, so with luck just enabling the existing ones will work
- when you know the final PCI ids. */
-
- { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set },
-
- { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set },
-
- { "SIS", PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, pirq_sis_get, pirq_sis_set },
-
-#endif
-
- { "AMD756 VIPER", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B,
- pirq_amd756_get, pirq_amd756_set },
-
- { "default", 0, 0, NULL, NULL }
-};
-
-static struct irq_router *pirq_router;
-static struct pci_dev *pirq_router_dev;
-
-static void __init pirq_find_router(void)
-{
- struct irq_routing_table *rt = pirq_table;
- struct irq_router *r;
-
- DBG("PCI: Attempting to find IRQ router for %04x:%04x\n",
- rt->rtr_vendor, rt->rtr_device);
-
- /* fall back to default router if nothing else found */
- pirq_router = &pirq_routers[ARRAY_SIZE(pirq_routers) - 1];
-
- pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
- if (!pirq_router_dev) {
- DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn);
- return;
- }
-
- for(r=pirq_routers; r->vendor; r++) {
- /* Exact match against router table entry? Use it! */
- if (r->vendor == rt->rtr_vendor && r->device == rt->rtr_device) {
- pirq_router = r;
- break;
- }
- /* Match against router device entry? Use it as a fallback */
- if (r->vendor == pirq_router_dev->vendor && r->device == pirq_router_dev->device) {
- pirq_router = r;
- }
- }
- printk(KERN_INFO "PCI: Using IRQ router %s [%04x/%04x] at %s\n",
- pirq_router->name,
- pirq_router_dev->vendor,
- pirq_router_dev->device,
- pirq_router_dev->slot_name);
-}
-
-static struct irq_info *pirq_get_info(struct pci_dev *dev)
-{
- struct irq_routing_table *rt = pirq_table;
- int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
- struct irq_info *info;
-
- for (info = rt->slots; entries--; info++)
- if (info->bus == dev->bus->number && PCI_SLOT(info->devfn) == PCI_SLOT(dev->devfn))
- return info;
- return NULL;
-}
-
-static irqreturn_t pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
- return IRQ_NONE;
-}
-
-static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
-{
- u8 pin;
- struct irq_info *info;
- int i, pirq, newirq;
- int irq = 0;
- u32 mask;
- struct irq_router *r = pirq_router;
- struct pci_dev *dev2 = NULL;
- char *msg = NULL;
-
- /* Find IRQ pin */
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
- if (!pin) {
- DBG(" -> no interrupt pin\n");
- return 0;
- }
- pin = pin - 1;
-
- /* Find IRQ routing entry */
-
- if (!pirq_table)
- return 0;
-
- DBG("IRQ for %s:%d", dev->slot_name, pin);
- info = pirq_get_info(dev);
- if (!info) {
- DBG(" -> not found in routing table\n");
- return 0;
- }
- pirq = info->irq[pin].link;
- mask = info->irq[pin].bitmap;
- if (!pirq) {
- DBG(" -> not routed\n");
- return 0;
- }
- DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs);
- mask &= pcibios_irq_mask;
-
- /* Work around broken HP Pavilion Notebooks which assign USB to
- IRQ 9 even though it is actually wired to IRQ 11 */
-
- if (broken_hp_bios_irq9 && pirq == 0x59 && dev->irq == 9) {
- dev->irq = 11;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
- r->set(pirq_router_dev, dev, pirq, 11);
- }
-
- /*
- * Find the best IRQ to assign: use the one
- * reported by the device if possible.
- */
- newirq = dev->irq;
- if (!((1 << newirq) & mask)) {
- if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0;
- else printk(KERN_WARNING "PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n", newirq, dev->slot_name);
- }
- if (!newirq && assign) {
- for (i = 0; i < 16; i++) {
- if (!(mask & (1 << i)))
- continue;
- if (pirq_penalty[i] < pirq_penalty[newirq] &&
- !request_irq(i, pcibios_test_irq_handler, SA_SHIRQ, "pci-test", dev)) {
- free_irq(i, dev);
- newirq = i;
- }
- }
- }
- DBG(" -> newirq=%d", newirq);
-
- /* Check if it is hardcoded */
- if ((pirq & 0xf0) == 0xf0) {
- irq = pirq & 0xf;
- DBG(" -> hardcoded IRQ %d\n", irq);
- msg = "Hardcoded";
- } else if ( r->get && (irq = r->get(pirq_router_dev, dev, pirq)) && \
- ((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) {
- DBG(" -> got IRQ %d\n", irq);
- msg = "Found";
- } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
- DBG(" -> assigning IRQ %d", newirq);
- if (r->set(pirq_router_dev, dev, pirq, newirq)) {
- eisa_set_level_irq(newirq);
- DBG(" ... OK\n");
- msg = "Assigned";
- irq = newirq;
- }
- }
-
- if (!irq) {
- DBG(" ... failed\n");
- if (newirq && mask == (1 << newirq)) {
- msg = "Guessed";
- irq = newirq;
- } else
- return 0;
- }
- printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, dev->slot_name);
-
- /* Update IRQ for all devices with the same pirq value */
- while ((dev2 = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
- pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
- if (!pin)
- continue;
- pin--;
- info = pirq_get_info(dev2);
- if (!info)
- continue;
- if (info->irq[pin].link == pirq) {
- /* We refuse to override the dev->irq information. Give a warning! */
- if ( dev2->irq && dev2->irq != irq && \
- (!(pci_probe & PCI_USE_PIRQ_MASK) || \
- ((1 << dev2->irq) & mask)) ) {
- printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
- dev2->slot_name, dev2->irq, irq);
- continue;
- }
- dev2->irq = irq;
- pirq_penalty[irq]++;
- if (dev != dev2)
- printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, dev2->slot_name);
- }
- }
- return 1;
-}
-
-void __init pcibios_fixup_irqs(void)
-{
- struct pci_dev *dev = NULL;
- u8 pin;
-
- DBG("PCI: IRQ fixup\n");
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- /*
- * If the BIOS has set an out of range IRQ number, just ignore it.
- * Also keep track of which IRQ's are already in use.
- */
- if (dev->irq >= 16) {
- DBG("%s: ignoring bogus IRQ %d\n", dev->slot_name, dev->irq);
- dev->irq = 0;
- }
- /* If the IRQ is already assigned to a PCI device, ignore its ISA use penalty */
- if (pirq_penalty[dev->irq] >= 100 && pirq_penalty[dev->irq] < 100000)
- pirq_penalty[dev->irq] = 0;
- pirq_penalty[dev->irq]++;
- }
-
- dev = NULL;
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-#ifdef CONFIG_X86_IO_APIC
- /*
- * Recalculate IRQ numbers if we use the I/O APIC.
- */
- if (io_apic_assign_pci_irqs)
- {
- int irq;
-
- if (pin) {
- pin--; /* interrupt pins are numbered starting from 1 */
- irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
- /*
- * Busses behind bridges are typically not listed in the MP-table.
- * In this case we have to look up the IRQ based on the parent bus,
- * parent slot, and pin number. The SMP code detects such bridged
- * busses itself so we should get into this branch reliably.
- */
- if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
- struct pci_dev * bridge = dev->bus->self;
-
- pin = (pin + PCI_SLOT(dev->devfn)) % 4;
- irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
- PCI_SLOT(bridge->devfn), pin);
- if (irq >= 0)
- printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n",
- bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq);
- }
- if (irq >= 0) {
- printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
- dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
- dev->irq = irq;
- }
- }
- }
-#endif
- /*
- * Still no IRQ? Try to lookup one...
- */
- if (pin && !dev->irq)
- pcibios_lookup_irq(dev, 0);
- }
-}
-
-static int __init pcibios_irq_init(void)
-{
- DBG("PCI: IRQ init\n");
-
- if (pcibios_enable_irq)
- return 0;
-
- pirq_table = pirq_find_routing_table();
-
- if (pirq_table) {
- pirq_peer_trick();
- pirq_find_router();
- if (pirq_table->exclusive_irqs) {
- int i;
- for (i=0; i<16; i++)
- if (!(pirq_table->exclusive_irqs & (1 << i)))
- pirq_penalty[i] += 100;
- }
- /* If we're using the I/O APIC, avoid using the PCI IRQ routing table */
- if (io_apic_assign_pci_irqs)
- pirq_table = NULL;
- }
-
- pcibios_enable_irq = pirq_enable_irq;
-
- pcibios_fixup_irqs();
- return 0;
-}
-
-subsys_initcall(pcibios_irq_init);
-
-
-void pcibios_penalize_isa_irq(int irq)
-{
- /*
- * If any ISAPnP device reports an IRQ in its list of possible
- * IRQ's, we try to avoid assigning it to PCI devices.
- */
- pirq_penalty[irq] += 100;
-}
-
-int pirq_enable_irq(struct pci_dev *dev)
-{
- u8 pin;
- extern int interrupt_line_quirk;
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
- if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
- /* With IDE legacy devices the IRQ lookup failure is not a problem.. */
- if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
- return 0;
-
- printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.\n",
- 'A' + pin - 1, dev->slot_name);
- }
- /* VIA bridges use interrupt line for apic/pci steering across
- the V-Link */
- else if (interrupt_line_quirk)
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-
- return 0;
-}
+++ /dev/null
-/*
- * legacy.c - traditional, old school PCI bus probing
- */
-#include <linux/init.h>
-#include <linux/pci.h>
-#include "pci.h"
-
-/*
- * Discover remaining PCI buses in case there are peer host bridges.
- * We use the number of last PCI bus provided by the PCI BIOS.
- */
-void __devinit pcibios_fixup_peer_bridges(void)
-{
- int n;
- struct pci_bus *bus;
- struct pci_dev *dev;
- u16 l;
-
- if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
- return;
- DBG("PCI: Peer bridge fixup\n");
-
- bus = kmalloc(sizeof(*bus), GFP_ATOMIC);
- dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
- if (!bus || !dev) {
- printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__);
- goto exit;
- }
-
- for (n=0; n <= pcibios_last_bus; n++) {
- if (pci_bus_exists(&pci_root_buses, n))
- continue;
- bus->number = n;
- bus->ops = pci_root_ops;
- dev->bus = bus;
- for (dev->devfn=0; dev->devfn<256; dev->devfn += 8)
- if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) &&
- l != 0x0000 && l != 0xffff) {
- DBG("Found device at %02x:%02x [%04x]\n", n, dev->devfn, l);
- printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
- pci_scan_bus(n, pci_root_ops, NULL);
- break;
- }
- }
-exit:
- kfree(dev);
- kfree(bus);
-}
-
-static int __init pci_legacy_init(void)
-{
- if (!pci_root_ops) {
- printk("PCI: System does not support PCI\n");
- return 0;
- }
-
- if (pcibios_scanned++)
- return 0;
-
- printk("PCI: Probing PCI hardware\n");
- pci_root_bus = pcibios_scan_root(0);
-
- pcibios_fixup_peer_bridges();
-
- return 0;
-}
-
-subsys_initcall(pci_legacy_init);
+++ /dev/null
-/*
- * Low-Level PCI Access for x86-64 machines.
- *
- * (c) 1999 Martin Mares <mj@ucw.cz>
- */
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-#define PCI_PROBE_BIOS 0x0001
-#define PCI_PROBE_CONF1 0x0002
-#define PCI_PROBE_CONF2 0x0004
-#define PCI_NO_SORT 0x0100
-#define PCI_BIOS_SORT 0x0200
-#define PCI_NO_CHECKS 0x0400
-#define PCI_USE_PIRQ_MASK 0x0800
-#define PCI_ASSIGN_ROMS 0x1000
-#define PCI_BIOS_IRQ_SCAN 0x2000
-#define PCI_ASSIGN_ALL_BUSSES 0x4000
-#define PCI_NO_ACPI_ROUTING 0x8000
-
-extern unsigned int pci_probe;
-
-extern unsigned int pcibios_max_latency;
-
-void pcibios_resource_survey(void);
-int pcibios_enable_resources(struct pci_dev *, int);
-
-/* pci-pc.c */
-
-extern int pcibios_last_bus;
-extern struct pci_bus *pci_root_bus;
-extern struct pci_ops *pci_root_ops;
-
-/* pci-irq.c */
-
-struct irq_info {
- u8 bus, devfn; /* Bus, device and function */
- struct {
- u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
- u16 bitmap; /* Available IRQs */
- } __attribute__((packed)) irq[4];
- u8 slot; /* Slot number, 0=onboard */
- u8 rfu;
-} __attribute__((packed));
-
-struct irq_routing_table {
- u32 signature; /* PIRQ_SIGNATURE should be here */
- u16 version; /* PIRQ_VERSION */
- u16 size; /* Table size in bytes */
- u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
- u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
- u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
- u32 miniport_data; /* Crap */
- u8 rfu[11];
- u8 checksum; /* Modulo 256 checksum must give zero */
- struct irq_info slots[0];
-} __attribute__((packed));
-
-extern unsigned int pcibios_irq_mask;
-
-extern int pcibios_scanned;
-extern spinlock_t pci_config_lock;
-
-int pirq_enable_irq(struct pci_dev *dev);
-
-extern int (*pcibios_enable_irq)(struct pci_dev *dev);
-
-/* legacy.c */
-extern void pcibios_fixup_peer_bridges(void);
+++ /dev/null
-/*
- * Low-Level PCI Access for x86-64 machines
- *
- * Copyright 1993, 1994 Drew Eckhardt
- * Visionary Computing
- * (Unix and Linux consulting and custom programming)
- * Drew@Colorado.EDU
- * +1 (303) 786-7975
- *
- * Drew's work was sponsored by:
- * iX Multiuser Multitasking Magazine
- * Hannover, Germany
- * hm@ix.de
- *
- * Copyright 1997--2000 Martin Mares <mj@ucw.cz>
- *
- * For more information, please consult the following manuals (look at
- * http://www.pcisig.com/ for how to get them):
- *
- * PCI BIOS Specification
- * PCI Local Bus Specification
- * PCI to PCI Bridge Specification
- * PCI System Design Guide
- *
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-
-#include "pci.h"
-
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
-void
-pcibios_align_resource(void *data, struct resource *res,
- unsigned long size, unsigned long align)
-{
- if (res->flags & IORESOURCE_IO) {
- unsigned long start = res->start;
-
- if (start & 0x300) {
- start = (start + 0x3ff) & ~0x3ff;
- res->start = start;
- }
- }
-}
-
-
-/*
- * Handle resources of PCI devices. If the world were perfect, we could
- * just allocate all the resource regions and do nothing more. It isn't.
- * On the other hand, we cannot just re-allocate all devices, as it would
- * require us to know lots of host bridge internals. So we attempt to
- * keep as much of the original configuration as possible, but tweak it
- * when it's found to be wrong.
- *
- * Known BIOS problems we have to work around:
- * - I/O or memory regions not configured
- * - regions configured, but not enabled in the command register
- * - bogus I/O addresses above 64K used
- * - expansion ROMs left enabled (this may sound harmless, but given
- * the fact the PCI specs explicitly allow address decoders to be
- * shared between expansion ROMs and other resource regions, it's
- * at least dangerous)
- *
- * Our solution:
- * (1) Allocate resources for all buses behind PCI-to-PCI bridges.
- * This gives us fixed barriers on where we can allocate.
- * (2) Allocate resources for all enabled devices. If there is
- * a collision, just mark the resource as unallocated. Also
- * disable expansion ROMs during this step.
- * (3) Try to allocate resources for disabled devices. If the
- * resources were assigned correctly, everything goes well,
- * if they weren't, they won't disturb allocation of other
- * resources.
- * (4) Assign new addresses to resources which were either
- * not configured at all or misconfigured. If explicitly
- * requested by the user, configure expansion ROM address
- * as well.
- */
-
-static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
-{
- struct list_head *ln;
- struct pci_bus *bus;
- struct pci_dev *dev;
- int idx;
- struct resource *r, *pr;
-
- /* Depth-First Search on bus tree */
- for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
- bus = pci_bus_b(ln);
- if ((dev = bus->self)) {
- for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
- r = &dev->resource[idx];
- if (!r->start)
- continue;
- pr = pci_find_parent_resource(dev, r);
- if (!pr || request_resource(pr, r) < 0)
- printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
- }
- }
- pcibios_allocate_bus_resources(&bus->children);
- }
-}
-
-static void __init pcibios_allocate_resources(int pass)
-{
- struct pci_dev *dev = NULL;
- int idx, disabled;
- u16 command;
- struct resource *r, *pr;
-
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- pci_read_config_word(dev, PCI_COMMAND, &command);
- for(idx = 0; idx < 6; idx++) {
- r = &dev->resource[idx];
- if (r->parent) /* Already allocated */
- continue;
- if (!r->start) /* Address not assigned at all */
- continue;
- if (r->flags & IORESOURCE_IO)
- disabled = !(command & PCI_COMMAND_IO);
- else
- disabled = !(command & PCI_COMMAND_MEMORY);
- if (pass == disabled) {
- DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n",
- r->start, r->end, r->flags, disabled, pass);
- pr = pci_find_parent_resource(dev, r);
- if (!pr || request_resource(pr, r) < 0) {
- printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, dev->slot_name);
- /* We'll assign a new address later */
- r->end -= r->start;
- r->start = 0;
- }
- }
- }
- if (!pass) {
- r = &dev->resource[PCI_ROM_RESOURCE];
- if (r->flags & PCI_ROM_ADDRESS_ENABLE) {
- /* Turn the ROM off, leave the resource region, but keep it unregistered. */
- u32 reg;
- DBG("PCI: Switching off ROM of %s\n", dev->slot_name);
- r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_read_config_dword(dev, dev->rom_base_reg, ®);
- pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
- }
- }
- }
-}
-
-static void __init pcibios_assign_resources(void)
-{
- struct pci_dev *dev = NULL;
- int idx;
- struct resource *r;
-
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- int class = dev->class >> 8;
-
- /* Don't touch classless devices and host bridges */
- if (!class || class == PCI_CLASS_BRIDGE_HOST)
- continue;
-
- for(idx=0; idx<6; idx++) {
- r = &dev->resource[idx];
-
- /*
- * Don't touch IDE controllers and I/O ports of video cards!
- */
- if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
- (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
- continue;
-
- /*
- * We shall assign a new address to this resource, either because
- * the BIOS forgot to do so or because we have decided the old
- * address was unusable for some reason.
- */
- if (!r->start && r->end)
- pci_assign_resource(dev, idx);
- }
-
- if (pci_probe & PCI_ASSIGN_ROMS) {
- r = &dev->resource[PCI_ROM_RESOURCE];
- r->end -= r->start;
- r->start = 0;
- if (r->end)
- pci_assign_resource(dev, PCI_ROM_RESOURCE);
- }
- }
-}
-
-void __init pcibios_resource_survey(void)
-{
- DBG("PCI: Allocating resources\n");
- pcibios_allocate_bus_resources(&pci_root_buses);
- pcibios_allocate_resources(0);
- pcibios_allocate_resources(1);
- pcibios_assign_resources();
-}
-
-int pcibios_enable_resources(struct pci_dev *dev, int mask)
-{
- u16 cmd, old_cmd;
- int idx;
- struct resource *r;
-
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- old_cmd = cmd;
- for(idx=0; idx<6; idx++) {
- if (!(mask & (1<<idx)))
- continue;
-
- r = &dev->resource[idx];
- if (!r->start && r->end) {
- printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
- return -EINVAL;
- }
- if (r->flags & IORESOURCE_IO)
- cmd |= PCI_COMMAND_IO;
- if (r->flags & IORESOURCE_MEM)
- cmd |= PCI_COMMAND_MEMORY;
- }
- if (dev->resource[PCI_ROM_RESOURCE].start)
- cmd |= PCI_COMMAND_MEMORY;
- if (cmd != old_cmd) {
- printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
- return 0;
-}
-
-/*
- * If we set up a device for bus mastering, we need to check the latency
- * timer as certain crappy BIOSes forget to set it properly.
- */
-unsigned int pcibios_max_latency = 255;
-
-void pcibios_set_master(struct pci_dev *dev)
-{
- u8 lat;
- pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
- if (lat < 16)
- lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
- else if (lat > pcibios_max_latency)
- lat = pcibios_max_latency;
- else
- return;
- printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
-}
-
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state, int write_combine)
-{
- unsigned long prot;
-
- /* I/O space cannot be accessed via normal processor loads and
- * stores on this platform.
- */
- if (mmap_state == pci_mmap_io)
- return -EINVAL;
-
- /* Leave vm_pgoff as-is, the PCI space address is the physical
- * address on this platform.
- */
- vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
-
- prot = pgprot_val(vma->vm_page_prot);
- if (boot_cpu_data.x86 > 3)
- prot |= _PAGE_PCD | _PAGE_PWT;
- vma->vm_page_prot = __pgprot(prot);
-
- /* Write-combine setting is ignored, it is changed via the mtrr
- * interfaces on this platform.
- */
- if (remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-
- return 0;
-}
#include <asm/apicdef.h>
#include <asm/page.h>
#include <asm/vsyscall.h>
+#include <asm/vsyscall32.h>
/*
* Here we define all the compile-time 'special' virtual
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
+/* Only covers 32bit vsyscalls currently. Need another set for 64bit. */
+#define FIXADDR_USER_START ((unsigned long)VSYSCALL32_VSYSCALL)
+#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE)
+
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
extern void __this_fixmap_does_not_exist(void);
#define IO_SPACE_LIMIT 0xffff
-#ifdef __KERNEL__
+#if defined(__KERNEL__) && __x86_64__
#include <linux/vmalloc.h>
extern struct pglist_data *node_data[];
-/* kern_addr_valid below hardcodes the same algorithm*/
static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
{
int nid;
#define local_mapnr(kvaddr) \
( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) )
-#define kern_addr_valid(kvaddr) ({ \
- int ok = 0; \
- unsigned long index = __pa(kvaddr) >> memnode_shift; \
- if (index <= NODEMAPSIZE) { \
- unsigned nodeid = memnodemap[index]; \
- unsigned long pfn = __pa(kvaddr) >> PAGE_SHIFT; \
- unsigned long start_pfn = node_start_pfn(nodeid); \
- ok = (nodeid != 0xff) && \
- (pfn >= start_pfn) && \
- (pfn < start_pfn + node_size(nodeid)); \
- } \
- ok; \
-})
/* AK: this currently doesn't deal with invalid addresses. We'll see
if the 2.5 kernel doesn't pass them
#define __PAGE_OFFSET 0x0000010000000000 /* 1 << 40 */
#define __PHYSICAL_MASK_SHIFT 40
#define __PHYSICAL_MASK ((1UL << __PHYSICAL_MASK_SHIFT) - 1)
+#define __VIRTUAL_MASK_SHIFT 48
+#define __VIRTUAL_MASK ((1UL << __VIRTUAL_MASK_SHIFT) - 1)
#define KERNEL_TEXT_SIZE (40UL*1024*1024)
#define KERNEL_TEXT_START 0xffffffff80000000UL
struct pci_dev;
extern int iommu_setup(char *opt);
-extern void pci_iommu_init(void);
/* Allocate and map kernel buffer using consistent mode DMA for a device.
* hwdev should be valid struct pci_dev pointer for PCI devices,
#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0)
#define pmd_bad(x) ((pmd_val(x) & (~PTE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE )
#define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot)))
-
+#define pmd_pfn(x) ((pmd_val(x) >> PAGE_SHIFT) & __PHYSICAL_MASK)
#define pte_to_pgoff(pte) ((pte_val(pte) & PHYSICAL_PAGE_MASK) >> PAGE_SHIFT)
#define pgoff_to_pte(off) ((pte_t) { ((off) << PAGE_SHIFT) | _PAGE_FILE })
#endif /* !__ASSEMBLY__ */
-#ifndef CONFIG_DISCONTIGMEM
-#define kern_addr_valid(addr) (1)
-#endif
+extern int kern_addr_valid(unsigned long addr);
#define io_remap_page_range remap_page_range
#define pgtable_cache_init() do { } while (0)
#define check_pgt_cache() do { } while (0)
+/* fs/proc/kcore.c */
+#define kc_vaddr_to_offset(v) ((v) & __VIRTUAL_MASK)
+#define kc_offset_to_vaddr(o) \
+ (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
+
#endif /* _X86_64_PGTABLE_H */
extern void init_memory_mapping(void);
extern void system_call(void);
+extern int kernel_syscall(void);
+extern void syscall_init(void);
+
+extern void ia32_syscall(void);
extern void ia32_cstar_target(void);
+
extern void calibrate_delay(void);
extern void cpu_idle(void);
extern void sys_ni_syscall(void);
extern void ia32_syscall(void);
extern void iommu_hole_init(void);
+extern void time_init_smp(void);
+
extern void do_softirq_thunk(void);
extern int numa_setup(char *opt);
extern void reserve_bootmem_generic(unsigned long phys, unsigned len);
extern void free_bootmem_generic(unsigned long phys, unsigned len);
+extern void load_gs_index(unsigned gs);
+
extern unsigned long end_pfn_map;
+extern unsigned long cpu_initialized;
+
extern void show_stack(unsigned long * rsp);
extern void show_trace(unsigned long * rsp);
extern void show_registers(struct pt_regs *regs);
extern unsigned long end_pfn;
extern unsigned long table_start, table_end;
-extern void syscall_init(void);
+extern int exception_trace;
+extern int no_iommu, force_mmu;
+extern int using_apic_timer;
+extern int disable_apic;
+extern unsigned cpu_khz;
-struct pt_regs;
+extern int fallback_aper_order;
+extern int fallback_aper_force;
+
+extern void smp_local_timer_interrupt(struct pt_regs * regs);
long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);