From 227c3311786dbe64cb221e63d53817f98240e587 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 26 Apr 2008 02:19:18 -0700 Subject: sparc64: Fix wedged irq regression. Kernel bugzilla 10273 As reported by Jos van der Ende, ever since commit 5a606b72a4309a656cd1a19ad137dc5557c4b8ea ("[SPARC64]: Do not ACK an INO if it is disabled or inprogress.") sun4u interrupts can get stuck. What this changset did was add the following conditional to the various IRQ chip ->enable() handlers on sparc64: if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) return; which is correct, however it means that special care is needed in the ->enable() method. Specifically we must put the interrupt into IDLE state during an enable, or else it might never be sent out again. Setting the INO interrupt state to IDLE resets the state machine, the interrupt input to the INO is retested by the hardware, and if an interrupt is being signalled by the device, the INO moves back into TRANSMIT state, and an interrupt vector is sent to the cpu. The two sun4v IRQ chip handlers were already doing this properly, only sun4u got it wrong. Signed-off-by: David S. Miller --- arch/sparc64/kernel/irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index eb88bd6e674e..b441a26b73b0 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -1,6 +1,6 @@ /* irq.c: UltraSparc IRQ handling/init/registry. * - * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1997, 2007, 2008 David S. Miller (davem@davemloft.net) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) */ @@ -308,6 +308,7 @@ static void sun4u_irq_enable(unsigned int virt_irq) IMAP_AID_SAFARI | IMAP_NID_SAFARI); val |= tid | IMAP_VALID; upa_writeq(val, imap); + upa_writeq(ICLR_IDLE, data->iclr); } } -- cgit v1.2.3 From 05d515ef3d14eb95ffe9239ec1b8a03b24fa8469 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 26 Apr 2008 03:07:34 -0700 Subject: sparc64: Cleanups and corrections for arch/sparc64/Kconfig Refer to chip as "SPARC" throughout. Say 32-bit SPARC and 64-bit SPARC rather than mentioning specific chips such like UltraSPARC, as appropriate. Remove non-sense help text referring to things that will never appear on a SPARC system, such as EISA busses etc. Use "help" instead of "--help--" Signed-off-by: David S. Miller --- arch/sparc64/Kconfig | 82 +++++++++++----------------------------------------- 1 file changed, 17 insertions(+), 65 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 8acc5cc38621..d3fa0f8fc613 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -1,9 +1,5 @@ -# $Id: config.in,v 1.158 2002/01/24 22:14:44 davem Exp $ -# For a description of the syntax of this configuration file, -# see the Configure script. -# - -mainmenu "Linux/UltraSPARC Kernel Configuration" +# sparc64 configuration +mainmenu "Linux Kernel Configuration for 64-bit SPARC" config SPARC bool @@ -17,12 +13,6 @@ config SPARC64 default y select HAVE_IDE select HAVE_LMB - help - SPARC is a family of RISC microprocessors designed and marketed by - Sun Microsystems, incorporated. This port covers the newer 64-bit - UltraSPARC. The UltraLinux project maintains both the SPARC32 and - SPARC64 ports; its web page is available at - . config GENERIC_TIME bool @@ -97,7 +87,7 @@ config SPARC64_PAGE_SIZE_8KB help This lets you select the page size of the kernel. - 8KB and 64KB work quite well, since Sparc ELF sections + 8KB and 64KB work quite well, since SPARC ELF sections provide for up to 64KB alignment. Therefore, 512KB and 4MB are for expert hackers only. @@ -138,7 +128,7 @@ config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" depends on SMP select HOTPLUG - ---help--- + help Say Y here to experiment with turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu/cpu#. Say N if you want to disable CPU hotplug. @@ -155,23 +145,16 @@ source "kernel/time/Kconfig" config SMP bool "Symmetric multi-processing support" - ---help--- + help This enables support for systems with more than one CPU. If you have a system with only one CPU, say N. If you have a system with more than one CPU, say Y. If you say N here, the kernel will run on single and multiprocessor machines, but will use only one CPU of a multiprocessor machine. If - you say Y here, the kernel will run on many, but not all, - singleprocessor machines. On a singleprocessor machine, the kernel - will run faster if you say N here. - - People using multiprocessor machines who say Y here should also say - Y to "Enhanced Real Time Clock Support", below. The "Advanced Power - Management" code will be disabled if you say Y here. - - See also and the SMP-HOWTO - available at . + you say Y here, the kernel will run on single-processor machines. + On a single-processor machine, the kernel will run faster if you say + N here. If you don't know what to do here, say N. @@ -284,50 +267,19 @@ source "mm/Kconfig" config ISA bool - help - Find out whether you have ISA slots on your motherboard. ISA is the - name of a bus system, i.e. the way the CPU talks to the other stuff - inside your box. Other bus systems are PCI, EISA, MicroChannel - (MCA) or VESA. ISA is an older system, now being displaced by PCI; - newer boards don't support it. If you have ISA, say Y, otherwise N. config ISAPNP bool - help - Say Y here if you would like support for ISA Plug and Play devices. - Some information is in . - - To compile this driver as a module, choose M here: the - module will be called isapnp. - - If unsure, say Y. config EISA bool - ---help--- - The Extended Industry Standard Architecture (EISA) bus was - developed as an open alternative to the IBM MicroChannel bus. - - The EISA bus provided some of the features of the IBM MicroChannel - bus while maintaining backward compatibility with cards made for - the older ISA bus. The EISA bus saw limited use between 1988 and - 1995 when it was made obsolete by the PCI bus. - - Say Y here if you are building a kernel for an EISA-based machine. - - Otherwise, say N. config MCA bool - help - MicroChannel Architecture is found in some IBM PS/2 machines and - laptops. It is a bus system similar to PCI or ISA. See - (and especially the web page given - there) before attempting to build an MCA bus kernel. config PCMCIA tristate - ---help--- + help Say Y here if you want to attach PCMCIA- or PC-cards to your Linux computer. These are credit-card size devices such as network cards, modems or hard drives often used with laptops computers. There are @@ -369,10 +321,10 @@ config PCI bool "PCI support" select ARCH_SUPPORTS_MSI help - Find out whether you have a PCI motherboard. PCI is the name of a - bus system, i.e. the way the CPU talks to the other stuff inside - your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or - VESA. If you have PCI, say Y, otherwise N. + Find out whether your system includes a PCI bus. PCI is the name of + a bus system, i.e. the way the CPU talks to the other stuff inside + your box. If you say Y here, the kernel will include drivers and + infrastructure code to support PCI bus devices. config PCI_DOMAINS def_bool PCI @@ -397,9 +349,9 @@ menu "Executable file formats" source "fs/Kconfig.binfmt" config SPARC32_COMPAT - bool "Kernel support for Linux/Sparc 32bit binary compatibility" + bool "Kernel support for 32-bit SPARC binary compatibility" help - This allows you to run 32-bit binaries on your Ultra. + This allows you to run 32-bit binaries on your 64-bit SPARC system. Everybody wants this; say Y. config COMPAT @@ -421,8 +373,8 @@ config SCHED_SMT default y help SMT scheduler support improves the CPU scheduler's decision making - when dealing with UltraSPARC cpus at a cost of slightly increased - overhead in some places. If unsure say N here. + when dealing with SPARC cpus at a cost of slightly increased overhead + in some places. If unsure say N here. config SCHED_MC bool "Multi-core scheduler support" -- cgit v1.2.3 From 09337f501ebdd224cd69df6d168a5c4fe75d86fa Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 26 Apr 2008 03:17:12 -0700 Subject: sparc64: Kill CONFIG_SPARC32_COMPAT It's completely superfluous, CONFIG_COMPAT is sufficient. What this used to be is an umbrella for enabling code shared by all 32-bit compat binary support types. But with the removal of SunOS and Solaris support, the only one left is Linux 32-bit ELF. Update defconfig. Signed-off-by: David S. Miller --- arch/sparc64/Kconfig | 7 ------- arch/sparc64/defconfig | 23 +++++++++-------------- arch/sparc64/kernel/Makefile | 4 ++-- arch/sparc64/kernel/audit.c | 6 +++--- arch/sparc64/kernel/signal.c | 4 ++-- init/Kconfig | 2 +- 6 files changed, 17 insertions(+), 29 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index d3fa0f8fc613..edbe71e3fab9 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -348,15 +348,8 @@ menu "Executable file formats" source "fs/Kconfig.binfmt" -config SPARC32_COMPAT - bool "Kernel support for 32-bit SPARC binary compatibility" - help - This allows you to run 32-bit binaries on your 64-bit SPARC system. - Everybody wants this; say Y. - config COMPAT bool - depends on SPARC32_COMPAT default y select COMPAT_BINFMT_ELF diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 92f79680f70d..aff93c9d13f4 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.25-numa -# Wed Apr 23 04:49:08 2008 +# Linux kernel version: 2.6.25 +# Sat Apr 26 03:11:06 2008 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -152,7 +152,9 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_HUGETLB_PAGE_SIZE_4MB=y # CONFIG_HUGETLB_PAGE_SIZE_512K is not set # CONFIG_HUGETLB_PAGE_SIZE_64K is not set -# CONFIG_NUMA is not set +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=4 +CONFIG_NODES_SPAN_OTHER_NODES=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -162,12 +164,14 @@ CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_DISCONTIGMEM_MANUAL is not set CONFIG_SPARSEMEM_MANUAL=y CONFIG_SPARSEMEM=y +CONFIG_NEED_MULTIPLE_NODES=y CONFIG_HAVE_MEMORY_PRESENT=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y CONFIG_SPARSEMEM_VMEMMAP=y CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y CONFIG_RESOURCES_64BIT=y CONFIG_ZONE_DMA_FLAG=0 CONFIG_NR_QUICK=1 @@ -191,7 +195,6 @@ CONFIG_SUN_OPENPROMFS=m CONFIG_BINFMT_ELF=y CONFIG_COMPAT_BINFMT_ELF=y CONFIG_BINFMT_MISC=m -CONFIG_SPARC32_COMPAT=y CONFIG_COMPAT=y CONFIG_SYSVIPC_COMPAT=y CONFIG_SCHED_SMT=y @@ -746,13 +749,7 @@ CONFIG_DEVPORT=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y # CONFIG_I2C_CHARDEV is not set - -# -# I2C Algorithms -# CONFIG_I2C_ALGOBIT=y -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPCA is not set # # I2C Hardware Bus support @@ -780,6 +777,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIA is not set # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_PLATFORM is not set # # Miscellaneous I2C Chip support @@ -1026,6 +1024,7 @@ CONFIG_SND_ALI5451=m # CONFIG_SND_AU8810 is not set # CONFIG_SND_AU8820 is not set # CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set # CONFIG_SND_AZT3328 is not set # CONFIG_SND_BT87X is not set # CONFIG_SND_CA0106 is not set @@ -1096,10 +1095,6 @@ CONFIG_SND_SUN_CS4231=m # # CONFIG_SND_SOC is not set -# -# SoC Audio support for SuperH -# - # # ALSA SoC audio for Freescale SOCs # diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 63c6ae0dd273..029558222c8f 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -20,12 +20,12 @@ obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o \ pci_sun4v.o pci_sun4v_asm.o pci_fire.o obj-$(CONFIG_PCI_MSI) += pci_msi.o obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o -obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o +obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o obj-$(CONFIG_AUDIT) += audit.o -obj-$(CONFIG_AUDIT)$(CONFIG_SPARC32_COMPAT) += compat_audit.o +obj-$(CONFIG_AUDIT)$(CONFIG_COMPAT) += compat_audit.o obj-y += $(obj-yy) diff --git a/arch/sparc64/kernel/audit.c b/arch/sparc64/kernel/audit.c index 24d7f4b4178a..8fff0ac63d56 100644 --- a/arch/sparc64/kernel/audit.c +++ b/arch/sparc64/kernel/audit.c @@ -30,7 +30,7 @@ static unsigned signal_class[] = { int audit_classify_arch(int arch) { -#ifdef CONFIG_SPARC32_COMPAT +#ifdef CONFIG_COMPAT if (arch == AUDIT_ARCH_SPARC) return 1; #endif @@ -39,7 +39,7 @@ int audit_classify_arch(int arch) int audit_classify_syscall(int abi, unsigned syscall) { -#ifdef CONFIG_SPARC32_COMPAT +#ifdef CONFIG_COMPAT extern int sparc32_classify_syscall(unsigned); if (abi == AUDIT_ARCH_SPARC) return sparc32_classify_syscall(syscall); @@ -60,7 +60,7 @@ int audit_classify_syscall(int abi, unsigned syscall) static int __init audit_classes_init(void) { -#ifdef CONFIG_SPARC32_COMPAT +#ifdef CONFIG_COMPAT extern __u32 sparc32_dir_class[]; extern __u32 sparc32_write_class[]; extern __u32 sparc32_read_class[]; diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 77a3e8592cbc..6afa5ef536eb 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -8,7 +8,7 @@ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ -#ifdef CONFIG_SPARC32_COMPAT +#ifdef CONFIG_COMPAT #include /* for compat_old_sigset_t */ #endif #include @@ -531,7 +531,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) else oldset = ¤t->blocked; -#ifdef CONFIG_SPARC32_COMPAT +#ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) { extern void do_signal32(sigset_t *, struct pt_regs *, struct signal_deliver_cookie *); diff --git a/init/Kconfig b/init/Kconfig index ba3a389fab94..f1f22db74d5a 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -521,7 +521,7 @@ menuconfig EMBEDDED config UID16 bool "Enable 16-bit UID system calls" if EMBEDDED - depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION) + depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION) default y help This enables the legacy 16-bit UID syscall wrappers. -- cgit v1.2.3 From dc8ca2a111c10f031346f6f8f82640d6bc0dd347 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 26 Apr 2008 20:59:52 -0700 Subject: sparc64: Do not ignore 'pmu' device ranges. I must have disabled this due to other bugs which were fixed over time. And this is needed in order for child devices of "pmu" to get proper resource values. Signed-off-by: David S. Miller --- arch/sparc64/kernel/of_device.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 9e58e8cba1c3..d569f60c24b8 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -412,12 +412,6 @@ static int __init build_one_resource(struct device_node *parent, static int __init use_1to1_mapping(struct device_node *pp) { - /* If this is on the PMU bus, don't try to translate it even - * if a ranges property exists. - */ - if (!strcmp(pp->name, "pmu")) - return 1; - /* If we have a ranges property in the parent, use it. */ if (of_find_property(pp, "ranges", NULL) != NULL) return 0; -- cgit v1.2.3 From 5da496e4b90626784a82803682e186a8e67222a0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 26 Apr 2008 21:07:35 -0700 Subject: sparc64: Kill unused local ISA bus layer. No more drivers use this, and therefore it can die. Signed-off-by: David S. Miller --- arch/sparc64/kernel/Makefile | 2 +- arch/sparc64/kernel/isa.c | 191 ------------------------------------ arch/sparc64/kernel/pci.c | 2 - arch/sparc64/kernel/sparc64_ksyms.c | 2 - include/asm-sparc64/floppy.h | 1 - include/asm-sparc64/isa.h | 47 --------- 6 files changed, 1 insertion(+), 244 deletions(-) delete mode 100644 arch/sparc64/kernel/isa.c delete mode 100644 include/asm-sparc64/isa.h (limited to 'arch') diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 029558222c8f..2bd0340b743d 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -15,7 +15,7 @@ obj-y := process.o setup.o cpu.o idprom.o \ visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o \ +obj-$(CONFIG_PCI) += ebus.o pci_common.o \ pci_psycho.o pci_sabre.o pci_schizo.o \ pci_sun4v.o pci_sun4v_asm.o pci_fire.o obj-$(CONFIG_PCI_MSI) += pci_msi.o diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c deleted file mode 100644 index a2af5ed784c9..000000000000 --- a/arch/sparc64/kernel/isa.c +++ /dev/null @@ -1,191 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -struct sparc_isa_bridge *isa_chain; - -static void __init fatal_err(const char *reason) -{ - prom_printf("ISA: fatal error, %s.\n", reason); -} - -static void __init report_dev(struct sparc_isa_device *isa_dev, int child) -{ - if (child) - printk(" (%s)", isa_dev->prom_node->name); - else - printk(" [%s", isa_dev->prom_node->name); -} - -static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev) -{ - struct of_device *op = of_find_device_by_node(isa_dev->prom_node); - - memcpy(&isa_dev->resource, &op->resource[0], sizeof(struct resource)); -} - -static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev) -{ - struct of_device *op = of_find_device_by_node(isa_dev->prom_node); - - if (!op || !op->num_irqs) { - isa_dev->irq = PCI_IRQ_NONE; - } else { - isa_dev->irq = op->irqs[0]; - } -} - -static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev) -{ - struct device_node *dp = parent_isa_dev->prom_node->child; - - if (!dp) - return; - - printk(" ->"); - while (dp) { - struct sparc_isa_device *isa_dev; - - isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL); - if (!isa_dev) { - fatal_err("cannot allocate child isa_dev"); - prom_halt(); - } - - /* Link it in to parent. */ - isa_dev->next = parent_isa_dev->child; - parent_isa_dev->child = isa_dev; - - isa_dev->bus = parent_isa_dev->bus; - isa_dev->prom_node = dp; - - isa_dev_get_resource(isa_dev); - isa_dev_get_irq(isa_dev); - - report_dev(isa_dev, 1); - - dp = dp->sibling; - } -} - -static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) -{ - struct device_node *dp = isa_br->prom_node->child; - - while (dp) { - struct sparc_isa_device *isa_dev; - struct dev_archdata *sd; - - isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL); - if (!isa_dev) { - printk(KERN_DEBUG "ISA: cannot allocate isa_dev"); - return; - } - - sd = &isa_dev->ofdev.dev.archdata; - sd->prom_node = dp; - 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; - isa_dev->ofdev.dev.bus = &isa_bus_type; - sprintf(isa_dev->ofdev.dev.bus_id, "isa[%08x]", dp->node); - - /* Register with core */ - if (of_device_register(&isa_dev->ofdev) != 0) { - printk(KERN_DEBUG "isa: device registration error for %s!\n", - dp->path_component_name); - kfree(isa_dev); - goto next_sibling; - } - - /* Link it in. */ - isa_dev->next = NULL; - if (isa_br->devices == NULL) { - isa_br->devices = isa_dev; - } else { - struct sparc_isa_device *tmp = isa_br->devices; - - while (tmp->next) - tmp = tmp->next; - - tmp->next = isa_dev; - } - - isa_dev->bus = isa_br; - isa_dev->prom_node = dp; - - isa_dev_get_resource(isa_dev); - isa_dev_get_irq(isa_dev); - - report_dev(isa_dev, 0); - - isa_fill_children(isa_dev); - - printk("]"); - - next_sibling: - dp = dp->sibling; - } -} - -void __init isa_init(void) -{ - struct pci_dev *pdev; - unsigned short vendor, device; - int index = 0; - - vendor = PCI_VENDOR_ID_AL; - device = PCI_DEVICE_ID_AL_M1533; - - pdev = NULL; - while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) { - struct sparc_isa_bridge *isa_br; - struct device_node *dp; - - dp = pci_device_to_OF_node(pdev); - - isa_br = kzalloc(sizeof(*isa_br), GFP_KERNEL); - if (!isa_br) { - printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge"); - pci_dev_put(pdev); - return; - } - - isa_br->ofdev.node = dp; - isa_br->ofdev.dev.parent = &pdev->dev; - isa_br->ofdev.dev.bus = &isa_bus_type; - sprintf(isa_br->ofdev.dev.bus_id, "isa%d", index); - - /* Register with core */ - if (of_device_register(&isa_br->ofdev) != 0) { - printk(KERN_DEBUG "isa: device registration error for %s!\n", - dp->path_component_name); - kfree(isa_br); - pci_dev_put(pdev); - return; - } - - /* Link it in. */ - isa_br->next = isa_chain; - isa_chain = isa_br; - - isa_br->self = pdev; - isa_br->index = index++; - isa_br->prom_node = dp; - - printk("isa%d:", isa_br->index); - - isa_fill_devices(isa_br); - - printk("\n"); - } -} diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 49f912766519..dbf2fc2f4d87 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -885,7 +884,6 @@ static int __init pcibios_init(void) pci_scan_each_controller_bus(); - isa_init(); ebus_init(); power_init(); diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 66336590e830..8ac0b99f2c55 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -49,7 +49,6 @@ #endif #ifdef CONFIG_PCI #include -#include #endif #include #include @@ -187,7 +186,6 @@ EXPORT_SYMBOL(insw); EXPORT_SYMBOL(insl); #ifdef CONFIG_PCI EXPORT_SYMBOL(ebus_chain); -EXPORT_SYMBOL(isa_chain); EXPORT_SYMBOL(pci_alloc_consistent); EXPORT_SYMBOL(pci_free_consistent); EXPORT_SYMBOL(pci_map_single); diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h index 040d7962c5a3..ca19f80a9b7d 100644 --- a/include/asm-sparc64/floppy.h +++ b/include/asm-sparc64/floppy.h @@ -293,7 +293,6 @@ static int sun_fd_eject(int drive) #ifdef CONFIG_PCI #include -#include #include static struct ebus_dma_info sun_pci_fd_ebus_dma; diff --git a/include/asm-sparc64/isa.h b/include/asm-sparc64/isa.h deleted file mode 100644 index ecd9290f78d4..000000000000 --- a/include/asm-sparc64/isa.h +++ /dev/null @@ -1,47 +0,0 @@ -/* $Id: isa.h,v 1.1 2001/05/11 04:31:55 davem Exp $ - * isa.h: Sparc64 layer for PCI to ISA bridge devices. - * - * Copyright (C) 2001 David S. Miller (davem@redhat.com) - */ - -#ifndef __SPARC64_ISA_H -#define __SPARC64_ISA_H - -#include -#include -#include - -struct sparc_isa_bridge; - -struct sparc_isa_device { - struct of_device ofdev; - struct sparc_isa_device *next; - struct sparc_isa_device *child; - struct sparc_isa_bridge *bus; - struct device_node *prom_node; - struct resource resource; - unsigned int irq; -}; -#define to_isa_device(d) container_of(d, struct sparc_isa_device, ofdev.dev) - -struct sparc_isa_bridge { - struct of_device ofdev; - struct sparc_isa_bridge *next; - struct sparc_isa_device *devices; - struct pci_dev *self; - int index; - struct device_node *prom_node; -}; -#define to_isa_bridge(d) container_of(d, struct sparc_isa_bridge, ofdev.dev) - -extern struct sparc_isa_bridge *isa_chain; - -extern void isa_init(void); - -#define for_each_isa(bus) \ - for((bus) = isa_chain; (bus); (bus) = (bus)->next) - -#define for_each_isadev(dev, bus) \ - for((dev) = (bus)->devices; (dev); (dev) = (dev)->next) - -#endif /* !(__SPARC64_ISA_H) */ -- cgit v1.2.3 From 7cf069955f2f0b95fed6a8b1a61ef598a3df0f4e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 27 Apr 2008 00:25:30 -0700 Subject: sparc64: Kill bogus RT_ALIGNEDSZ macro from signal.c The structure has to be 8-byte aligned in size, so this macro is just noise. Signed-off-by: David S. Miller --- arch/sparc64/kernel/signal.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 6afa5ef536eb..314f51aefa0f 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -236,9 +236,6 @@ struct rt_signal_frame { __siginfo_fpu_t fpu_state; }; -/* Align macros */ -#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) - static long _sigpause_common(old_sigset_t set) { set &= _BLOCKABLE; @@ -400,7 +397,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, synchronize_user_stack(); save_and_clear_fpu(); - sigframe_size = RT_ALIGNEDSZ; + sigframe_size = sizeof(struct rt_signal_frame); if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) sigframe_size -= sizeof(__siginfo_fpu_t); -- cgit v1.2.3 From 5526b7e4513c66bc1c91f661dcd518d5199f8934 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 27 Apr 2008 02:26:36 -0700 Subject: sparc: Remove old style signal frame support. Back around the same time we were bootstrapping the first 32-bit sparc Linux kernel with a SunOS userland, we made the signal frame match that of SunOS. By the time we even started putting together a native Linux userland for 32-bit Sparc we realized this layout wasn't sufficient for Linux's needs. Therefore we changed the layout, yet kept support for the old style signal frame layout in there. The detection mechanism is that we had sys_sigaction() start passing in a negative signal number to indicate "new style signal frames please". Anyways, no binaries exist in the world that use the old stuff. In fact, I bet Jakub Jelinek and myself are the only two people who ever had such binaries to be honest. So let's get rid of this stuff. I added an assertion using WARN_ON_ONCE() that makes sure 32-bit applications are passing in that negative signal number still. Signed-off-by: David S. Miller --- arch/sparc/kernel/process.c | 2 - arch/sparc/kernel/signal.c | 260 +++--------------------------------- arch/sparc/kernel/sys_sparc.c | 14 +- arch/sparc64/kernel/process.c | 6 +- arch/sparc64/kernel/signal32.c | 272 +++----------------------------------- arch/sparc64/kernel/sys_sparc32.c | 11 +- include/asm-sparc/processor.h | 4 +- include/asm-sparc64/thread_info.h | 6 +- 8 files changed, 47 insertions(+), 528 deletions(-) (limited to 'arch') diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 70c0dd22491d..e7f35198ae34 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -357,8 +357,6 @@ void flush_thread(void) { current_thread_info()->w_saved = 0; - /* No new signal delivery by default */ - current->thread.new_signal = 0; #ifndef CONFIG_SMP if(last_task_used_math == current) { #else diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 3e849e8e3480..3c312290c3c2 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -1,5 +1,4 @@ -/* $Id: signal.c,v 1.110 2002/02/08 03:57:14 davem Exp $ - * linux/arch/sparc/kernel/signal.c +/* linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -32,37 +31,7 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, void *fpqueue, unsigned long *fpqdepth); extern void fpload(unsigned long *fpregs, unsigned long *fsr); -/* Signal frames: the original one (compatible with SunOS): - * - * Set up a signal frame... Make the stack look the way SunOS - * expects it to look which is basically: - * - * ---------------------------------- <-- %sp at signal time - * Struct sigcontext - * Signal address - * Ptr to sigcontext area above - * Signal code - * The signal number itself - * One register window - * ---------------------------------- <-- New %sp - */ -struct signal_sframe { - struct reg_window sig_window; - int sig_num; - int sig_code; - struct sigcontext __user *sig_scptr; - int sig_address; - struct sigcontext sig_context; - unsigned int extramask[_NSIG_WORDS - 1]; -}; - -/* - * And the new one, intended to be used for Linux applications only - * (we have enough in there to work with clone). - * All the interesting bits are in the info field. - */ - -struct new_signal_frame { +struct signal_frame { struct sparc_stackf ss; __siginfo_t info; __siginfo_fpu_t __user *fpu_save; @@ -85,8 +54,7 @@ struct rt_signal_frame { }; /* Align macros */ -#define SF_ALIGNEDSZ (((sizeof(struct signal_sframe) + 7) & (~7))) -#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7))) +#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7))) #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) static int _sigpause_common(old_sigset_t set) @@ -141,15 +109,20 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) return err; } -static inline void do_new_sigreturn (struct pt_regs *regs) +asmlinkage void do_sigreturn(struct pt_regs *regs) { - struct new_signal_frame __user *sf; + struct signal_frame __user *sf; unsigned long up_psr, pc, npc; sigset_t set; __siginfo_fpu_t __user *fpu_save; int err; - sf = (struct new_signal_frame __user *) regs->u_regs[UREG_FP]; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + + synchronize_user_stack(); + + sf = (struct signal_frame __user *) regs->u_regs[UREG_FP]; /* 1. Make sure we are not getting garbage from the user */ if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) @@ -198,73 +171,6 @@ segv_and_exit: force_sig(SIGSEGV, current); } -asmlinkage void do_sigreturn(struct pt_regs *regs) -{ - struct sigcontext __user *scptr; - unsigned long pc, npc, psr; - sigset_t set; - int err; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - synchronize_user_stack(); - - if (current->thread.new_signal) { - do_new_sigreturn(regs); - return; - } - - scptr = (struct sigcontext __user *) regs->u_regs[UREG_I0]; - - /* Check sanity of the user arg. */ - if (!access_ok(VERIFY_READ, scptr, sizeof(struct sigcontext)) || - (((unsigned long) scptr) & 3)) - goto segv_and_exit; - - err = __get_user(pc, &scptr->sigc_pc); - err |= __get_user(npc, &scptr->sigc_npc); - - if ((pc | npc) & 3) - goto segv_and_exit; - - /* This is pretty much atomic, no amount locking would prevent - * the races which exist anyways. - */ - err |= __get_user(set.sig[0], &scptr->sigc_mask); - /* Note that scptr + 1 points to extramask */ - err |= __copy_from_user(&set.sig[1], scptr + 1, - (_NSIG_WORDS - 1) * sizeof(unsigned int)); - - if (err) - goto segv_and_exit; - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->pc = pc; - regs->npc = npc; - - err = __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp); - err |= __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0); - err |= __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1); - - /* User can only change condition codes in %psr. */ - err |= __get_user(psr, &scptr->sigc_psr); - if (err) - goto segv_and_exit; - - regs->psr &= ~(PSR_ICC); - regs->psr |= (psr & PSR_ICC); - return; - -segv_and_exit: - force_sig(SIGSEGV, current); -} - asmlinkage void do_rt_sigreturn(struct pt_regs *regs) { struct rt_signal_frame __user *sf; @@ -351,128 +257,6 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re return (void __user *)(sp - framesize); } -static inline void -setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info) -{ - struct signal_sframe __user *sframep; - struct sigcontext __user *sc; - int window = 0, err; - unsigned long pc = regs->pc; - unsigned long npc = regs->npc; - struct thread_info *tp = current_thread_info(); - void __user *sig_address; - int sig_code; - - synchronize_user_stack(); - sframep = (struct signal_sframe __user *) - get_sigframe(sa, regs, SF_ALIGNEDSZ); - if (invalid_frame_pointer(sframep, sizeof(*sframep))){ - /* Don't change signal code and address, so that - * post mortem debuggers can have a look. - */ - goto sigill_and_return; - } - - sc = &sframep->sig_context; - - /* We've already made sure frame pointer isn't in kernel space... */ - err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), - &sc->sigc_onstack); - err |= __put_user(oldset->sig[0], &sc->sigc_mask); - err |= __copy_to_user(sframep->extramask, &oldset->sig[1], - (_NSIG_WORDS - 1) * sizeof(unsigned int)); - err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); - err |= __put_user(pc, &sc->sigc_pc); - err |= __put_user(npc, &sc->sigc_npc); - err |= __put_user(regs->psr, &sc->sigc_psr); - err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); - err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); - err |= __put_user(tp->w_saved, &sc->sigc_oswins); - if (tp->w_saved) - for (window = 0; window < tp->w_saved; window++) { - put_user((char *)tp->rwbuf_stkptrs[window], - &sc->sigc_spbuf[window]); - err |= __copy_to_user(&sc->sigc_wbuf[window], - &tp->reg_window[window], - sizeof(struct reg_window)); - } - else - err |= __copy_to_user(sframep, (char *) regs->u_regs[UREG_FP], - sizeof(struct reg_window)); - - tp->w_saved = 0; /* So process is allowed to execute. */ - - err |= __put_user(signr, &sframep->sig_num); - sig_address = NULL; - sig_code = 0; - if (SI_FROMKERNEL (info) && (info->si_code & __SI_MASK) == __SI_FAULT) { - sig_address = info->si_addr; - switch (signr) { - case SIGSEGV: - switch (info->si_code) { - case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break; - default: sig_code = SUBSIG_PROTECTION; break; - } - break; - case SIGILL: - switch (info->si_code) { - case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break; - case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break; - case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP(info->si_trapno); break; - default: sig_code = SUBSIG_STACK; break; - } - break; - case SIGFPE: - switch (info->si_code) { - case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break; - case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break; - case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break; - case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break; - case FPE_FLTUND: sig_code = SUBSIG_FPUNFLOW; break; - case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break; - case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break; - default: sig_code = SUBSIG_FPERROR; break; - } - break; - case SIGBUS: - switch (info->si_code) { - case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break; - case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break; - default: sig_code = SUBSIG_BUSTIMEOUT; break; - } - break; - case SIGEMT: - switch (info->si_code) { - case EMT_TAGOVF: sig_code = SUBSIG_TAG; break; - } - break; - case SIGSYS: - if (info->si_code == (__SI_FAULT|0x100)) { - sig_code = info->si_trapno; - break; - } - default: - sig_address = NULL; - } - } - err |= __put_user((unsigned long)sig_address, &sframep->sig_address); - err |= __put_user(sig_code, &sframep->sig_code); - err |= __put_user(sc, &sframep->sig_scptr); - if (err) - goto sigsegv; - - regs->u_regs[UREG_FP] = (unsigned long) sframep; - regs->pc = (unsigned long) sa->sa_handler; - regs->npc = (regs->pc + 4); - return; - -sigill_and_return: - do_exit(SIGILL); -sigsegv: - force_sigsegv(signr, current); -} - - static inline int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) { @@ -508,21 +292,20 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) return err; } -static inline void -new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset) +static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset) { - struct new_signal_frame __user *sf; + struct signal_frame __user *sf; int sigframe_size, err; /* 1. Make sure everything is clean */ synchronize_user_stack(); - sigframe_size = NF_ALIGNEDSZ; + sigframe_size = SF_ALIGNEDSZ; if (!used_math()) sigframe_size -= sizeof(__siginfo_fpu_t); - sf = (struct new_signal_frame __user *) + sf = (struct signal_frame __user *) get_sigframe(&ka->sa, regs, sigframe_size); if (invalid_frame_pointer(sf, sigframe_size)) @@ -586,9 +369,8 @@ sigsegv: force_sigsegv(signo, current); } -static inline void -new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset, siginfo_t *info) +static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset, siginfo_t *info) { struct rt_signal_frame __user *sf; int sigframe_size; @@ -674,11 +456,9 @@ handle_signal(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { if (ka->sa.sa_flags & SA_SIGINFO) - new_setup_rt_frame(ka, regs, signr, oldset, info); - else if (current->thread.new_signal) - new_setup_frame(ka, regs, signr, oldset); + setup_rt_frame(ka, regs, signr, oldset, info); else - setup_frame(&ka->sa, regs, signr, oldset, info); + setup_frame(ka, regs, signr, oldset); spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index 42bf09db9a81..f188b5dc9fd0 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c @@ -1,5 +1,4 @@ -/* $Id: sys_sparc.c,v 1.70 2001/04/14 01:12:02 davem Exp $ - * linux/arch/sparc/kernel/sys_sparc.c +/* linux/arch/sparc/kernel/sys_sparc.c * * This file contains various random system calls that * have a non-standard calling sequence on the Linux/sparc @@ -395,10 +394,8 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act, struct k_sigaction new_ka, old_ka; int ret; - if (sig < 0) { - current->thread.new_signal = 1; - sig = -sig; - } + WARN_ON_ONCE(sig >= 0); + sig = -sig; if (act) { unsigned long mask; @@ -446,11 +443,6 @@ sys_rt_sigaction(int sig, if (sigsetsize != sizeof(sigset_t)) return -EINVAL; - /* All tasks which use RT signals (effectively) use - * new style signals. - */ - current->thread.new_signal = 1; - if (act) { new_ka.ka_restorer = restorer; if (copy_from_user(&new_ka.sa, act, sizeof(*act))) diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index acf8c5250aa9..500ac6d483a0 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -1,5 +1,4 @@ -/* $Id: process.c,v 1.131 2002/02/09 19:49:30 davem Exp $ - * arch/sparc64/kernel/process.c +/* arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) @@ -368,9 +367,6 @@ void flush_thread(void) if (get_thread_current_ds() != ASI_AIUS) set_fs(USER_DS); - - /* Init new signal delivery disposition. */ - clear_thread_flag(TIF_NEWSIGNALS); } /* It's a bit more tricky when 64-bit tasks are involved... */ diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 43cdec64d9c9..91f8d0826db1 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -1,5 +1,4 @@ -/* $Id: signal32.c,v 1.74 2002/02/09 19:49:30 davem Exp $ - * arch/sparc64/kernel/signal32.c +/* arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -31,30 +30,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -/* Signal frames: the original one (compatible with SunOS): - * - * Set up a signal frame... Make the stack look the way SunOS - * expects it to look which is basically: - * - * ---------------------------------- <-- %sp at signal time - * Struct sigcontext - * Signal address - * Ptr to sigcontext area above - * Signal code - * The signal number itself - * One register window - * ---------------------------------- <-- New %sp - */ -struct signal_sframe32 { - struct reg_window32 sig_window; - int sig_num; - int sig_code; - /* struct sigcontext32 * */ u32 sig_scptr; - int sig_address; - struct sigcontext32 sig_context; - unsigned int extramask[_COMPAT_NSIG_WORDS - 1]; -}; - /* This magic should be in g_upper[0] for all upper parts * to be valid. */ @@ -65,12 +40,7 @@ typedef struct { unsigned int asi; } siginfo_extra_v8plus_t; -/* - * And the new one, intended to be used for Linux applications only - * (we have enough in there to work with clone). - * All the interesting bits are in the info field. - */ -struct new_signal_frame32 { +struct signal_frame32 { struct sparc_stackf32 ss; __siginfo32_t info; /* __siginfo_fpu32_t * */ u32 fpu_save; @@ -149,8 +119,7 @@ struct rt_signal_frame32 { }; /* Align macros */ -#define SF_ALIGNEDSZ (((sizeof(struct signal_sframe32) + 7) & (~7))) -#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7))) +#define SF_ALIGNEDSZ (((sizeof(struct signal_frame32) + 7) & (~7))) #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7))) int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) @@ -241,17 +210,22 @@ static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu return err; } -void do_new_sigreturn32(struct pt_regs *regs) +void do_sigreturn32(struct pt_regs *regs) { - struct new_signal_frame32 __user *sf; + struct signal_frame32 __user *sf; unsigned int psr; unsigned pc, npc, fpu_save; sigset_t set; unsigned seta[_COMPAT_NSIG_WORDS]; int err, i; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + + synchronize_user_stack(); + regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; - sf = (struct new_signal_frame32 __user *) regs->u_regs[UREG_FP]; + sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP]; /* 1. Make sure we are not getting garbage from the user */ if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) || @@ -319,76 +293,6 @@ segv: force_sig(SIGSEGV, current); } -asmlinkage void do_sigreturn32(struct pt_regs *regs) -{ - struct sigcontext32 __user *scptr; - unsigned int pc, npc, psr; - sigset_t set; - unsigned int seta[_COMPAT_NSIG_WORDS]; - int err; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - synchronize_user_stack(); - if (test_thread_flag(TIF_NEWSIGNALS)) { - do_new_sigreturn32(regs); - return; - } - - scptr = (struct sigcontext32 __user *) - (regs->u_regs[UREG_I0] & 0x00000000ffffffffUL); - /* Check sanity of the user arg. */ - if (!access_ok(VERIFY_READ, scptr, sizeof(struct sigcontext32)) || - (((unsigned long) scptr) & 3)) - goto segv; - - err = __get_user(pc, &scptr->sigc_pc); - err |= __get_user(npc, &scptr->sigc_npc); - - if ((pc | npc) & 3) - goto segv; /* Nice try. */ - - err |= __get_user(seta[0], &scptr->sigc_mask); - /* Note that scptr + 1 points to extramask */ - err |= copy_from_user(seta+1, scptr + 1, - (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); - if (err) - goto segv; - switch (_NSIG_WORDS) { - case 4: set.sig[3] = seta[6] + (((long)seta[7]) << 32); - case 3: set.sig[2] = seta[4] + (((long)seta[5]) << 32); - case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32); - case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32); - } - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (test_thread_flag(TIF_32BIT)) { - pc &= 0xffffffff; - npc &= 0xffffffff; - } - regs->tpc = pc; - regs->tnpc = npc; - err = __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp); - err |= __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0); - err |= __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1); - - /* User can only change condition codes in %tstate. */ - err |= __get_user(psr, &scptr->sigc_psr); - if (err) - goto segv; - regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC); - regs->tstate |= psr_to_tstate_icc(psr); - return; - -segv: - force_sig(SIGSEGV, current); -} - asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) { struct rt_signal_frame32 __user *sf; @@ -504,145 +408,6 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns return (void __user *)(sp - framesize); } -static void -setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info) -{ - struct signal_sframe32 __user *sframep; - struct sigcontext32 __user *sc; - unsigned int seta[_COMPAT_NSIG_WORDS]; - int err = 0; - void __user *sig_address; - int sig_code; - unsigned long pc = regs->tpc; - unsigned long npc = regs->tnpc; - unsigned int psr; - - if (test_thread_flag(TIF_32BIT)) { - pc &= 0xffffffff; - npc &= 0xffffffff; - } - - synchronize_user_stack(); - save_and_clear_fpu(); - - sframep = (struct signal_sframe32 __user *) - get_sigframe(sa, regs, SF_ALIGNEDSZ); - if (invalid_frame_pointer(sframep, sizeof(*sframep))){ - /* Don't change signal code and address, so that - * post mortem debuggers can have a look. - */ - do_exit(SIGILL); - } - - sc = &sframep->sig_context; - - /* We've already made sure frame pointer isn't in kernel space... */ - err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), - &sc->sigc_onstack); - - switch (_NSIG_WORDS) { - case 4: seta[7] = (oldset->sig[3] >> 32); - seta[6] = oldset->sig[3]; - case 3: seta[5] = (oldset->sig[2] >> 32); - seta[4] = oldset->sig[2]; - case 2: seta[3] = (oldset->sig[1] >> 32); - seta[2] = oldset->sig[1]; - case 1: seta[1] = (oldset->sig[0] >> 32); - seta[0] = oldset->sig[0]; - } - err |= __put_user(seta[0], &sc->sigc_mask); - err |= __copy_to_user(sframep->extramask, seta + 1, - (_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int)); - err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); - err |= __put_user(pc, &sc->sigc_pc); - err |= __put_user(npc, &sc->sigc_npc); - psr = tstate_to_psr(regs->tstate); - if (current_thread_info()->fpsaved[0] & FPRS_FEF) - psr |= PSR_EF; - err |= __put_user(psr, &sc->sigc_psr); - err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); - err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); - err |= __put_user(get_thread_wsaved(), &sc->sigc_oswins); - - err |= copy_in_user((u32 __user *)sframep, - (u32 __user *)(regs->u_regs[UREG_FP]), - sizeof(struct reg_window32)); - - set_thread_wsaved(0); /* So process is allowed to execute. */ - err |= __put_user(signr, &sframep->sig_num); - sig_address = NULL; - sig_code = 0; - if (SI_FROMKERNEL (info) && (info->si_code & __SI_MASK) == __SI_FAULT) { - sig_address = info->si_addr; - switch (signr) { - case SIGSEGV: - switch (info->si_code) { - case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break; - default: sig_code = SUBSIG_PROTECTION; break; - } - break; - case SIGILL: - switch (info->si_code) { - case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break; - case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break; - case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP(info->si_trapno); break; - default: sig_code = SUBSIG_STACK; break; - } - break; - case SIGFPE: - switch (info->si_code) { - case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break; - case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break; - case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break; - case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break; - case FPE_FLTUND: sig_code = SUBSIG_FPUNFLOW; break; - case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break; - case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break; - default: sig_code = SUBSIG_FPERROR; break; - } - break; - case SIGBUS: - switch (info->si_code) { - case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break; - case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break; - default: sig_code = SUBSIG_BUSTIMEOUT; break; - } - break; - case SIGEMT: - switch (info->si_code) { - case EMT_TAGOVF: sig_code = SUBSIG_TAG; break; - } - break; - case SIGSYS: - if (info->si_code == (__SI_FAULT|0x100)) { - /* See sys_sunos32.c */ - sig_code = info->si_trapno; - break; - } - default: - sig_address = NULL; - } - } - err |= __put_user(ptr_to_compat(sig_address), &sframep->sig_address); - err |= __put_user(sig_code, &sframep->sig_code); - err |= __put_user(ptr_to_compat(sc), &sframep->sig_scptr); - if (err) - goto sigsegv; - - regs->u_regs[UREG_FP] = (unsigned long) sframep; - regs->tpc = (unsigned long) sa->sa_handler; - regs->tnpc = (regs->tpc + 4); - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - return; - -sigsegv: - force_sigsegv(signr, current); -} - - static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) { unsigned long *fpregs = current_thread_info()->fpregs; @@ -663,10 +428,10 @@ static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) return err; } -static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset) +static void setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset) { - struct new_signal_frame32 __user *sf; + struct signal_frame32 __user *sf; int sigframe_size; u32 psr; int i, err; @@ -676,11 +441,11 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, synchronize_user_stack(); save_and_clear_fpu(); - sigframe_size = NF_ALIGNEDSZ; + sigframe_size = SF_ALIGNEDSZ; if (!(current_thread_info()->fpsaved[0] & FPRS_FEF)) sigframe_size -= sizeof(__siginfo_fpu_t); - sf = (struct new_signal_frame32 __user *) + sf = (struct signal_frame32 __user *) get_sigframe(&ka->sa, regs, sigframe_size); if (invalid_frame_pointer(sf, sigframe_size)) @@ -944,10 +709,9 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, { if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame32(ka, regs, signr, oldset, info); - else if (test_thread_flag(TIF_NEWSIGNALS)) - new_setup_frame32(ka, regs, signr, oldset); else - setup_frame32(&ka->sa, regs, signr, oldset, info); + setup_frame32(ka, regs, signr, oldset); + spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NOMASK)) diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index c1a61e98899a..161ce4710fe7 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -554,10 +554,8 @@ asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act struct k_sigaction new_ka, old_ka; int ret; - if (sig < 0) { - set_thread_flag(TIF_NEWSIGNALS); - sig = -sig; - } + WARN_ON_ONCE(sig >= 0); + sig = -sig; if (act) { compat_old_sigset_t mask; @@ -601,11 +599,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig, if (sigsetsize != sizeof(compat_sigset_t)) return -EINVAL; - /* All tasks which use RT signals (effectively) use - * new style signals. - */ - set_thread_flag(TIF_NEWSIGNALS); - if (act) { u32 u_handler, u_restorer; diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h index e3006979709b..8898efbbbe07 100644 --- a/include/asm-sparc/processor.h +++ b/include/asm-sparc/processor.h @@ -1,5 +1,4 @@ -/* $Id: processor.h,v 1.83 2001/10/08 09:32:13 davem Exp $ - * include/asm-sparc/processor.h +/* include/asm-sparc/processor.h * * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu) */ @@ -65,7 +64,6 @@ struct thread_struct { struct fpq fpqueue[16]; unsigned long flags; mm_segment_t current_ds; - int new_signal; }; #define SPARC_FLAG_KTHREAD 0x1 /* task is a kernel thread */ diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h index 98252cd44dd6..71e42d1a80d9 100644 --- a/include/asm-sparc64/thread_info.h +++ b/include/asm-sparc64/thread_info.h @@ -1,5 +1,4 @@ -/* $Id: thread_info.h,v 1.1 2002/02/10 00:00:58 davem Exp $ - * thread_info.h: sparc64 low-level thread information +/* thread_info.h: sparc64 low-level thread information * * Copyright (C) 2002 David S. Miller (davem@redhat.com) */ @@ -223,7 +222,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_PERFCTR 4 /* performance counters active */ #define TIF_UNALIGNED 5 /* allowed to do unaligned accesses */ -#define TIF_NEWSIGNALS 6 /* wants new-style signals */ +/* flag bit 6 is available */ #define TIF_32BIT 7 /* 32-bit binary */ /* flag bit 8 is available */ #define TIF_SECCOMP 9 /* secure computing */ @@ -242,7 +241,6 @@ register struct thread_info *current_thread_info_reg asm("g6"); #define _TIF_NEED_RESCHED (1< Date: Sun, 27 Apr 2008 14:52:51 -0700 Subject: sparc64: Clean up handling of pt_regs trap type encoding. If we use this from more than one place, it's better to have helpers instead of twiddling magic constants all over. Add pt_regs_trap_type(), pt_regs_clear_trap_type(), and pt_regs_is_syscall(). Use them in do_signal(). Signed-off-by: David S. Miller --- arch/sparc64/kernel/signal.c | 7 +++---- include/asm-sparc64/ptrace.h | 23 ++++++++++++++++++++++- 2 files changed, 25 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 314f51aefa0f..f2d88d8f7a42 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -513,11 +513,10 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) struct k_sigaction ka; sigset_t *oldset; siginfo_t info; - int signr, tt; + int signr; - tt = regs->magic & 0x1ff; - if (tt == 0x110 || tt == 0x111 || tt == 0x16d) { - regs->magic &= ~0x1ff; + if (pt_regs_is_syscall(regs)) { + pt_regs_clear_trap_type(regs); cookie.restart_syscall = 1; } else cookie.restart_syscall = 0; diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h index b4b951d570bb..714b81956f32 100644 --- a/include/asm-sparc64/ptrace.h +++ b/include/asm-sparc64/ptrace.h @@ -1,4 +1,3 @@ -/* $Id: ptrace.h,v 1.14 2002/02/09 19:49:32 davem Exp $ */ #ifndef _SPARC64_PTRACE_H #define _SPARC64_PTRACE_H @@ -8,10 +7,15 @@ * stack during a system call and basically all traps. */ +/* This magic value must have the low 9 bits clear, + * as that is where we encode the %tt value, see below. + */ #define PT_REGS_MAGIC 0x57ac6c00 #ifndef __ASSEMBLY__ +#include + struct pt_regs { unsigned long u_regs[16]; /* globals and ins */ unsigned long tstate; @@ -33,6 +37,23 @@ struct pt_regs { unsigned int magic; }; +static inline int pt_regs_trap_type(struct pt_regs *regs) +{ + return regs->magic & 0x1ff; +} + +static inline int pt_regs_clear_trap_type(struct pt_regs *regs) +{ + return regs->magic &= ~0x1ff; +} + +static inline bool pt_regs_is_syscall(struct pt_regs *regs) +{ + int tt = pt_regs_trap_type(regs); + + return (tt == 0x110 || tt == 0x111 || tt == 0x16d); +} + struct pt_regs32 { unsigned int psr; unsigned int pc; -- cgit v1.2.3 From fd7354108aa5497d7177b95a6b157eaf8597d621 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 27 Apr 2008 14:54:02 -0700 Subject: sparc64: Fix accidental syscall restart on child return from clone/fork/vfork. This fixes a regression added by 238468b2ac76020c192a7402c92df5097916bf4a ("[SPARC64]: Use trap type stored in pt_regs to handle syscall restart.") Because we now encode the "returning from syscall" status in the pt_regs area, we have to be mindful to zap it out in the child of a fork. During a parallel kernel build I saw an accidental -EINTR return from vfork() in 'make' because of this bug. Signed-off-by: David S. Miller --- arch/sparc64/kernel/process.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 500ac6d483a0..056013749157 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -591,6 +591,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, if (clone_flags & CLONE_SETTLS) t->kregs->u_regs[UREG_G7] = regs->u_regs[UREG_I3]; + /* We do not want to accidently trigger system call restart + * handling in the new thread. Therefore, clear out the trap + * type, which will make pt_regs_regs_is_syscall() return false. + */ + pt_regs_clear_trap_type(t->kregs); + return 0; } -- cgit v1.2.3