Commit 3dccf5d0 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] x86-64 update

From: Andi Kleen <ak@muc.de>

Current x86-64 patchkit for 2.6.5.

- Add drivers/firmware/Kconfig

- Clarify description of CONFIG_IOMMU_DEBUG

- Use correct gcc option to optimize for Intel CPUs

- Add EDD support (Matt Domsch)

- Add workaround for broken IOMMU on VIA hardware.  Uses swiotlb there now.

- Handle more than 8 local APICs (Suresh B Siddha) 

- Delete obsolete mtrr Makefile

- Add x86_cache_alignment and set it up properly for P4 (128 bytes instead
  of 64bytes).  Also report in /proc/cpuinfo

- Minor cleanup in in_gate_area

- Make asm-generic/dma-mapping.h compile with !CONFIG_PCI Just stub out all
  functions in this case.  This is mainly to work around sysfs.

- More !CONFIG_PCI compile fixes

- Make u64 sector_t unconditional
parent b5c7a2dd
......@@ -401,6 +401,8 @@ endmenu
source drivers/Kconfig
source "drivers/firmware/Kconfig"
source fs/Kconfig
source "arch/x86_64/oprofile/Kconfig"
......@@ -480,11 +482,18 @@ config FRAME_POINTER
config IOMMU_DEBUG
depends on GART_IOMMU && DEBUG_KERNEL
bool "Force IOMMU to on"
bool "Enable IOMMU debugging"
help
Force the IOMMU to on even when you have less than 4GB of memory and add
debugging code.
Can be disabled at boot time with iommu=noforce.
Force the IOMMU to on even when you have less than 4GB of
memory and add debugging code. On overflow always panic. And
allow to enable IOMMU leak tracing. Can be disabled at boot
time with iommu=noforce. This will also enable scatter gather
list merging. Currently not recommended for production
code. When you use it make sure you have a big enough
IOMMU/AGP aperture. Most of the options enabled by this can
be set more finegrained using the iommu= command line
options. See Documentation/x86_64/boot-options.txt for more
details.
config IOMMU_LEAK
bool "IOMMU leak tracing"
......
......@@ -38,7 +38,7 @@ OBJCOPYFLAGS := -O binary -R .note -R .comment -S
LDFLAGS_vmlinux := -e stext
cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,)
cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=prescott,)
cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=nocona,)
CFLAGS += $(cflags-y)
CFLAGS += -mno-red-zone
......
......@@ -533,6 +533,8 @@ is_disk1:
movw $0xAA, (0x1ff) # device present
no_psmouse:
#include "../../i386/boot/edd.S"
# Now we want to move to protected mode ...
cmpw $0, %cs:realmode_swtch
jz rmodeswtch_normal
......
......@@ -25,6 +25,8 @@
#include <asm/pci-direct.h>
int iommu_aperture;
int iommu_aperture_disabled __initdata = 0;
int iommu_aperture_allowed __initdata = 0;
int fallback_aper_order __initdata = 1; /* 64MB */
int fallback_aper_force __initdata = 0;
......@@ -200,6 +202,9 @@ void __init iommu_hole_init(void)
u64 aper_base;
int valid_agp = 0;
if (iommu_aperture_disabled)
return;
printk("Checking aperture...\n");
fix = 0;
......
......@@ -34,6 +34,7 @@
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/desc.h>
#include <asm/proto.h>
int sis_apic_bug; /* not actually supported, dummy for compile */
......@@ -211,7 +212,6 @@ static int __init enable_ioapic_setup(char *str)
__setup("noapic", disable_ioapic_setup);
__setup("apic", enable_ioapic_setup);
#ifndef CONFIG_SMP
#include <asm/pci-direct.h>
#include <linux/pci_ids.h>
#include <linux/pci.h>
......@@ -220,7 +220,11 @@ __setup("apic", enable_ioapic_setup);
off. Check for an Nvidia or VIA PCI bridge and turn it off.
Use pci direct infrastructure because this runs before the PCI subsystem.
Can be overwritten with "apic" */
Can be overwritten with "apic"
And another hack to disable the IOMMU on VIA chipsets.
Kludge-O-Rama. */
void __init check_ioapic(void)
{
int num,slot,func;
......@@ -245,12 +249,21 @@ void __init check_ioapic(void)
PCI_VENDOR_ID);
vendor &= 0xffff;
switch (vendor) {
case PCI_VENDOR_ID_NVIDIA:
case PCI_VENDOR_ID_VIA:
if (end_pfn >= (0xffffffff>>PAGE_SHIFT) &&
!iommu_aperture_allowed) {
printk(KERN_INFO
"Looks like a VIA chipset. Disabling IOMMU. Overwrite with \"iommu=allowed\"\n");
iommu_aperture_disabled = 1;
}
/* FALL THROUGH */
case PCI_VENDOR_ID_NVIDIA:
#ifndef CONFIG_SMP
printk(KERN_INFO
"PCI bridge %02x:%02x from %x found. Setting \"noapic\". Overwrite with \"apic\"\n",
num,slot,vendor);
skip_ioapic_setup = 1;
#endif
return;
}
......@@ -263,7 +276,6 @@ void __init check_ioapic(void)
}
}
}
#endif
static int __init ioapic_pirq_setup(char *str)
{
......@@ -1785,7 +1797,7 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id)
* advantage of new APIC bus architecture.
*/
if (!physids_empty(apic_id_map))
if (physids_empty(apic_id_map))
apic_id_map = phys_cpu_present_map;
spin_lock_irqsave(&ioapic_lock, flags);
......
......@@ -83,6 +83,9 @@ extern int acpi_parse_ioapic (acpi_table_entry_header *header);
#endif /*CONFIG_X86_IO_APIC*/
#endif /*CONFIG_ACPI_BOOT*/
u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
/*
* Intel MP BIOS table parsing routines:
*/
......@@ -147,6 +150,7 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
ver = 0x10;
}
apic_version[m->mpc_apicid] = ver;
bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
}
static void __init MP_bus_info (struct mpc_config_bus *m)
......
#
# Reuse the i386 MTRR driver.
#
obj-y := main.o if.o generic.o state.o
obj-y += amd.o
obj-y += cyrix.o
obj-y += centaur.o
$(obj)/main.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/main.c $(obj)/main.c
$(obj)/if.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/if.c $(obj)/if.c
$(obj)/generic.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/generic.c $(obj)/generic.c
$(obj)/state.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/state.c $(obj)/state.c
$(obj)/amd.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/amd.c $(obj)/amd.c
$(obj)/cyrix.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/cyrix.c $(obj)/cyrix.c
$(obj)/centaur.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/centaur.c $(obj)/centaur.c
$(obj)/mtrr.h:
@ln -sf ../../../i386/kernel/cpu/mtrr/mtrr.h $(obj)/mtrr.h
clean-files += main.c if.c generic.c state.c amd.c cyrix.c centaur.c mtrr.h
......@@ -194,6 +194,7 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
/* Kludge to make it bug-to-bug compatible with i386. i386
uses the normal dma_mask for alloc_consistent. */
if (hwdev)
dma_mask &= hwdev->dma_mask;
again:
......@@ -849,6 +850,7 @@ fs_initcall(pci_iommu_init);
forcesac For SAC mode for masks <40bits (experimental)
fullflush Flush IOMMU on each allocation (default)
nofullflush Don't use IOMMU fullflush
allowed overwrite iommu off workarounds for specific chipsets.
soft Use software bounce buffering (default for Intel machines)
*/
__init int iommu_setup(char *opt)
......@@ -861,8 +863,12 @@ __init int iommu_setup(char *opt)
no_agp = 1;
if (!memcmp(p,"off", 3))
no_iommu = 1;
if (!memcmp(p,"force", 5))
if (!memcmp(p,"force", 5)) {
force_iommu = 1;
iommu_aperture_allowed = 1;
}
if (!memcmp(p,"allowed",7))
iommu_aperture_allowed = 1;
if (!memcmp(p,"noforce", 7)) {
iommu_merge = 0;
force_iommu = 0;
......
......@@ -39,6 +39,7 @@
#include <linux/pci.h>
#include <linux/acpi.h>
#include <linux/kallsyms.h>
#include <linux/edd.h>
#include <asm/mtrr.h>
#include <asm/uaccess.h>
#include <asm/system.h>
......@@ -369,6 +370,30 @@ static int __init noreplacement_setup(char *s)
__setup("noreplacement", noreplacement_setup);
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
unsigned char eddnr;
struct edd_info edd[EDDMAXNR];
unsigned int edd_disk80_sig;
#ifdef CONFIG_EDD_MODULE
EXPORT_SYMBOL(eddnr);
EXPORT_SYMBOL(edd);
EXPORT_SYMBOL(edd_disk80_sig);
#endif
/**
* copy_edd() - Copy the BIOS EDD information
* from empty_zero_page into a safe place.
*
*/
static inline void copy_edd(void)
{
eddnr = EDD_NR;
memcpy(edd, EDD_BUF, sizeof(edd));
edd_disk80_sig = DISK80_SIGNATURE;
}
#else
#define copy_edd() do {} while (0)
#endif
void __init setup_arch(char **cmdline_p)
{
unsigned long low_mem_size;
......@@ -387,6 +412,7 @@ void __init setup_arch(char **cmdline_p)
rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
#endif
setup_memory_region();
copy_edd();
if (!MOUNT_ROOT_RDONLY)
root_mountflags &= ~MS_RDONLY;
......@@ -475,10 +501,7 @@ void __init setup_arch(char **cmdline_p)
#endif
paging_init();
#ifndef CONFIG_SMP
/* Temporary hack: disable the IO-APIC for UP Nvidia and VIA. */
check_ioapic();
#endif
#ifdef CONFIG_ACPI_BOOT
/*
* Initialize the ACPI boot-time table parser (gets the RSDP and SDT).
......@@ -797,6 +820,9 @@ static void __init init_intel(struct cpuinfo_x86 *c)
c->x86_virt_bits = (eax >> 8) & 0xff;
c->x86_phys_bits = eax & 0xff;
}
if (c->x86 == 15)
c->x86_cache_alignment = c->x86_clflush_size * 2;
}
void __init get_cpu_vendor(struct cpuinfo_x86 *c)
......@@ -831,6 +857,7 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
c->x86_vendor_id[0] = '\0'; /* Unset */
c->x86_model_id[0] = '\0'; /* Unset */
c->x86_clflush_size = 64;
c->x86_cache_alignment = c->x86_clflush_size;
memset(&c->x86_capability, 0, sizeof c->x86_capability);
/* Get vendor name */
......@@ -1058,6 +1085,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if (c->x86_tlbsize > 0)
seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
seq_printf(m, "clflush size\t: %d\n", c->x86_clflush_size);
seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
c->x86_phys_bits, c->x86_virt_bits);
......
......@@ -60,8 +60,6 @@ char phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
/* Bitmask of currently online CPUs */
cpumask_t cpu_online_map;
/* which CPU (physical APIC ID) maps to which logical CPU number */
volatile char x86_apicid_to_cpu[NR_CPUS];
/* which logical CPU number maps to which CPU (physical APIC ID) */
volatile char x86_cpu_to_apicid[NR_CPUS];
......@@ -580,8 +578,6 @@ static void __init do_boot_cpu (int apicid)
panic("failed fork for CPU %d", cpu);
wake_up_forked_process(idle);
x86_cpu_to_apicid[cpu] = apicid;
x86_apicid_to_cpu[apicid] = cpu;
/*
* We remove it from the pidhash and the runqueue
......@@ -735,7 +731,7 @@ static void smp_tune_scheduling (void)
static void __init smp_boot_cpus(unsigned int max_cpus)
{
unsigned apicid, cpu;
unsigned apicid, cpu, bit, kicked;
nmi_watchdog_default();
......@@ -820,11 +816,13 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
*/
Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map));
for (apicid = 0; apicid < NR_CPUS; apicid++) {
kicked = 1;
for (bit = 0; kicked < NR_CPUS && bit < MAX_APICS; bit++) {
apicid = cpu_present_to_apicid(bit);
/*
* Don't even attempt to start the boot CPU!
*/
if (apicid == boot_cpu_id)
if (apicid == boot_cpu_id || (apicid == BAD_APICID))
continue;
if (!cpu_isset(apicid, phys_cpu_present_map))
......@@ -833,6 +831,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
continue;
do_boot_cpu(apicid);
++kicked;
}
/*
......
......@@ -98,8 +98,10 @@ EXPORT_SYMBOL(copy_to_user);
EXPORT_SYMBOL(copy_in_user);
EXPORT_SYMBOL(strnlen_user);
#ifdef CONFIG_PCI
EXPORT_SYMBOL(pci_alloc_consistent);
EXPORT_SYMBOL(pci_free_consistent);
#endif
#ifdef CONFIG_PCI
EXPORT_SYMBOL(pcibios_penalize_isa_irq);
......
......@@ -603,8 +603,6 @@ struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
int in_gate_area(struct task_struct *task, unsigned long addr)
{
struct vm_area_struct *vma = &gate_vma;
if (test_tsk_thread_flag(task, TIF_IA32))
vma = &gate32_vma;
struct vm_area_struct *vma = get_gate_vma(task);
return (addr >= vma->vm_start) && (addr < vma->vm_end);
}
......@@ -7,6 +7,10 @@
#ifndef _ASM_GENERIC_DMA_MAPPING_H
#define _ASM_GENERIC_DMA_MAPPING_H
#include <linux/config.h>
#ifdef CONFIG_PCI
/* we implement the API below in terms of the existing PCI one,
* so include it */
#include <linux/pci.h>
......@@ -146,6 +150,119 @@ dma_mapping_error(dma_addr_t dma_addr)
return pci_dma_mapping_error(dma_addr);
}
#else
static inline int
dma_supported(struct device *dev, u64 mask)
{
return 0;
}
static inline int
dma_set_mask(struct device *dev, u64 dma_mask)
{
BUG();
return 0;
}
static inline void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
int flag)
{
BUG();
return NULL;
}
static inline void
dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_handle)
{
BUG();
}
static inline dma_addr_t
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction direction)
{
BUG();
return 0;
}
static inline void
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction direction)
{
BUG();
}
static inline dma_addr_t
dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction)
{
BUG();
return 0;
}
static inline void
dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
enum dma_data_direction direction)
{
BUG();
}
static inline int
dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction direction)
{
BUG();
return 0;
}
static inline void
dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
enum dma_data_direction direction)
{
BUG();
}
static inline void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
BUG();
}
static inline void
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
BUG();
}
static inline void
dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
enum dma_data_direction direction)
{
BUG();
}
static inline void
dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
enum dma_data_direction direction)
{
BUG();
}
static inline int
dma_error(dma_addr_t dma_addr)
{
return 0;
}
#endif
/* Now for the API extensions over the pci_ one */
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
......
......@@ -370,4 +370,6 @@ struct local_apic {
#undef u32
#define BAD_APICID 0xFFu
#endif
......@@ -26,6 +26,9 @@ extern char x86_boot_params[2048];
#define INITRD_START (*(unsigned int *) (PARAM+0x218))
#define INITRD_SIZE (*(unsigned int *) (PARAM+0x21c))
#define EDID_INFO (*(struct edid_info *) (PARAM+0x440))
#define DISK80_SIGNATURE (*(unsigned int*) (PARAM+DISK80_SIG_BUFFER))
#define EDD_NR (*(unsigned char *) (PARAM+EDDNR))
#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF))
#define COMMAND_LINE saved_command_line
#define COMMAND_LINE_SIZE 256
......
......@@ -357,8 +357,9 @@ static inline void pcibios_add_platform_entries(struct pci_dev *dev)
#endif /* __KERNEL__ */
/* generic pci stuff */
#ifdef CONFIG_PCI
#include <asm-generic/pci.h>
#include <linux/dma-mapping.h>
#endif
#endif /* __x8664_PCI_H */
......@@ -59,6 +59,7 @@ struct cpuinfo_x86 {
char x86_model_id[64];
int x86_cache_size; /* in KB */
int x86_clflush_size;
int x86_cache_alignment;
int x86_tlbsize; /* number of 4K pages in DTLB/ITLB combined(in pages)*/
__u8 x86_virt_bits, x86_phys_bits;
__u32 x86_power;
......@@ -453,6 +454,6 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
ti->task; \
})
#define cache_line_size() (boot_cpu_data.x86_clflush_size)
#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
#endif /* __ASM_X86_64_PROCESSOR_H */
......@@ -101,6 +101,8 @@ extern int acpi_disabled;
extern int fallback_aper_order;
extern int fallback_aper_force;
extern int iommu_aperture;
extern int iommu_aperture_disabled;
extern int iommu_aperture_allowed;
extern void smp_local_timer_interrupt(struct pt_regs * regs);
......
......@@ -80,10 +80,30 @@ extern __inline int hard_smp_processor_id(void)
* the real APIC ID <-> CPU # mapping.
* AK: why is this volatile?
*/
extern volatile char x86_apicid_to_cpu[NR_CPUS];
extern volatile char x86_cpu_to_apicid[NR_CPUS];
#define safe_smp_processor_id() (disable_apic ? 0 : x86_apicid_to_cpu[hard_smp_processor_id()])
static inline char x86_apicid_to_cpu(char apicid)
{
int i;
for (i = 0; i < NR_CPUS; ++i)
if (x86_cpu_to_apicid[i] == apicid)
return i;
return -1;
}
#define safe_smp_processor_id() (disable_apic ? 0 : x86_apicid_to_cpu(hard_smp_processor_id()))
extern u8 bios_cpu_apicid[];
static inline int cpu_present_to_apicid(int mps_cpu)
{
if (mps_cpu < NR_CPUS)
return (int)bios_cpu_apicid[mps_cpu];
else
return BAD_APICID;
}
#define cpu_online(cpu) cpu_isset(cpu, cpu_online_map)
#endif /* !ASSEMBLY */
......
......@@ -33,8 +33,6 @@ typedef unsigned long long __u64;
#ifndef __ASSEMBLY__
#include <linux/config.h>
typedef signed char s8;
typedef unsigned char u8;
......@@ -50,10 +48,8 @@ typedef unsigned long long u64;
typedef u64 dma64_addr_t;
typedef u64 dma_addr_t;
#ifdef CONFIG_LBD
typedef u64 sector_t;
#define HAVE_SECTOR_T
#endif
#endif /* __ASSEMBLY__ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment