From 49a849652513235a244dfbf5e58c54f796bd1148 Mon Sep 17 00:00:00 2001 From: Becky Bruce Date: Fri, 8 May 2009 12:19:27 +0000 Subject: powerpc: Allow mem=x cmdline to work with 4G+ We're currently choking on mem=4g (and above) due to memory_limit being specified as an unsigned long. Make memory_limit phys_addr_t to fix this. Signed-off-by: Becky Bruce Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/machine_kexec.c | 4 ++-- arch/powerpc/kernel/prom.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c index d59e2b1bdcb..bb3d893a835 100644 --- a/arch/powerpc/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec.c @@ -125,8 +125,8 @@ void __init reserve_crashkernel(void) /* Crash kernel trumps memory limit */ if (memory_limit && memory_limit <= crashk_res.end) { memory_limit = crashk_res.end + 1; - printk("Adjusted memory limit for crashkernel, now 0x%lx\n", - memory_limit); + printk("Adjusted memory limit for crashkernel, now 0x%llx\n", + (unsigned long long)memory_limit); } printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 5ec6a9e2393..ce01ff2474d 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -426,7 +426,7 @@ static int __init early_parse_mem(char *p) return 1; memory_limit = PAGE_ALIGN(memparse(p, &p)); - DBG("memory limit = 0x%lx\n", memory_limit); + DBG("memory limit = 0x%llx\n", (unsigned long long)memory_limit); return 0; } @@ -1160,7 +1160,7 @@ static inline void __init phyp_dump_reserve_mem(void) {} void __init early_init_devtree(void *params) { - unsigned long limit; + phys_addr_t limit; DBG(" -> early_init_devtree(%p)\n", params); @@ -1204,7 +1204,7 @@ void __init early_init_devtree(void *params) limit = memory_limit; if (! limit) { - unsigned long memsize; + phys_addr_t memsize; /* Ensure that total memory size is page-aligned, because * otherwise mark_bootmem() gets upset. */ @@ -1218,7 +1218,7 @@ void __init early_init_devtree(void *params) lmb_analyze(); lmb_dump_all(); - DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); + DBG("Phys. mem: %llx\n", lmb_phys_mem_size()); /* We may need to relocate the flat tree, do it now. * FIXME .. and the initrd too? */ -- cgit v1.2.3 From b173f03d7c48d3346541f26e0b29690dbadca279 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 14 May 2009 18:34:06 +0000 Subject: powerpc/pseries: Really fix the oprofile CPU type on pseries My previous pach for fixing the oprofile CPU type got somewhat mismerged (by my fault) when it collided with another related patch. This should finally (fingers crossed) fix the whole thing. We make sure we keep the -old- oprofile type and CPU type whenever one of them was specified in the first pass through the function. Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/cputable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index f9c40f869c6..3e33fb933d9 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1836,7 +1836,7 @@ static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s) * and, in that case, keep the current value for * oprofile_cpu_type. */ - if (old.oprofile_cpu_type == NULL) { + if (old.oprofile_cpu_type != NULL) { t->oprofile_cpu_type = old.oprofile_cpu_type; t->oprofile_type = old.oprofile_type; } -- cgit v1.2.3 From ad892a63f64888a7b05eb2046febbcfbdd54dfcc Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 14 May 2009 20:16:47 +0000 Subject: powerpc: Fix PCI ROM access A couple of issues crept in since about 2.6.27 related to accessing PCI device ROMs on various powerpc machines. First, historically, we don't allocate the ROM resource in the resource tree. I'm not entirely certain of why, I susepct they often contained garbage on x86 but it's hard to tell. This causes the current generic code to always call pci_assign_resource() when trying to access the said ROM from sysfs, which will try to re-assign some new address regardless of what the ROM BAR was already set to at boot time. This can be a problem on hypervisor platforms like pSeries where we aren't supposed to move PCI devices around (and in fact probably can't). Second, our code that generates the PCI tree from the OF device-tree (instead of doing config space probing) which we mostly use on pseries at the moment, didn't set the (new) flag IORESOURCE_SIZEALIGN on any resource. That means that any attempt at re-assigning such a resource with pci_assign_resource() would fail due to resource_alignment() returning 0. This fixes this by doing these two things: - The code that calculates resource flags based on the OF device-node is improved to set IORESOURCE_SIZEALIGN on any valid BAR, and while at it also set IORESOURCE_READONLY for ROMs since we were lacking that too - We now allocate ROM resources as part of the resource tree. However to limit the chances of nasty conflicts due to busted firmwares, we only do it on the second pass of our two-passes allocation scheme, so that all valid and enabled BARs get precedence. This brings pSeries back the ability to access PCI ROMs via sysfs (and thus initialize various video cards from X etc...). Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/pci-common.c | 21 ++++++++++++++------- arch/powerpc/kernel/pci_64.c | 15 ++++++++++++--- 2 files changed, 26 insertions(+), 10 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 9c69e7e145c..4fee63cb53f 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1366,12 +1366,17 @@ static void __init pcibios_allocate_resources(int pass) for_each_pci_dev(dev) { pci_read_config_word(dev, PCI_COMMAND, &command); - for (idx = 0; idx < 6; idx++) { + for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) { r = &dev->resource[idx]; if (r->parent) /* Already allocated */ continue; if (!r->flags || (r->flags & IORESOURCE_UNSET)) continue; /* Not assigned at all */ + /* We only allocate ROMs on pass 1 just in case they + * have been screwed up by firmware + */ + if (idx == PCI_ROM_RESOURCE ) + disabled = 1; if (r->flags & IORESOURCE_IO) disabled = !(command & PCI_COMMAND_IO); else @@ -1382,17 +1387,19 @@ static void __init pcibios_allocate_resources(int pass) if (pass) continue; r = &dev->resource[PCI_ROM_RESOURCE]; - if (r->flags & IORESOURCE_ROM_ENABLE) { + if (r->flags) { /* Turn the ROM off, leave the resource region, * but keep it unregistered. */ u32 reg; - pr_debug("PCI: Switching off ROM of %s\n", - pci_name(dev)); - r->flags &= ~IORESOURCE_ROM_ENABLE; pci_read_config_dword(dev, dev->rom_base_reg, ®); - pci_write_config_dword(dev, dev->rom_base_reg, - reg & ~PCI_ROM_ADDRESS_ENABLE); + if (reg & PCI_ROM_ADDRESS_ENABLE) { + pr_debug("PCI: Switching off ROM of %s\n", + pci_name(dev)); + r->flags &= ~IORESOURCE_ROM_ENABLE; + pci_write_config_dword(dev, dev->rom_base_reg, + reg & ~PCI_ROM_ADDRESS_ENABLE); + } } } } diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index be574fc0d92..96edb6f8bab 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -64,7 +64,7 @@ static u32 get_int_prop(struct device_node *np, const char *name, u32 def) return def; } -static unsigned int pci_parse_of_flags(u32 addr0) +static unsigned int pci_parse_of_flags(u32 addr0, int bridge) { unsigned int flags = 0; @@ -75,8 +75,17 @@ static unsigned int pci_parse_of_flags(u32 addr0) if (addr0 & 0x40000000) flags |= IORESOURCE_PREFETCH | PCI_BASE_ADDRESS_MEM_PREFETCH; + /* Note: We don't know whether the ROM has been left enabled + * by the firmware or not. We mark it as disabled (ie, we do + * not set the IORESOURCE_ROM_ENABLE flag) for now rather than + * do a config space read, it will be force-enabled if needed + */ + if (!bridge && (addr0 & 0xff) == 0x30) + flags |= IORESOURCE_READONLY; } else if (addr0 & 0x01000000) flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; + if (flags) + flags |= IORESOURCE_SIZEALIGN; return flags; } @@ -95,7 +104,7 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) return; pr_debug(" parse addresses (%d bytes) @ %p\n", proplen, addrs); for (; proplen >= 20; proplen -= 20, addrs += 5) { - flags = pci_parse_of_flags(addrs[0]); + flags = pci_parse_of_flags(addrs[0], 0); if (!flags) continue; base = of_read_number(&addrs[1], 2); @@ -293,7 +302,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node, } i = 1; for (; len >= 32; len -= 32, ranges += 8) { - flags = pci_parse_of_flags(ranges[0]); + flags = pci_parse_of_flags(ranges[0], 1); size = of_read_number(&ranges[6], 2); if (flags == 0 || size == 0) continue; -- cgit v1.2.3 From 021376a3b655364c92c10be544a3319946a792e8 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 13 May 2009 20:30:24 +0000 Subject: powerpc/ftrace: Use pr_devel() in ftrace.c pr_debug() can now result in code being generated even when #DEBUG is not defined. That's not really desirable in the ftrace code which we want to be snappy. With CONFIG_DYNAMIC_DEBUG=y: size before: text data bss dec hex filename 3334 672 4 4010 faa arch/powerpc/kernel/ftrace.o size after: text data bss dec hex filename 2616 360 4 2980 ba4 arch/powerpc/kernel/ftrace.o Signed-off-by: Michael Ellerman Acked-by: Steven Rostedt Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/ftrace.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index 70e2a736be1..5b078ee391f 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c @@ -157,7 +157,7 @@ __ftrace_make_nop(struct module *mod, * 0xe8, 0x4c, 0x00, 0x28, ld r2,40(r12) */ - pr_debug("ip:%lx jumps to %lx r2: %lx", ip, tramp, mod->arch.toc); + pr_devel("ip:%lx jumps to %lx r2: %lx", ip, tramp, mod->arch.toc); /* Find where the trampoline jumps to */ if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) { @@ -165,7 +165,7 @@ __ftrace_make_nop(struct module *mod, return -EFAULT; } - pr_debug(" %08x %08x", jmp[0], jmp[1]); + pr_devel(" %08x %08x", jmp[0], jmp[1]); /* verify that this is what we expect it to be */ if (((jmp[0] & 0xffff0000) != 0x3d820000) || @@ -181,18 +181,18 @@ __ftrace_make_nop(struct module *mod, offset = ((unsigned)((unsigned short)jmp[0]) << 16) + (int)((short)jmp[1]); - pr_debug(" %x ", offset); + pr_devel(" %x ", offset); /* get the address this jumps too */ tramp = mod->arch.toc + offset + 32; - pr_debug("toc: %lx", tramp); + pr_devel("toc: %lx", tramp); if (probe_kernel_read(jmp, (void *)tramp, 8)) { printk(KERN_ERR "Failed to read %lx\n", tramp); return -EFAULT; } - pr_debug(" %08x %08x\n", jmp[0], jmp[1]); + pr_devel(" %08x %08x\n", jmp[0], jmp[1]); ptr = ((unsigned long)jmp[0] << 32) + jmp[1]; @@ -269,7 +269,7 @@ __ftrace_make_nop(struct module *mod, * 0x4e, 0x80, 0x04, 0x20 bctr */ - pr_debug("ip:%lx jumps to %lx", ip, tramp); + pr_devel("ip:%lx jumps to %lx", ip, tramp); /* Find where the trampoline jumps to */ if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) { @@ -277,7 +277,7 @@ __ftrace_make_nop(struct module *mod, return -EFAULT; } - pr_debug(" %08x %08x ", jmp[0], jmp[1]); + pr_devel(" %08x %08x ", jmp[0], jmp[1]); /* verify that this is what we expect it to be */ if (((jmp[0] & 0xffff0000) != 0x3d600000) || @@ -293,7 +293,7 @@ __ftrace_make_nop(struct module *mod, if (tramp & 0x8000) tramp -= 0x10000; - pr_debug(" %lx ", tramp); + pr_devel(" %lx ", tramp); if (tramp != addr) { printk(KERN_ERR @@ -402,7 +402,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) /* ld r2,40(r1) */ op[1] = 0xe8410028; - pr_debug("write to %lx\n", rec->ip); + pr_devel("write to %lx\n", rec->ip); if (probe_kernel_write((void *)ip, op, MCOUNT_INSN_SIZE * 2)) return -EPERM; @@ -442,7 +442,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) return -EINVAL; } - pr_debug("write to %lx\n", rec->ip); + pr_devel("write to %lx\n", rec->ip); if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE)) return -EPERM; -- cgit v1.2.3 From c3cf8667ed7db58c1960958cbb0a9098d513cc60 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 15 May 2009 04:33:54 +0000 Subject: powerpc/ftrace: Fix constraint to be early clobber After upgrading my distcc boxes from gcc 4.2.2 to 4.4.0, the function graph tracer broke. This was discovered on my x86 boxes. The issue is that gcc used the same register for an output as it did for an input in an asm statement. I first thought this was a bug in gcc and reported it. I was notified that gcc was correct and that the output had to be flagged as an "early clobber". I noticed that powerpc had the same issue and this patch fixes it. Signed-off-by: Steven Rostedt Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/ftrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index 5b078ee391f..2d182f119d1 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c @@ -594,7 +594,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) PPC_LONG "2b,4b\n" ".previous" - : [old] "=r" (old), [faulted] "=r" (faulted) + : [old] "=&r" (old), [faulted] "=r" (faulted) : [parent] "r" (parent), [return_hooker] "r" (return_hooker) : "memory" ); -- cgit v1.2.3 From 0e337b42d620ca7c45fe64e64dd71957c56216c9 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 17 May 2009 18:29:03 +0000 Subject: powerpc: Explicit alignment for .data.cacheline_aligned I don't think anything guarantees that the objects in data.page_aligned are a multiple of PAGE_SIZE, thus the section may end on any boundary. So the following section, .data.cacheline_aligned needs an explicit alignment. Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/kernel/vmlinux.lds.S | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index a047a6cfca4..8ef8a14abc9 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -264,6 +264,7 @@ SECTIONS *(.data.page_aligned) } + . = ALIGN(L1_CACHE_BYTES); .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { *(.data.cacheline_aligned) } -- cgit v1.2.3