From 51af77dbb806a3df044de15301d51488202bdfce Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 13 Apr 2004 06:18:37 -0700 Subject: [PATCH] [PATCH] x86-64 update Various fixes and cleanups for x86-64. - Update defconfig - Fix some problems in ROM resource scanning (Rene Herman) - Initialize APIC id of CPU 0 (Venkatesh Pallipadi) - Always enable swiotlb for GART_IOMMU - Fix compilation without IOMMU_GART - Remove nodes_present; use standard node_online_map instead. This also fixes a bug with no memory on node 0. - Switch node<->cpu mapping to arrays. This fixes some awkward special cases with no nodes and empty nodes. - Move K8 fallback node setup to common code - Eliminate old fake_node. - Fix wrong fields in MCE handling (Marc Bevand) - Make pci_dma_consistent behave more similar to i386 to fix Alsa --- arch/x86_64/Kconfig | 6 +- arch/x86_64/defconfig | 17 +++- arch/x86_64/kernel/io_apic.c | 2 + arch/x86_64/kernel/mce.c | 4 +- arch/x86_64/kernel/pci-gart.c | 3 - arch/x86_64/kernel/setup.c | 154 ++++++++++++++++++------------- arch/x86_64/kernel/setup64.c | 5 + arch/x86_64/kernel/smpboot.c | 2 + arch/x86_64/kernel/x8664_ksyms.c | 7 -- arch/x86_64/mm/k8topology.c | 26 +----- arch/x86_64/mm/numa.c | 52 +++++++++-- include/asm-x86_64/numa.h | 7 +- include/asm-x86_64/proto.h | 2 +- include/asm-x86_64/topology.h | 15 +-- 14 files changed, 179 insertions(+), 123 deletions(-) diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index db1a88d6e46d3..26c6908d9cd99 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -290,9 +290,11 @@ config GART_IOMMU Normally the kernel will take the right choice by itself. If unsure say Y +# need this always enabled with GART_IOMMU for the VIA workaround config SWIOTLB - select GART_IOMMU - bool "Software IOTLB support" + bool + depends on GART_IOMMU + default y config DUMMY_IOMMU bool diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index c4e3ccd82d1bd..60eca82950cfa 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -24,8 +24,10 @@ CONFIG_STANDALONE=y # CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=18 # CONFIG_HOTPLUG is not set CONFIG_IKCONFIG=y @@ -37,6 +39,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # @@ -83,7 +86,6 @@ CONFIG_X86_MCE=y # CONFIG_PM=y CONFIG_SOFTWARE_SUSPEND=y -# CONFIG_PM_DISK is not set # # ACPI (Advanced Configuration and Power Interface) Support @@ -107,7 +109,6 @@ CONFIG_ACPI_EC=y CONFIG_ACPI_POWER=y CONFIG_ACPI_PCI=y CONFIG_ACPI_SYSTEM=y -# CONFIG_X86_PM_TIMER is not set # # CPU Frequency scaling @@ -281,6 +282,8 @@ CONFIG_SCSI_SATA=y # CONFIG_SCSI_SATA_SVW is not set CONFIG_SCSI_ATA_PIIX=y # CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_SIL is not set +# CONFIG_SCSI_SATA_SIS is not set CONFIG_SCSI_SATA_VIA=y # CONFIG_SCSI_SATA_VITESSE is not set # CONFIG_SCSI_BUSLOGIC is not set @@ -350,7 +353,6 @@ CONFIG_IP_MULTICAST=y # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set @@ -368,7 +370,6 @@ CONFIG_IPV6=y # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set @@ -605,7 +606,7 @@ CONFIG_RTC=y # CONFIG_AGP=y CONFIG_AGP_AMD64=y -CONFIG_AGP_INTEL=y +# CONFIG_AGP_INTEL_MCH is not set # CONFIG_DRM is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y @@ -691,6 +692,11 @@ CONFIG_SOUND_ICH=y # # CONFIG_USB_GADGET is not set +# +# Firmware Drivers +# +# CONFIG_EDD is not set + # # File systems # @@ -736,6 +742,7 @@ CONFIG_ISO9660_FS=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 8c989a37460c0..8254a0b6f948e 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -250,12 +250,14 @@ void __init check_ioapic(void) vendor &= 0xffff; switch (vendor) { case PCI_VENDOR_ID_VIA: +#ifdef CONFIG_GART_IOMMU 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; } +#endif /* FALL THROUGH */ case PCI_VENDOR_ID_NVIDIA: #ifndef CONFIG_SMP diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index f0537a97f5caf..8dfd18ca3741d 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c @@ -85,7 +85,7 @@ static void print_mce(struct mce *m) if (m->addr) printk("ADDR %Lx ", m->addr); if (m->misc) - printk("MISC %Lx ", m->addr); + printk("MISC %Lx ", m->misc); printk("\n"); } @@ -160,7 +160,7 @@ void do_machine_check(struct pt_regs * regs, long error_code) if (m.status & MCI_STATUS_MISCV) rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc); if (m.status & MCI_STATUS_ADDRV) - rdmsrl(MSR_IA32_MC0_MISC + i*4, m.addr); + rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr); rdtscll(m.tsc); wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0); diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 6c4590e2e7724..292b675293e5d 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -607,9 +607,6 @@ int pci_dma_supported(struct pci_dev *dev, u64 mask) return 0; } - if (no_iommu && (mask < (end_pfn << PAGE_SHIFT)) && !swiotlb) - return 0; - return 1; } diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 257c6ccd2aaee..84d49ebe571ff 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -103,91 +103,115 @@ char command_line[COMMAND_LINE_SIZE]; char saved_command_line[COMMAND_LINE_SIZE]; struct resource standard_io_resources[] = { - { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, - { "pic1", 0x20, 0x21, IORESOURCE_BUSY }, - { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, - { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY }, - { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, - { "pic2", 0xa0, 0xa1, IORESOURCE_BUSY }, - { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, - { "fpu", 0xf0, 0xff, IORESOURCE_BUSY } + { "dma1", 0x00, 0x1f, IORESOURCE_BUSY | IORESOURCE_IO }, + { "pic1", 0x20, 0x21, IORESOURCE_BUSY | IORESOURCE_IO }, + { "timer", 0x40, 0x5f, IORESOURCE_BUSY | IORESOURCE_IO }, + { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY | IORESOURCE_IO }, + { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY | IORESOURCE_IO }, + { "pic2", 0xa0, 0xa1, IORESOURCE_BUSY | IORESOURCE_IO }, + { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY | IORESOURCE_IO }, + { "fpu", 0xf0, 0xff, IORESOURCE_BUSY | IORESOURCE_IO } }; -#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource)) +#define STANDARD_IO_RESOURCES \ + (sizeof standard_io_resources / sizeof standard_io_resources[0]) -struct resource code_resource = { "Kernel code", 0x100000, 0 }; -struct resource data_resource = { "Kernel data", 0, 0 }; -struct resource vram_resource = { "Video RAM area", 0xa0000, 0xbffff, IORESOURCE_BUSY }; +struct resource code_resource = { "Kernel code", 0x100000, 0, IORESOURCE_MEM }; +struct resource data_resource = { "Kernel data", 0, 0, IORESOURCE_MEM }; +struct resource vram_resource = { "Video RAM area", 0xa0000, 0xbffff, IORESOURCE_BUSY | IORESOURCE_MEM }; -/* System ROM resources */ -#define MAXROMS 6 -static struct resource rom_resources[MAXROMS] = { - { "System ROM", 0xF0000, 0xFFFFF, IORESOURCE_BUSY }, - { "Video ROM", 0xc0000, 0xc7fff, IORESOURCE_BUSY } +#define IORESOURCE_ROM (IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM) + +static struct resource system_rom_resource = { "System ROM", 0xf0000, 0xfffff, IORESOURCE_ROM }; +static struct resource extension_rom_resource = { "Extension ROM", 0xe0000, 0xeffff, IORESOURCE_ROM }; + +static struct resource adapter_rom_resources[] = { + { "Adapter ROM", 0xc8000, 0, IORESOURCE_ROM }, + { "Adapter ROM", 0, 0, IORESOURCE_ROM }, + { "Adapter ROM", 0, 0, IORESOURCE_ROM }, + { "Adapter ROM", 0, 0, IORESOURCE_ROM }, + { "Adapter ROM", 0, 0, IORESOURCE_ROM }, + { "Adapter ROM", 0, 0, IORESOURCE_ROM } }; +#define ADAPTER_ROM_RESOURCES \ + (sizeof adapter_rom_resources / sizeof adapter_rom_resources[0]) + +static struct resource video_rom_resource = { "Video ROM", 0xc0000, 0xc7fff, IORESOURCE_ROM }; + #define romsignature(x) (*(unsigned short *)(x) == 0xaa55) -static void __init probe_roms(void) +static int __init checksum(unsigned char *rom, unsigned long length) { - int roms = 1; - unsigned long base; - unsigned char *romstart; + unsigned char *p, sum = 0; - request_resource(&iomem_resource, rom_resources+0); + for (p = rom; p < rom + length; p++) + sum += *p; + return sum == 0; +} - /* Video ROM is standard at C000:0000 - C7FF:0000, check signature */ - for (base = 0xC0000; base < 0xE0000; base += 2048) { - romstart = isa_bus_to_virt(base); - if (!romsignature(romstart)) +static void __init probe_roms(void) +{ + unsigned long start, length, upper; + unsigned char *rom; + int i; + + /* video rom */ + upper = adapter_rom_resources[0].start; + for (start = video_rom_resource.start; start < upper; start += 2048) { + rom = isa_bus_to_virt(start); + if (!romsignature(rom)) continue; - request_resource(&iomem_resource, rom_resources + roms); - roms++; - break; - } - /* Extension roms at C800:0000 - DFFF:0000 */ - for (base = 0xC8000; base < 0xE0000; base += 2048) { - unsigned long length; + video_rom_resource.start = start; - romstart = isa_bus_to_virt(base); - if (!romsignature(romstart)) - continue; - length = romstart[2] * 512; - if (length) { - unsigned int i; - unsigned char chksum; - - chksum = 0; - for (i = 0; i < length; i++) - chksum += romstart[i]; - - /* Good checksum? */ - if (!chksum) { - rom_resources[roms].start = base; - rom_resources[roms].end = base + length - 1; - rom_resources[roms].name = "Extension ROM"; - rom_resources[roms].flags = IORESOURCE_BUSY; - - request_resource(&iomem_resource, rom_resources + roms); - roms++; - if (roms >= MAXROMS) - return; + /* 0 < length <= 0x7f * 512, historically */ + length = rom[2] * 512; + + /* if checksum okay, trust length byte */ + if (length && checksum(rom, length)) + video_rom_resource.end = start + length - 1; + + request_resource(&iomem_resource, &video_rom_resource); + break; } + + start = (video_rom_resource.end + 1 + 2047) & ~2047UL; + if (start < upper) + start = upper; + + /* system rom */ + request_resource(&iomem_resource, &system_rom_resource); + upper = system_rom_resource.start; + + /* check for extension rom (ignore length byte!) */ + rom = isa_bus_to_virt(extension_rom_resource.start); + if (romsignature(rom)) { + length = extension_rom_resource.end - extension_rom_resource.start + 1; + if (checksum(rom, length)) { + request_resource(&iomem_resource, &extension_rom_resource); + upper = extension_rom_resource.start; } } - /* Final check for motherboard extension rom at E000:0000 */ - base = 0xE0000; - romstart = isa_bus_to_virt(base); + /* check for adapter roms on 2k boundaries */ + for (i = 0; i < ADAPTER_ROM_RESOURCES && start < upper; start += 2048) { + rom = isa_bus_to_virt(start); + if (!romsignature(rom)) + continue; + + /* 0 < length <= 0x7f * 512, historically */ + length = rom[2] * 512; + + /* but accept any length that fits if checksum okay */ + if (!length || start + length > upper || !checksum(rom, length)) + continue; - if (romsignature(romstart)) { - rom_resources[roms].start = base; - rom_resources[roms].end = base + 65535; - rom_resources[roms].name = "Extension ROM"; - rom_resources[roms].flags = IORESOURCE_BUSY; + adapter_rom_resources[i].start = start; + adapter_rom_resources[i].end = start + length - 1; + request_resource(&iomem_resource, &adapter_rom_resources[i]); - request_resource(&iomem_resource, rom_resources + roms); + start = adapter_rom_resources[i++].end & ~2047UL; } } diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 7467bf602de0f..dd0d41548b97c 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -24,6 +24,7 @@ #include #include #include +#include char x86_boot_params[2048] __initdata = {0,}; @@ -329,4 +330,8 @@ void __init cpu_init (void) set_debug(0UL, 7); fpu_init(); + +#ifdef CONFIG_NUMA + numa_add_cpu(cpu); +#endif } diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 89d34014ddb03..4d9c47feb69c9 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -811,6 +811,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus) if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_id) BUG(); + x86_cpu_to_apicid[0] = boot_cpu_id; + /* * Now scan the CPU present map and fire up the other CPUs. */ diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index 0efbdc31d999d..3a73b20df3df4 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c @@ -208,13 +208,6 @@ EXPORT_SYMBOL(init_level4_pgt); extern unsigned long __supported_pte_mask; EXPORT_SYMBOL(__supported_pte_mask); -#ifdef CONFIG_DISCONTIGMEM -EXPORT_SYMBOL(memnode_shift); -EXPORT_SYMBOL(memnodemap); -EXPORT_SYMBOL(node_data); -EXPORT_SYMBOL(fake_node); -#endif - EXPORT_SYMBOL(clear_page); #ifdef CONFIG_SMP diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c index 8ee85369f5e48..0ec22c11cca42 100644 --- a/arch/x86_64/mm/k8topology.c +++ b/arch/x86_64/mm/k8topology.c @@ -48,7 +48,6 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) int nodeid, i, nb; int found = 0; u32 reg; - int rr; nb = find_northbridge(); if (nb < 0) @@ -91,7 +90,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) nodeid, (base>>8)&3, (limit>>8) & 3); return -1; } - if ((1UL << nodeid) & nodes_present) { + if (node_online(nodeid)) { printk(KERN_INFO "Node %d already present. Skipping\n", nodeid); continue; @@ -152,28 +151,13 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) printk(KERN_INFO "Using node hash shift of %d\n", memnode_shift); for (i = 0; i < MAXNODE; i++) { - if (nodes[i].start != nodes[i].end) + if (nodes[i].start != nodes[i].end) { + /* assume 1:1 NODE:CPU */ + cpu_to_node[i] = i; setup_node_bootmem(i, nodes[i].start, nodes[i].end); } - - /* There are unfortunately some poorly designed mainboards around - that only connect memory to a single CPU. This breaks the 1:1 cpu->node - mapping. To avoid this fill in the mapping for all possible - CPUs, as the number of CPUs is not known yet. - We round robin the existing nodes. */ - rr = 0; - for (i = 0; i < MAXNODE; i++) { - if (nodes_present & (1UL<> rr) == 0) - rr = 0; - rr = ffz(~nodes_present >> rr); - node_data[i] = node_data[rr]; - rr++; } - if (found == 1) - fake_node = 1; - + numa_init_array(); return 0; } diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 826df2aeda922..e891e9dc3fc4c 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,9 @@ bootmem_data_t plat_node_bdata[MAX_NUMNODES]; int memnode_shift; u8 memnodemap[NODEMAPSIZE]; +unsigned char cpu_to_node[NR_CPUS]; +cpumask_t node_to_cpumask[MAXNODE]; + static int numa_off __initdata; unsigned long nodes_present; @@ -105,7 +109,6 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages< numnodes) numnodes = nodeid + 1; - nodes_present |= (1UL << nodeid); node_set_online(nodeid); } @@ -136,13 +139,36 @@ void __init setup_node_zones(int nodeid) start_pfn, NULL); } -int fake_node; +void __init numa_init_array(void) +{ + int rr, i; + /* There are unfortunately some poorly designed mainboards around + that only connect memory to a single CPU. This breaks the 1:1 cpu->node + mapping. To avoid this fill in the mapping for all possible + CPUs, as the number of CPUs is not known yet. + We round robin the existing nodes. */ + rr = 0; + for (i = 0; i < MAXNODE; i++) { + if (node_online(i)) + continue; + rr = find_next_bit(node_online_map, MAX_NUMNODES, rr); + if (rr == MAX_NUMNODES) + rr = find_first_bit(node_online_map, MAX_NUMNODES); + node_data[i] = node_data[rr]; + cpu_to_node[i] = rr; + rr++; + } + + set_bit(0, &node_to_cpumask[cpu_to_node(0)]); +} -int __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) +void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) { + int i; + #ifdef CONFIG_K8_NUMA if (!numa_off && !k8_scan_nodes(start_pfn< +#include /* Map the K8 CPU local memory controllers to a simple 1:1 CPU:NODE topology */ -extern int fake_node; -/* This is actually a cpumask_t, but doesn't matter because we don't have - >BITS_PER_LONG CPUs */ -extern unsigned long cpu_online_map; +extern cpumask_t cpu_online_map; -#define cpu_to_node(cpu) (fake_node ? 0 : (cpu)) +extern unsigned char cpu_to_node[]; +extern cpumask_t node_to_cpumask[]; + +#define cpu_to_node(cpu) (cpu_to_node[cpu]) #define parent_node(node) (node) -#define node_to_first_cpu(node) (fake_node ? 0 : (node)) -#define node_to_cpumask(node) (fake_node ? cpu_online_map : (1UL << (node))) +#define node_to_first_cpu(node) (__ffs(node_to_cpumask[node])) +#define node_to_cpumask(node) (node_to_cpumask[node]) static inline unsigned long pcibus_to_cpumask(int bus) { -- 2.53.0