From b97094560b991af5c62391014e72bfa4c3a3701f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 13 Feb 2008 19:20:45 -0800 Subject: [SPARC64]: Call real_setup_per_cpu_areas() earlier and use lmb_alloc(). We have to do it like this before we can move the PROM and MDESC device tree code over to using lmb_alloc(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/smp.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 59f020d69d4c..524b88920947 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -1431,7 +1431,7 @@ EXPORT_SYMBOL(__per_cpu_shift); void __init real_setup_per_cpu_areas(void) { - unsigned long goal, size, i; + unsigned long paddr, goal, size, i; char *ptr; /* Copy section for each CPU (we discard the original) */ @@ -1441,8 +1441,13 @@ void __init real_setup_per_cpu_areas(void) for (size = PAGE_SIZE; size < goal; size <<= 1UL) __per_cpu_shift++; - ptr = alloc_bootmem_pages(size * NR_CPUS); + paddr = lmb_alloc(size * NR_CPUS, PAGE_SIZE); + if (!paddr) { + prom_printf("Cannot allocate per-cpu memory.\n"); + prom_halt(); + } + ptr = __va(paddr); __per_cpu_base = ptr - __per_cpu_start; for (i = 0; i < NR_CPUS; i++, ptr += size) -- cgit v1.2.3 From ad072004ca35a9918964ca7aee2bf00d79c8657f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 13 Feb 2008 19:21:51 -0800 Subject: [SPARC64]: Use lmb_alloc() for PROM device tree. Signed-off-by: David S. Miller --- arch/sparc64/kernel/prom.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 68964ddcde1e..ed03a18d3b36 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -19,8 +19,8 @@ #include #include #include -#include #include +#include #include #include @@ -122,16 +122,20 @@ int of_find_in_proplist(const char *list, const char *match, int len) } EXPORT_SYMBOL(of_find_in_proplist); -static unsigned int prom_early_allocated; +static unsigned int prom_early_allocated __initdata; static void * __init prom_early_alloc(unsigned long size) { + unsigned long paddr = lmb_alloc(size, SMP_CACHE_BYTES); void *ret; - ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); - if (ret != NULL) - memset(ret, 0, size); + if (!paddr) { + prom_printf("prom_early_alloc(%lu) failed\n"); + prom_halt(); + } + ret = __va(paddr); + memset(ret, 0, size); prom_early_allocated += size; return ret; -- cgit v1.2.3 From 4a28333984be123d9c063df23175c48749c4b4a0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 13 Feb 2008 19:22:23 -0800 Subject: [SPARC64]: Initialize MDESC earlier and use lmb_alloc() Signed-off-by: David S. Miller --- arch/sparc64/kernel/mdesc.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c index 910083589569..dde52bcf5c64 100644 --- a/arch/sparc64/kernel/mdesc.c +++ b/arch/sparc64/kernel/mdesc.c @@ -1,10 +1,10 @@ /* mdesc.c: Sun4V machine description handling. * - * Copyright (C) 2007 David S. Miller + * Copyright (C) 2007, 2008 David S. Miller */ #include #include -#include +#include #include #include #include @@ -84,24 +84,28 @@ static void mdesc_handle_init(struct mdesc_handle *hp, hp->handle_size = handle_size; } -static struct mdesc_handle * __init mdesc_bootmem_alloc(unsigned int mdesc_size) +static struct mdesc_handle * __init mdesc_lmb_alloc(unsigned int mdesc_size) { - struct mdesc_handle *hp; unsigned int handle_size, alloc_size; + struct mdesc_handle *hp; + unsigned long paddr; handle_size = (sizeof(struct mdesc_handle) - sizeof(struct mdesc_hdr) + mdesc_size); alloc_size = PAGE_ALIGN(handle_size); - hp = __alloc_bootmem(alloc_size, PAGE_SIZE, 0UL); - if (hp) - mdesc_handle_init(hp, handle_size, hp); + paddr = lmb_alloc(alloc_size, PAGE_SIZE); + hp = NULL; + if (paddr) { + hp = __va(paddr); + mdesc_handle_init(hp, handle_size, hp); + } return hp; } -static void mdesc_bootmem_free(struct mdesc_handle *hp) +static void mdesc_lmb_free(struct mdesc_handle *hp) { unsigned int alloc_size, handle_size = hp->handle_size; unsigned long start, end; @@ -124,9 +128,9 @@ static void mdesc_bootmem_free(struct mdesc_handle *hp) } } -static struct mdesc_mem_ops bootmem_mdesc_ops = { - .alloc = mdesc_bootmem_alloc, - .free = mdesc_bootmem_free, +static struct mdesc_mem_ops lmb_mdesc_ops = { + .alloc = mdesc_lmb_alloc, + .free = mdesc_lmb_free, }; static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size) @@ -888,7 +892,7 @@ void __init sun4v_mdesc_init(void) printk("MDESC: Size is %lu bytes.\n", len); - hp = mdesc_alloc(len, &bootmem_mdesc_ops); + hp = mdesc_alloc(len, &lmb_mdesc_ops); if (hp == NULL) { prom_printf("MDESC: alloc of %lu bytes failed.\n", len); prom_halt(); -- cgit v1.2.3 From ce3b1d47a8605905b666649ea309b6471a75b4ed Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 19 Mar 2008 03:54:09 -0700 Subject: [SPARC64]: Once we have the boot cmdline, call parse_early_param() Signed-off-by: David S. Miller --- arch/sparc64/kernel/setup.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 6acb4c51cfe4..46bcf41097a8 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -281,6 +281,7 @@ void __init setup_arch(char **cmdline_p) /* Initialize PROM console and command line. */ *cmdline_p = prom_getbootargs(); strcpy(boot_command_line, *cmdline_p); + parse_early_param(); boot_flags_init(*cmdline_p); register_console(&prom_early_console); -- cgit v1.2.3 From 0c49a573ea93f777fd27f26b7853e7bf5a20e1a3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 13 Feb 2008 22:15:46 -0800 Subject: [SPARC64]: Kill pci_iommu_table_init() declaration. No longer exists. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_impl.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index 4a50da13ce48..f79c923fdd8f 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -161,8 +161,6 @@ extern struct pci_pbm_info *pci_pbm_root; extern int pci_num_pbms; /* PCI bus scanning and fixup support. */ -extern void pci_iommu_table_init(struct iommu *iommu, int tsbsize, - u32 dma_offset, u32 dma_addr_mask); extern void pci_get_pbm_props(struct pci_pbm_info *pbm); extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); -- cgit v1.2.3 From c1b1a5f1f1b2612b69b67381b223bce9f8ec4da5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 19 Mar 2008 04:52:48 -0700 Subject: [SPARC64]: NUMA device infrastructure. Record and propagate NUMA information for devices. Signed-off-by: David S. Miller --- arch/sparc64/kernel/ebus.c | 1 + arch/sparc64/kernel/iommu.c | 33 +++++++++++++++++++++------------ arch/sparc64/kernel/isa.c | 1 + arch/sparc64/kernel/of_device.c | 12 +++++++++++- arch/sparc64/kernel/pci.c | 12 ++++++++++++ arch/sparc64/kernel/pci_fire.c | 5 ++++- arch/sparc64/kernel/pci_impl.h | 2 ++ arch/sparc64/kernel/pci_msi.c | 8 +++++++- arch/sparc64/kernel/pci_psycho.c | 5 ++++- arch/sparc64/kernel/pci_sabre.c | 4 +++- arch/sparc64/kernel/pci_schizo.c | 5 ++++- arch/sparc64/kernel/pci_sun4v.c | 13 ++++++++++--- arch/sparc64/kernel/sbus.c | 3 ++- 13 files changed, 82 insertions(+), 22 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 04ab81cb4f48..bc2632274840 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -396,6 +396,7 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de sd->op = &dev->ofdev; sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; sd->stc = dev->bus->ofdev.dev.parent->archdata.stc; + sd->numa_node = dev->bus->ofdev.dev.parent->archdata.numa_node; dev->ofdev.node = dp; dev->ofdev.dev.parent = &dev->bus->ofdev.dev; diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c index 756fa24eeefa..2a37a6ca2a16 100644 --- a/arch/sparc64/kernel/iommu.c +++ b/arch/sparc64/kernel/iommu.c @@ -173,9 +173,11 @@ void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long np } int iommu_table_init(struct iommu *iommu, int tsbsize, - u32 dma_offset, u32 dma_addr_mask) + u32 dma_offset, u32 dma_addr_mask, + int numa_node) { - unsigned long i, tsbbase, order, sz, num_tsb_entries; + unsigned long i, order, sz, num_tsb_entries; + struct page *page; num_tsb_entries = tsbsize / sizeof(iopte_t); @@ -188,11 +190,12 @@ int iommu_table_init(struct iommu *iommu, int tsbsize, /* Allocate and initialize the free area map. */ sz = num_tsb_entries / 8; sz = (sz + 7UL) & ~7UL; - iommu->arena.map = kzalloc(sz, GFP_KERNEL); + iommu->arena.map = kmalloc_node(sz, GFP_KERNEL, numa_node); if (!iommu->arena.map) { printk(KERN_ERR "IOMMU: Error, kmalloc(arena.map) failed.\n"); return -ENOMEM; } + memset(iommu->arena.map, 0, sz); iommu->arena.limit = num_tsb_entries; if (tlb_type != hypervisor) @@ -201,21 +204,23 @@ int iommu_table_init(struct iommu *iommu, int tsbsize, /* Allocate and initialize the dummy page which we * set inactive IO PTEs to point to. */ - iommu->dummy_page = get_zeroed_page(GFP_KERNEL); - if (!iommu->dummy_page) { + page = alloc_pages_node(numa_node, GFP_KERNEL, 0); + if (!page) { printk(KERN_ERR "IOMMU: Error, gfp(dummy_page) failed.\n"); goto out_free_map; } + iommu->dummy_page = (unsigned long) page_address(page); + memset((void *)iommu->dummy_page, 0, PAGE_SIZE); iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page); /* Now allocate and setup the IOMMU page table itself. */ order = get_order(tsbsize); - tsbbase = __get_free_pages(GFP_KERNEL, order); - if (!tsbbase) { + page = alloc_pages_node(numa_node, GFP_KERNEL, order); + if (!page) { printk(KERN_ERR "IOMMU: Error, gfp(tsb) failed.\n"); goto out_free_dummy_page; } - iommu->page_table = (iopte_t *)tsbbase; + iommu->page_table = (iopte_t *)page_address(page); for (i = 0; i < num_tsb_entries; i++) iopte_make_dummy(iommu, &iommu->page_table[i]); @@ -276,20 +281,24 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx) static void *dma_4u_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp) { + unsigned long flags, order, first_page; struct iommu *iommu; + struct page *page; + int npages, nid; iopte_t *iopte; - unsigned long flags, order, first_page; void *ret; - int npages; size = IO_PAGE_ALIGN(size); order = get_order(size); if (order >= 10) return NULL; - first_page = __get_free_pages(gfp, order); - if (first_page == 0UL) + nid = dev->archdata.numa_node; + page = alloc_pages_node(nid, gfp, order); + if (unlikely(!page)) return NULL; + + first_page = (unsigned long) page_address(page); memset((char *)first_page, 0, PAGE_SIZE << order); iommu = dev->archdata.iommu; diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index b5f7b354084f..a2af5ed784c9 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c @@ -92,6 +92,7 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) sd->op = &isa_dev->ofdev; sd->iommu = isa_br->ofdev.dev.parent->archdata.iommu; sd->stc = isa_br->ofdev.dev.parent->archdata.stc; + sd->numa_node = isa_br->ofdev.dev.parent->archdata.numa_node; isa_dev->ofdev.node = dp; isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 0fd9db95b896..9e58e8cba1c3 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -660,6 +661,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op, struct device_node *dp = op->node; struct device_node *pp, *ip; unsigned int orig_irq = irq; + int nid; if (irq == 0xffffffff) return irq; @@ -672,7 +674,7 @@ static unsigned int __init build_one_device_irq(struct of_device *op, printk("%s: direct translate %x --> %x\n", dp->full_name, orig_irq, irq); - return irq; + goto out; } /* Something more complicated. Walk up to the root, applying @@ -744,6 +746,14 @@ static unsigned int __init build_one_device_irq(struct of_device *op, printk("%s: Apply IRQ trans [%s] %x --> %x\n", op->node->full_name, ip->full_name, orig_irq, irq); +out: + nid = of_node_to_nid(dp); + if (nid != -1) { + cpumask_t numa_mask = node_to_cpumask(nid); + + irq_set_affinity(irq, numa_mask); + } + return irq; } diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 545356b00e2e..49f912766519 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -369,10 +369,12 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, sd->host_controller = pbm; sd->prom_node = node; sd->op = of_find_device_by_node(node); + sd->numa_node = pbm->numa_node; sd = &sd->op->dev.archdata; sd->iommu = pbm->iommu; sd->stc = &pbm->stc; + sd->numa_node = pbm->numa_node; type = of_get_property(node, "device_type", NULL); if (type == NULL) @@ -1159,6 +1161,16 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, return 0; } +#ifdef CONFIG_NUMA +int pcibus_to_node(struct pci_bus *pbus) +{ + struct pci_pbm_info *pbm = pbus->sysdata; + + return pbm->numa_node; +} +EXPORT_SYMBOL(pcibus_to_node); +#endif + /* Return the domain nuber for this pci bus */ int pci_domain_nr(struct pci_bus *pbus) diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 7571ed563147..d23bb6f53cda 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c @@ -71,7 +71,8 @@ static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) */ fire_write(iommu->iommu_flushinv, ~(u64)0); - err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask); + err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, + pbm->numa_node); if (err) return err; @@ -449,6 +450,8 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, pbm->next = pci_pbm_root; pci_pbm_root = pbm; + pbm->numa_node = -1; + pbm->scan_bus = pci_fire_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 12; diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index f79c923fdd8f..218bac4ff79b 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -148,6 +148,8 @@ struct pci_pbm_info { struct pci_bus *pci_bus; void (*scan_bus)(struct pci_pbm_info *); struct pci_ops *pci_ops; + + int numa_node; }; struct pci_controller_info { diff --git a/arch/sparc64/kernel/pci_msi.c b/arch/sparc64/kernel/pci_msi.c index d6d64b44af63..db5e8fd8f674 100644 --- a/arch/sparc64/kernel/pci_msi.c +++ b/arch/sparc64/kernel/pci_msi.c @@ -279,11 +279,17 @@ static int bringup_one_msi_queue(struct pci_pbm_info *pbm, unsigned long devino) { int irq = ops->msiq_build_irq(pbm, msiqid, devino); - int err; + int err, nid; if (irq < 0) return irq; + nid = pbm->numa_node; + if (nid != -1) { + cpumask_t numa_mask = node_to_cpumask(nid); + + irq_set_affinity(irq, numa_mask); + } err = request_irq(irq, sparc64_msiq_interrupt, 0, "MSIQ", &pbm->msiq_irq_cookies[msiqid - pbm->msiq_first]); diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 0bad96e5d184..994dbe0603da 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -848,7 +848,8 @@ static int psycho_iommu_init(struct pci_pbm_info *pbm) /* Leave diag mode enabled for full-flushing done * in pci_iommu.c */ - err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff); + err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff, + pbm->numa_node); if (err) return err; @@ -979,6 +980,8 @@ static void __init psycho_pbm_init(struct pci_controller_info *p, pbm->next = pci_pbm_root; pci_pbm_root = pbm; + pbm->numa_node = -1; + pbm->scan_bus = psycho_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 8; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 1c5f5fa2339f..4c34195baf37 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -704,7 +704,7 @@ static int sabre_iommu_init(struct pci_pbm_info *pbm, * in pci_iommu.c */ err = iommu_table_init(iommu, tsbsize * 1024 * 8, - dvma_offset, dma_mask); + dvma_offset, dma_mask, pbm->numa_node); if (err) return err; @@ -737,6 +737,8 @@ static void __init sabre_pbm_init(struct pci_controller_info *p, pbm->name = dp->full_name; printk("%s: SABRE PCI Bus Module\n", pbm->name); + pbm->numa_node = -1; + pbm->scan_bus = sabre_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 8; diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index e30609362322..615edd9c8e2a 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c @@ -1220,7 +1220,8 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) /* Leave diag mode enabled for full-flushing done * in pci_iommu.c */ - err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask); + err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, + pbm->numa_node); if (err) return err; @@ -1379,6 +1380,8 @@ static int __init schizo_pbm_init(struct pci_controller_info *p, pbm->next = pci_pbm_root; pci_pbm_root = pbm; + pbm->numa_node = -1; + pbm->scan_bus = schizo_scan_bus; pbm->pci_ops = &sun4u_pci_ops; pbm->config_space_reg_bits = 8; diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 01839706bd52..e2bb9790039c 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -127,10 +127,12 @@ static inline long iommu_batch_end(void) static void *dma_4v_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp) { - struct iommu *iommu; unsigned long flags, order, first_page, npages, n; + struct iommu *iommu; + struct page *page; void *ret; long entry; + int nid; size = IO_PAGE_ALIGN(size); order = get_order(size); @@ -139,10 +141,12 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size, npages = size >> IO_PAGE_SHIFT; - first_page = __get_free_pages(gfp, order); - if (unlikely(first_page == 0UL)) + nid = dev->archdata.numa_node; + page = alloc_pages_node(nid, gfp, order); + if (unlikely(!page)) return NULL; + first_page = (unsigned long) page_address(page); memset((char *)first_page, 0, PAGE_SIZE << order); iommu = dev->archdata.iommu; @@ -899,6 +903,8 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, pbm->next = pci_pbm_root; pci_pbm_root = pbm; + pbm->numa_node = of_node_to_nid(dp); + pbm->scan_bus = pci_sun4v_scan_bus; pbm->pci_ops = &sun4v_pci_ops; pbm->config_space_reg_bits = 12; @@ -913,6 +919,7 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, pbm->name = dp->full_name; printk("%s: SUN4V PCI Bus Module\n", pbm->name); + printk("%s: On NUMA node %d\n", pbm->name, pbm->numa_node); pci_determine_mem_io_space(pbm); diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index d1fb13ba02b5..fa2827c4a3ad 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c @@ -544,6 +544,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) sbus->ofdev.dev.archdata.iommu = iommu; sbus->ofdev.dev.archdata.stc = strbuf; + sbus->ofdev.dev.archdata.numa_node = -1; reg_base = regs + SYSIO_IOMMUREG_BASE; iommu->iommu_control = reg_base + IOMMU_CONTROL; @@ -575,7 +576,7 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) sbus->portid, regs); /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ - if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff)) + if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1)) goto fatal_memory_error; control = upa_readq(iommu->iommu_control); -- cgit v1.2.3 From 919ee677b656c52c5f86d3d916786891220d5452 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 23 Apr 2008 05:40:25 -0700 Subject: [SPARC64]: Add NUMA support. Currently there is only code to parse NUMA attributes on sun4v/niagara systems, but later on we will add such parsing for older systems. Signed-off-by: David S. Miller --- arch/sparc64/kernel/sysfs.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c index 52816c7be0b9..e885034a6b73 100644 --- a/arch/sparc64/kernel/sysfs.c +++ b/arch/sparc64/kernel/sysfs.c @@ -273,10 +273,22 @@ static void __init check_mmu_stats(void) mmu_stats_supported = 1; } +static void register_nodes(void) +{ +#ifdef CONFIG_NUMA + int i; + + for (i = 0; i < MAX_NUMNODES; i++) + register_one_node(i); +#endif +} + static int __init topology_init(void) { int cpu; + register_nodes(); + check_mmu_stats(); register_cpu_notifier(&sysfs_cpu_nb); -- cgit v1.2.3 From c6ca978370c57422cdcf814af1da96cfc7c24811 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 23 Apr 2008 19:15:59 -0700 Subject: sparc64: cleanup after SunOS/Solaris binary emulation removal The following cleanups are now possible: - arch/sparc64/kernel/entry.S:ret_sys_call no longer has to be global - arch/sparc64/kernel/sparc64_ksyms.c: remove no longer used prototypes Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- arch/sparc64/kernel/entry.S | 2 +- arch/sparc64/kernel/sparc64_ksyms.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index fb43c76bdc26..f54cd2dd55dc 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1559,7 +1559,7 @@ linux_sparc_syscall32: /* Linux native system calls enter here... */ .align 32 - .globl linux_sparc_syscall, ret_sys_call + .globl linux_sparc_syscall linux_sparc_syscall: /* Direct access to user regs, much faster. */ cmp %g1, NR_SYSCALLS ! IEU1 Group diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 38736460b8db..66336590e830 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -68,8 +68,6 @@ extern void *__memscan_zero(void *, size_t); extern void *__memscan_generic(void *, int, size_t); extern int __memcmp(const void *, const void *, __kernel_size_t); extern __kernel_size_t strlen(const char *); -extern void linux_sparc_syscall(void); -extern void rtrap(void); extern void show_regs(struct pt_regs *); extern void syscall_trace(struct pt_regs *, int); extern void sys_sigsuspend(void); -- cgit v1.2.3 From db9a7fb12c8d05104e8a541003593d62a42ade8f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 23 Apr 2008 22:22:29 -0700 Subject: [SPARC64]: PROM debug console can be CON_ANYTIME. No per-cpu or similar resources need to be setup before we can use this console device. Signed-off-by: David S. Miller --- arch/sparc64/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 46bcf41097a8..da5e6ee0c661 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -82,7 +82,7 @@ unsigned long cmdline_memory_size = 0; static struct console prom_early_console = { .name = "earlyprom", .write = prom_console_write, - .flags = CON_PRINTBUFFER | CON_BOOT, + .flags = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME, .index = -1, }; -- cgit v1.2.3 From 8243e40acb087fcd9e7609333f0b0551391f49fc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 23 Apr 2008 22:52:13 -0700 Subject: [SPARC64]: Store magic cookie and trap type in pt_regs. This sets us up for several simplifications and facilities: 1) The magic cookie lets us identify trap frames more accurately in stack backtraces. 2) The trap type lets us simplify all of the "are we in a syscall" state management and checks. 3) We can now see if a task off the cpu is sleeping in a system call or not. In fact, we can see what trap it is sleeping in whatever the type. The utrace guys will use this. Based upon some discussions with Roland McGrath. Signed-off-by: David S. Miller --- arch/sparc64/kernel/etrap.S | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S index 4b2bf9eb447a..b49d3b60bc0c 100644 --- a/arch/sparc64/kernel/etrap.S +++ b/arch/sparc64/kernel/etrap.S @@ -53,7 +53,11 @@ etrap_irq: stx %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC] rd %y, %g3 stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC] + rdpr %tt, %g1 st %g3, [%g2 + STACKFRAME_SZ + PT_V9_Y] + sethi %hi(PT_REGS_MAGIC), %g3 + or %g3, %g1, %g1 + st %g1, [%g2 + STACKFRAME_SZ + PT_V9_MAGIC] rdpr %cansave, %g1 brnz,pt %g1, etrap_save -- cgit v1.2.3 From 238468b2ac76020c192a7402c92df5097916bf4a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 24 Apr 2008 03:01:48 -0700 Subject: [SPARC64]: Use trap type stored in pt_regs to handle syscall restart. Now that we can check the trap type directly, we don't need the funny restart_syscall indication from the trap return paths. Signed-off-by: David S. Miller --- arch/sparc64/kernel/signal.c | 22 +++++++++++++--------- arch/sparc64/kernel/signal32.c | 20 ++++++++------------ 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 1c47009eb5ec..b959597201ed 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -510,15 +510,20 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall) +static void do_signal(struct pt_regs *regs, unsigned long orig_i0) { - siginfo_t info; struct signal_deliver_cookie cookie; struct k_sigaction ka; - int signr; sigset_t *oldset; + siginfo_t info; + int signr, tt; - cookie.restart_syscall = restart_syscall; + tt = regs->magic & 0x1ff; + if (tt == 0x110 || tt == 0x111 || tt == 0x16d) { + regs->magic &= ~0x1ff; + cookie.restart_syscall = 1; + } else + cookie.restart_syscall = 0; cookie.orig_i0 = orig_i0; if (test_thread_flag(TIF_RESTORE_SIGMASK)) @@ -529,9 +534,8 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s #ifdef CONFIG_SPARC32_COMPAT if (test_thread_flag(TIF_32BIT)) { extern void do_signal32(sigset_t *, struct pt_regs *, - unsigned long, int); - do_signal32(oldset, regs, orig_i0, - cookie.restart_syscall); + struct signal_deliver_cookie *); + do_signal32(oldset, regs, &cookie); return; } #endif @@ -539,7 +543,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_s signr = get_signal_to_deliver(&info, &ka, regs, &cookie); if (signr > 0) { if (cookie.restart_syscall) - syscall_restart(orig_i0, regs, &ka.sa); + syscall_restart(cookie.orig_i0, regs, &ka.sa); handle_signal(signr, &ka, &info, oldset, regs); /* a signal was successfully delivered; the saved @@ -580,7 +584,7 @@ void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_s unsigned long thread_info_flags) { if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) - do_signal(regs, orig_i0, restart_syscall); + do_signal(regs, orig_i0); } void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 74e0512f135c..43cdec64d9c9 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -982,20 +982,16 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs * mistake. */ void do_signal32(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_i0, int restart_syscall) + struct signal_deliver_cookie *cookie) { - siginfo_t info; - struct signal_deliver_cookie cookie; struct k_sigaction ka; + siginfo_t info; int signr; - cookie.restart_syscall = restart_syscall; - cookie.orig_i0 = orig_i0; - - signr = get_signal_to_deliver(&info, &ka, regs, &cookie); + signr = get_signal_to_deliver(&info, &ka, regs, cookie); if (signr > 0) { - if (cookie.restart_syscall) - syscall_restart32(orig_i0, regs, &ka.sa); + if (cookie->restart_syscall) + syscall_restart32(cookie->orig_i0, regs, &ka.sa); handle_signal32(signr, &ka, &info, oldset, regs); /* a signal was successfully delivered; the saved @@ -1007,16 +1003,16 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, clear_thread_flag(TIF_RESTORE_SIGMASK); return; } - if (cookie.restart_syscall && + if (cookie->restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { /* replay the system call when we are done */ - regs->u_regs[UREG_I0] = cookie.orig_i0; + regs->u_regs[UREG_I0] = cookie->orig_i0; regs->tpc -= 4; regs->tnpc -= 4; } - if (cookie.restart_syscall && + if (cookie->restart_syscall && regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; -- cgit v1.2.3 From 7697daaa894ca2bc5cd652269c316bcdc3ec441b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 24 Apr 2008 03:15:22 -0700 Subject: [SPARC64]: %l6 trap return handling no longer necessary. Now that we indicate the "restart system call" in the trap type field of pt_regs->magic, we don't need to set the %l6 boolean in all of the trap return paths. And we therefore don't need to pass it to do_notify_resume(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/entry.S | 35 +++++++++++++++++------------------ arch/sparc64/kernel/entry.h | 1 - arch/sparc64/kernel/rtrap.S | 21 ++++----------------- arch/sparc64/kernel/signal.c | 3 +-- arch/sparc64/kernel/sun4v_tlb_miss.S | 16 ++++++++-------- arch/sparc64/kernel/tsb.S | 2 +- arch/sparc64/kernel/winfixup.S | 12 ++++++------ 7 files changed, 37 insertions(+), 53 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index f54cd2dd55dc..fd06e937ae1e 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -47,7 +47,7 @@ do_fpdis: ba,pt %xcc, etrap 109: or %g7, %lo(109b), %g7 add %g0, %g0, %g0 - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap 1: TRAP_LOAD_THREAD_REG(%g6, %g1) ldub [%g6 + TI_FPSAVED], %g5 @@ -226,7 +226,7 @@ fp_other_bounce: call do_fpother add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap - clr %l6 + nop .globl do_fpother_check_fitos .align 32 @@ -489,7 +489,7 @@ utrap_trap: /* %g3=handler,%g4=level */ call bad_trap add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap - clr %l6 + nop invoke_utrap: sllx %g3, 3, %g3 @@ -607,7 +607,7 @@ __spitfire_cee_trap_continue: call spitfire_access_error add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap - clr %l6 + nop /* This is the trap handler entry point for ECC correctable * errors. They are corrected, but we listen for the trap @@ -686,7 +686,7 @@ __spitfire_data_access_exception_tl1: call spitfire_data_access_exception_tl1 add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap - clr %l6 + nop __spitfire_data_access_exception: rdpr %pstate, %g4 @@ -705,7 +705,7 @@ __spitfire_data_access_exception: call spitfire_data_access_exception add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap - clr %l6 + nop .globl __spitfire_insn_access_exception .globl __spitfire_insn_access_exception_tl1 @@ -725,7 +725,7 @@ __spitfire_insn_access_exception_tl1: call spitfire_insn_access_exception_tl1 add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap - clr %l6 + nop __spitfire_insn_access_exception: rdpr %pstate, %g4 @@ -743,7 +743,7 @@ __spitfire_insn_access_exception: call spitfire_insn_access_exception add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap - clr %l6 + nop /* These get patched into the trap table at boot time * once we know we have a cheetah processor. @@ -937,7 +937,7 @@ do_dcpe_tl1_fatal: call cheetah_plus_parity_error add %sp, PTREGS_OFF, %o1 ba,pt %xcc, rtrap - clr %l6 + nop do_icpe_tl1: rdpr %tl, %g1 ! Save original trap level @@ -979,7 +979,7 @@ do_icpe_tl1_fatal: call cheetah_plus_parity_error add %sp, PTREGS_OFF, %o1 ba,pt %xcc, rtrap - clr %l6 + nop dcpe_icpe_tl1_common: /* Flush D-cache, re-enable D/I caches in DCU and finally @@ -1281,7 +1281,7 @@ __do_privact: call do_privact add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap - clr %l6 + nop .globl do_mna do_mna: @@ -1308,7 +1308,7 @@ do_mna: call mem_address_unaligned add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap - clr %l6 + nop .globl do_lddfmna do_lddfmna: @@ -1326,7 +1326,7 @@ do_lddfmna: call handle_lddfmna add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap - clr %l6 + nop .globl do_stdfmna do_stdfmna: @@ -1344,7 +1344,7 @@ do_stdfmna: call handle_stdfmna add %sp, PTREGS_OFF, %o0 ba,pt %xcc, rtrap - clr %l6 + nop .globl breakpoint_trap breakpoint_trap: @@ -1424,13 +1424,13 @@ sys32_rt_sigreturn: 1: ldx [%curptr + TI_FLAGS], %l5 andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 be,pt %icc, rtrap - clr %l6 + nop add %sp, PTREGS_OFF, %o0 call syscall_trace mov 1, %o1 ba,pt %xcc, rtrap - clr %l6 + nop /* This is how fork() was meant to be done, 8 instruction entry. * @@ -1605,7 +1605,7 @@ ret_sys_call: bne,pn %icc, linux_syscall_trace2 add %l1, 0x4, %l2 ! npc = npc+4 stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] - ba,pt %xcc, rtrap_clr_l6 + ba,pt %xcc, rtrap stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] 1: @@ -1616,7 +1616,6 @@ ret_sys_call: sub %g0, %o0, %o0 or %g3, %g2, %g3 stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - mov 1, %l6 stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] bne,pn %icc, linux_syscall_trace2 add %l1, 0x4, %l2 ! npc = npc+4 diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h index 4a91e9c6d31b..32fbab620852 100644 --- a/arch/sparc64/kernel/entry.h +++ b/arch/sparc64/kernel/entry.h @@ -20,7 +20,6 @@ extern void timer_interrupt(int irq, struct pt_regs *regs); extern void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, - int restart_syscall, unsigned long thread_info_flags); extern asmlinkage void syscall_trace(struct pt_regs *regs, diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index 079d18a11d24..ecf6753b204a 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -18,12 +18,6 @@ #define RTRAP_PSTATE_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV) #define RTRAP_PSTATE_AG_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) - /* Register %l6 keeps track of whether we are returning - * from a system call or not. It is cleared if we call - * do_notify_resume, and it must not be otherwise modified - * until we fully commit to returning to userspace. - */ - .text .align 32 __handle_softirq: @@ -56,14 +50,12 @@ __handle_user_windows: be,pt %xcc, __handle_user_windows_continue nop mov %l5, %o1 - mov %l6, %o2 add %sp, PTREGS_OFF, %o0 - mov %l0, %o3 + mov %l0, %o2 call do_notify_resume wrpr %g0, RTRAP_PSTATE, %pstate wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - clr %l6 /* Signal delivery can modify pt_regs tstate, so we must * reload it. */ @@ -99,14 +91,12 @@ __handle_perfctrs: be,pt %xcc, __handle_perfctrs_continue sethi %hi(TSTATE_PEF), %o0 mov %l5, %o1 - mov %l6, %o2 add %sp, PTREGS_OFF, %o0 - mov %l0, %o3 + mov %l0, %o2 call do_notify_resume wrpr %g0, RTRAP_PSTATE, %pstate wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - clr %l6 /* Signal delivery can modify pt_regs tstate, so we must * reload it. */ @@ -127,13 +117,11 @@ __handle_userfpu: __handle_signal: mov %l5, %o1 - mov %l6, %o2 add %sp, PTREGS_OFF, %o0 - mov %l0, %o3 + mov %l0, %o2 call do_notify_resume wrpr %g0, RTRAP_PSTATE, %pstate wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate - clr %l6 /* Signal delivery can modify pt_regs tstate, so we must * reload it. @@ -145,9 +133,8 @@ __handle_signal: andn %l1, %l4, %l1 .align 64 - .globl rtrap_irq, rtrap_clr_l6, rtrap, irqsz_patchme, rtrap_xcall + .globl rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall rtrap_irq: -rtrap_clr_l6: clr %l6 rtrap: #ifndef CONFIG_SMP sethi %hi(per_cpu____cpu_data), %l0 diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index b959597201ed..77a3e8592cbc 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -580,8 +580,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) } } -void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall, - unsigned long thread_info_flags) +void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) { if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) do_signal(regs, orig_i0); diff --git a/arch/sparc64/kernel/sun4v_tlb_miss.S b/arch/sparc64/kernel/sun4v_tlb_miss.S index fd9430562e0b..e1fbf8c75787 100644 --- a/arch/sparc64/kernel/sun4v_tlb_miss.S +++ b/arch/sparc64/kernel/sun4v_tlb_miss.S @@ -262,7 +262,7 @@ sun4v_iacc: mov %l5, %o2 call sun4v_insn_access_exception add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap /* Instruction Access Exception, tl1. */ sun4v_iacc_tl1: @@ -278,7 +278,7 @@ sun4v_iacc_tl1: mov %l5, %o2 call sun4v_insn_access_exception_tl1 add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap /* Data Access Exception, tl0. */ sun4v_dacc: @@ -294,7 +294,7 @@ sun4v_dacc: mov %l5, %o2 call sun4v_data_access_exception add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap /* Data Access Exception, tl1. */ sun4v_dacc_tl1: @@ -310,7 +310,7 @@ sun4v_dacc_tl1: mov %l5, %o2 call sun4v_data_access_exception_tl1 add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap /* Memory Address Unaligned. */ sun4v_mna: @@ -344,7 +344,7 @@ sun4v_mna: mov %l5, %o2 call sun4v_do_mna add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap /* Privileged Action. */ sun4v_privact: @@ -352,7 +352,7 @@ sun4v_privact: rd %pc, %g7 call do_privact add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap /* Unaligned ldd float, tl0. */ sun4v_lddfmna: @@ -368,7 +368,7 @@ sun4v_lddfmna: mov %l5, %o2 call handle_lddfmna add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap /* Unaligned std float, tl0. */ sun4v_stdfmna: @@ -384,7 +384,7 @@ sun4v_stdfmna: mov %l5, %o2 call handle_stdfmna add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap #define BRANCH_ALWAYS 0x10680000 #define NOP 0x01000000 diff --git a/arch/sparc64/kernel/tsb.S b/arch/sparc64/kernel/tsb.S index 10adb2fb8ffe..c499214b501d 100644 --- a/arch/sparc64/kernel/tsb.S +++ b/arch/sparc64/kernel/tsb.S @@ -275,7 +275,7 @@ sparc64_realfault_common: stx %l5, [%g6 + TI_FAULT_ADDR] ! Save fault address call do_sparc64_fault ! Call fault handler add %sp, PTREGS_OFF, %o0 ! Compute pt_regs arg - ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state + ba,pt %xcc, rtrap ! Restore cpu state nop ! Delay slot (fill me) winfix_trampoline: diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S index c4aa110a10e5..a6b0863c27df 100644 --- a/arch/sparc64/kernel/winfixup.S +++ b/arch/sparc64/kernel/winfixup.S @@ -32,7 +32,7 @@ fill_fixup: rd %pc, %g7 call do_sparc64_fault add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, rtrap_clr_l6 + ba,pt %xcc, rtrap nop /* Be very careful about usage of the trap globals here. @@ -100,7 +100,7 @@ spill_fixup_dax: rd %pc, %g7 call do_sparc64_fault add %sp, PTREGS_OFF, %o0 - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap winfix_mna: andn %g3, 0x7f, %g3 @@ -122,12 +122,12 @@ fill_fixup_mna: mov %l4, %o2 call sun4v_do_mna mov %l5, %o1 - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap 1: mov %l4, %o1 mov %l5, %o2 call mem_address_unaligned nop - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap winfix_dax: andn %g3, 0x7f, %g3 @@ -150,7 +150,7 @@ fill_fixup_dax: add %sp, PTREGS_OFF, %o0 call sun4v_data_access_exception nop - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap 1: call spitfire_data_access_exception nop - ba,a,pt %xcc, rtrap_clr_l6 + ba,a,pt %xcc, rtrap -- cgit v1.2.3 From 77c664fa58624079f7a0fc29b46e8a32883633a5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 24 Apr 2008 03:28:52 -0700 Subject: [SPARC64]: Detect trap frames in stack backtraces. Now that we have a magic cookie in the pt_regs, we can properly detect trap frames in stack bactraces. Signed-off-by: David S. Miller --- arch/sparc64/kernel/stacktrace.c | 16 +++++++++++++--- arch/sparc64/kernel/traps.c | 19 +++++++++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) (limited to 'arch/sparc64/kernel') diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c index 84d39e873e88..01b52f561af4 100644 --- a/arch/sparc64/kernel/stacktrace.c +++ b/arch/sparc64/kernel/stacktrace.c @@ -20,6 +20,8 @@ void save_stack_trace(struct stack_trace *trace) thread_base = (unsigned long) tp; do { struct reg_window *rw; + struct pt_regs *regs; + unsigned long pc; /* Bogus frame pointer? */ if (fp < (thread_base + sizeof(struct thread_info)) || @@ -27,11 +29,19 @@ void save_stack_trace(struct stack_trace *trace) break; rw = (struct reg_window *) fp; + regs = (struct pt_regs *) (rw + 1); + + if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) { + pc = regs->tpc; + fp = regs->u_regs[UREG_I6] + STACK_BIAS; + } else { + pc = rw->ins[7]; + fp = rw->ins[6] + STACK_BIAS; + } + if (trace->skip > 0) trace->skip--; else - trace->entries[trace->nr_entries++] = rw->ins[7]; - - fp = rw->ins[6] + STACK_BIAS; + trace->entries[trace->nr_entries++] = pc; } while (trace->nr_entries < trace->max_entries); } diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 96da847023f3..d9b8d46707d1 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -2091,9 +2091,8 @@ static void user_instruction_dump(unsigned int __user *pc) void show_stack(struct task_struct *tsk, unsigned long *_ksp) { - unsigned long pc, fp, thread_base, ksp; + unsigned long fp, thread_base, ksp; struct thread_info *tp; - struct reg_window *rw; int count = 0; ksp = (unsigned long) _ksp; @@ -2117,15 +2116,27 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) printk("\n"); #endif do { + struct reg_window *rw; + struct pt_regs *regs; + unsigned long pc; + /* Bogus frame pointer? */ if (fp < (thread_base + sizeof(struct thread_info)) || fp >= (thread_base + THREAD_SIZE)) break; rw = (struct reg_window *)fp; - pc = rw->ins[7]; + regs = (struct pt_regs *) (rw + 1); + + if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) { + pc = regs->tpc; + fp = regs->u_regs[UREG_I6] + STACK_BIAS; + } else { + pc = rw->ins[7]; + fp = rw->ins[6] + STACK_BIAS; + } + printk(" [%016lx] ", pc); print_symbol("%s\n", pc); - fp = rw->ins[6] + STACK_BIAS; } while (++count < 16); #ifndef CONFIG_KALLSYMS printk("\n"); -- cgit v1.2.3