rpms/kernel/devel linux-2.6.15-rc1-ppc64-pci.patch, NONE, 1.1 linux-2.6.15-rc1-ppc64-syscallpath.patch, NONE, 1.1 kernel-2.6.spec, 1.1677, 1.1678
fedora-cvs-commits at redhat.com
fedora-cvs-commits at redhat.com
Tue Nov 15 17:55:28 UTC 2005
Author: dwmw2
Update of /cvs/dist/rpms/kernel/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv3624
Modified Files:
kernel-2.6.spec
Added Files:
linux-2.6.15-rc1-ppc64-pci.patch
linux-2.6.15-rc1-ppc64-syscallpath.patch
Log Message:
test syscall stuff
linux-2.6.15-rc1-ppc64-pci.patch:
arch/powerpc/kernel/rtas_pci.c | 68 ++--------------------------------
arch/powerpc/platforms/iseries/pci.c | 3 -
arch/powerpc/platforms/maple/pci.c | 16 --------
arch/powerpc/platforms/powermac/pci.c | 62 ++++++++++++++++---------------
arch/ppc64/kernel/pci.c | 68 ++++++++++++++++++++++++++++++++--
include/asm-powerpc/ppc-pci.h | 1
include/asm-ppc64/pci-bridge.h | 14 +++++--
7 files changed, 114 insertions(+), 118 deletions(-)
--- NEW FILE linux-2.6.15-rc1-ppc64-pci.patch ---
>From linuxppc64-dev-bounces at ozlabs.org Tue Nov 15 05:06:49 2005
Return-path: <linuxppc64-dev-bounces at ozlabs.org>
Envelope-to: dwmw2 at baythorne.infradead.org
Delivery-date: Tue, 15 Nov 2005 05:06:49 +0000
Received: from [2002:d592:9a28::1] (helo=pentafluge.infradead.org) by
baythorne.infradead.org with esmtps (Exim 4.54 #1 (Red Hat Linux)) id
1Ebt1s-00047x-MA for dwmw2 at baythorne.infradead.org; Tue, 15 Nov 2005
05:06:49 +0000
Received: from ozlabs.org ([203.10.76.45]) by pentafluge.infradead.org with
esmtps (Exim 4.54 #1 (Red Hat Linux)) id 1Ebt1m-0004nO-W2 for
dwmw2 at infradead.org; Tue, 15 Nov 2005 05:06:48 +0000
Received: from ozlabs.org (localhost [127.0.0.1]) by ozlabs.org (Postfix)
with ESMTP id D98CD68760; Tue, 15 Nov 2005 16:06:36 +1100 (EST)
X-Original-To: linuxppc64-dev at ozlabs.org
Delivered-To: linuxppc64-dev at ozlabs.org
Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) (using
TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not
present a certificate) by ozlabs.org (Postfix) with ESMTP id A5E8568754 for
<linuxppc64-dev at ozlabs.org>; Tue, 15 Nov 2005 16:06:33 +1100 (EST)
Received: from gaston (localhost [127.0.0.1]) by gate.crashing.org
(8.12.8/8.12.8) with ESMTP id jAF543WG014196; Mon, 14 Nov 2005 23:04:08
-0600
From: Benjamin Herrenschmidt <benh at kernel.crashing.org>
To: Paul Mackerras <paulus at samba.org>
Content-Type: text/plain
Date: Tue, 15 Nov 2005 16:05:33 +1100
Message-Id: <1132031134.23979.2.camel at gaston>
Mime-Version: 1.0
X-Mailer: Evolution 2.2.3
Cc: linuxppc64-dev <linuxppc64-dev at ozlabs.org>
Subject: [PATCH] powerpc: pci_64 fixes & cleanups
X-BeenThere: linuxppc64-dev at ozlabs.org
X-Mailman-Version: 2.1.5
Precedence: list
List-Id: 64-bit Linux on PowerPC Developers Mail List
<linuxppc64-dev.ozlabs.org>
List-Unsubscribe: <https://ozlabs.org/mailman/listinfo/linuxppc64-dev>,
<mailto:linuxppc64-dev-request at ozlabs.org?subject=unsubscribe>
List-Archive: <http://ozlabs.org/pipermail/linuxppc64-dev>
List-Post: <mailto:linuxppc64-dev at ozlabs.org>
List-Help: <mailto:linuxppc64-dev-request at ozlabs.org?subject=help>
List-Subscribe: <https://ozlabs.org/mailman/listinfo/linuxppc64-dev>,
<mailto:linuxppc64-dev-request at ozlabs.org?subject=subscribe>
Sender: linuxppc64-dev-bounces at ozlabs.org
Errors-To: linuxppc64-dev-bounces at ozlabs.org
X-Spam-Score: 0.0 (/)
X-Evolution-Source: imap://dwmw2@pentafluge.infradead.org/
Content-Transfer-Encoding: 8bit
I discovered that in some cases (PowerMac for example) we wouldn't
properly map the PCI IO space on recent kernels. In addition, the code
for initializing PCI host bridges was scattered all over the place with
some duplication between platforms.
This patch fixes the problem and does a small cleanup by creating a
pcibios_alloc_controller() in pci_64.c that is similar to the one in
pci_32.c (just takes an additional device node argument) that takes care
of all the grunt allocation and initialisation work. It should work for
both boot time and dynamically allocated PHBs.
Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
John, can you give it a spin with pci hotplug and see if I didn't break
anything there ? Thanks !
Index: linux-work/arch/powerpc/kernel/rtas_pci.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/rtas_pci.c 2005-11-11 10:14:48.000000000 +1100
+++ linux-work/arch/powerpc/kernel/rtas_pci.c 2005-11-15 14:58:09.000000000 +1100
@@ -304,75 +304,18 @@
struct pci_controller *phb,
unsigned int addr_size_words)
{
- pci_setup_pci_controller(phb);
-
if (is_python(dev))
python_countermeasures(dev, addr_size_words);
if (phb_set_bus_ranges(dev, phb))
return 1;
- phb->arch_data = dev;
phb->ops = &rtas_pci_ops;
phb->buid = get_phb_buid(dev);
return 0;
}
-static void __devinit add_linux_pci_domain(struct device_node *dev,
- struct pci_controller *phb,
- struct property *of_prop)
-{
- memset(of_prop, 0, sizeof(struct property));
- of_prop->name = "linux,pci-domain";
- of_prop->length = sizeof(phb->global_number);
- of_prop->value = (unsigned char *)&of_prop[1];
- memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number));
- prom_add_property(dev, of_prop);
-}
-
-static struct pci_controller * __init alloc_phb(struct device_node *dev,
- unsigned int addr_size_words)
-{
- struct pci_controller *phb;
- struct property *of_prop;
-
- phb = alloc_bootmem(sizeof(struct pci_controller));
- if (phb == NULL)
- return NULL;
-
- of_prop = alloc_bootmem(sizeof(struct property) +
- sizeof(phb->global_number));
- if (!of_prop)
- return NULL;
-
- if (setup_phb(dev, phb, addr_size_words))
- return NULL;
-
- add_linux_pci_domain(dev, phb, of_prop);
-
- return phb;
-}
-
-static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words)
-{
- struct pci_controller *phb;
-
- phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),
- GFP_KERNEL);
- if (phb == NULL)
- return NULL;
-
- if (setup_phb(dev, phb, addr_size_words))
- return NULL;
-
- phb->is_dynamic = 1;
-
- /* TODO: linux,pci-domain? */
-
- return phb;
-}
-
unsigned long __init find_and_init_phbs(void)
{
struct device_node *node;
@@ -397,10 +340,10 @@
if (node->type == NULL || strcmp(node->type, "pci") != 0)
continue;
- phb = alloc_phb(node, root_size_cells);
+ phb = pcibios_alloc_controller(node);
if (!phb)
continue;
-
+ setup_phb(node, phb, root_size_cells);
pci_process_bridge_OF_ranges(phb, node, 0);
pci_setup_phb_io(phb, index == 0);
#ifdef CONFIG_PPC_PSERIES
@@ -446,10 +389,10 @@
root_size_cells = prom_n_size_cells(root);
primary = list_empty(&hose_list);
- phb = alloc_phb_dynamic(dn, root_size_cells);
+ phb = pcibios_alloc_controller(dn);
if (!phb)
return NULL;
-
+ setup_phb(dn, phb, root_size_cells);
pci_process_bridge_OF_ranges(phb, dn, primary);
pci_setup_phb_io_dynamic(phb, primary);
@@ -505,8 +448,7 @@
}
list_del(&phb->list_node);
- if (phb->is_dynamic)
- kfree(phb);
+ pcibios_free_controller(phb);
return 0;
}
Index: linux-work/arch/powerpc/platforms/iseries/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/iseries/pci.c 2005-11-09 11:49:03.000000000 +1100
+++ linux-work/arch/powerpc/platforms/iseries/pci.c 2005-11-15 14:41:29.000000000 +1100
@@ -244,10 +244,9 @@
if (ret == 0) {
printk("bus %d appears to exist\n", bus);
- phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
+ phb = pcibios_alloc_controller(NULL);
if (phb == NULL)
return -ENOMEM;
- pci_setup_pci_controller(phb);
phb->pci_mem_offset = phb->local_number = bus;
phb->first_busno = bus;
Index: linux-work/arch/powerpc/platforms/maple/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/maple/pci.c 2005-11-11 10:14:48.000000000 +1100
+++ linux-work/arch/powerpc/platforms/maple/pci.c 2005-11-15 14:41:29.000000000 +1100
@@ -326,26 +326,12 @@
dev->full_name);
}
- hose = alloc_bootmem(sizeof(struct pci_controller));
+ hose = pcibios_alloc_controller(dev);
if (hose == NULL)
return -ENOMEM;
- pci_setup_pci_controller(hose);
-
- hose->arch_data = dev;
hose->first_busno = bus_range ? bus_range[0] : 0;
hose->last_busno = bus_range ? bus_range[1] : 0xff;
- of_prop = alloc_bootmem(sizeof(struct property) +
- sizeof(hose->global_number));
- if (of_prop) {
- memset(of_prop, 0, sizeof(struct property));
- of_prop->name = "linux,pci-domain";
- of_prop->length = sizeof(hose->global_number);
- of_prop->value = (unsigned char *)&of_prop[1];
- memcpy(of_prop->value, &hose->global_number, sizeof(hose->global_number));
- prom_add_property(dev, of_prop);
- }
-
disp_name = NULL;
if (device_is_compatible(dev, "u3-agp")) {
setup_u3_agp(hose);
Index: linux-work/arch/powerpc/platforms/powermac/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/powermac/pci.c 2005-11-11 10:14:48.000000000 +1100
+++ linux-work/arch/powerpc/platforms/powermac/pci.c 2005-11-15 14:41:29.000000000 +1100
@@ -640,15 +640,16 @@
* the reg address cell, we shall fix that by killing struct
* reg_property and using some accessor functions instead
*/
- hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000);
+ hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000,
+ 0x02000000);
/*
- * /ht node doesn't expose a "ranges" property, so we "remove" regions that
- * have been allocated to AGP. So far, this version of the code doesn't assign
- * any of the 0xfxxxxxxx "fine" memory regions to /ht.
- * We need to fix that sooner or later by either parsing all child "ranges"
- * properties or figuring out the U3 address space decoding logic and
- * then read its configuration register (if any).
+ * /ht node doesn't expose a "ranges" property, so we "remove"
+ * regions that have been allocated to AGP. So far, this version of
+ * the code doesn't assign any of the 0xfxxxxxxx "fine" memory regions
+ * to /ht. We need to fix that sooner or later by either parsing all
+ * child "ranges" properties or figuring out the U3 address space
+ * decoding logic and then read its configuration register (if any).
*/
hose->io_base_phys = 0xf4000000;
hose->pci_io_size = 0x00400000;
@@ -671,10 +672,10 @@
return;
}
- /* We "remove" the AGP resources from the resources allocated to HT, that
- * is we create "holes". However, that code does assumptions that so far
- * happen to be true (cross fingers...), typically that resources in the
- * AGP node are properly ordered
+ /* We "remove" the AGP resources from the resources allocated to HT,
+ * that is we create "holes". However, that code does assumptions
+ * that so far happen to be true (cross fingers...), typically that
+ * resources in the AGP node are properly ordered
*/
cur = 0;
for (i=0; i<3; i++) {
@@ -684,23 +685,30 @@
/* We don't care about "fine" resources */
if (res->start >= 0xf0000000)
continue;
- /* Check if it's just a matter of "shrinking" us in one direction */
+ /* Check if it's just a matter of "shrinking" us in one
+ * direction
+ */
if (hose->mem_resources[cur].start == res->start) {
DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n",
- cur, hose->mem_resources[cur].start, res->end + 1);
+ cur, hose->mem_resources[cur].start,
+ res->end + 1);
hose->mem_resources[cur].start = res->end + 1;
continue;
}
if (hose->mem_resources[cur].end == res->end) {
DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n",
- cur, hose->mem_resources[cur].end, res->start - 1);
+ cur, hose->mem_resources[cur].end,
+ res->start - 1);
hose->mem_resources[cur].end = res->start - 1;
continue;
}
/* No, it's not the case, we need a hole */
if (cur == 2) {
- /* not enough resources for a hole, we drop part of the range */
- printk(KERN_WARNING "Running out of resources for /ht host !\n");
+ /* not enough resources for a hole, we drop part
+ * of the range
+ */
+ printk(KERN_WARNING "Running out of resources"
+ " for /ht host !\n");
hose->mem_resources[cur].end = res->start - 1;
continue;
}
@@ -714,17 +722,6 @@
hose->mem_resources[cur-1].end = res->start - 1;
}
}
-
-/* XXX this needs to be converged between ppc32 and ppc64... */
-static struct pci_controller * __init pcibios_alloc_controller(void)
-{
- struct pci_controller *hose;
-
- hose = alloc_bootmem(sizeof(struct pci_controller));
- if (hose)
- pci_setup_pci_controller(hose);
- return hose;
-}
#endif
/*
@@ -756,11 +753,16 @@
#endif
bus_range = (int *) get_property(dev, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
- dev->full_name);
+ printk(KERN_WARNING "Can't get bus-range for %s, assume"
+ " bus 0\n", dev->full_name);
}
+ /* XXX Different prototypes, to be merged */
+#ifdef CONFIG_PPC64
+ hose = pcibios_alloc_controller(dev);
+#else
hose = pcibios_alloc_controller();
+#endif
if (!hose)
return -ENOMEM;
hose->arch_data = dev;
@@ -768,7 +770,7 @@
hose->last_busno = bus_range ? bus_range[1] : 0xff;
disp_name = NULL;
-#ifdef CONFIG_POWER4
+#ifdef CONFIG_PPC64
if (device_is_compatible(dev, "u3-agp")) {
setup_u3_agp(hose);
disp_name = "U3-AGP";
Index: linux-work/include/asm-ppc64/pci-bridge.h
===================================================================
--- linux-work.orig/include/asm-ppc64/pci-bridge.h 2005-11-11 10:14:49.000000000 +1100
+++ linux-work/include/asm-ppc64/pci-bridge.h 2005-11-15 14:59:23.000000000 +1100
@@ -61,12 +61,14 @@
int busno; /* for pci devices */
int bussubno; /* for pci devices */
int devfn; /* for pci devices */
+
+#ifdef CONFIG_PPC_PSERIES
int eeh_mode; /* See eeh.h for possible EEH_MODEs */
int eeh_config_addr;
int eeh_check_count; /* # times driver ignored error */
int eeh_freeze_count; /* # times this device froze up. */
int eeh_is_bridge; /* device is pci-to-pci bridge */
-
+#endif
int pci_ext_config_space; /* for pci devices */
struct pci_controller *phb; /* for pci devices */
struct iommu_table *iommu_table; /* for phb's or bridges */
@@ -74,9 +76,9 @@
struct device_node *node; /* back-pointer to the device_node */
#ifdef CONFIG_PPC_ISERIES
struct list_head Device_List;
- int Irq; /* Assigned IRQ */
- int Flags; /* Possible flags(disable/bist)*/
- u8 LogicalSlot; /* Hv Slot Index for Tces */
+ int Irq; /* Assigned IRQ */
+ int Flags; /* Possible flags(disable/bist)*/
+ u8 LogicalSlot; /* Hv Slot Index for Tces */
#endif
u32 config_space[16]; /* saved PCI config space */
};
@@ -136,6 +138,10 @@
return PCI_DN(busdn)->phb;
}
+extern struct pci_controller *
+pcibios_alloc_controller(struct device_node *dev);
+extern void pcibios_free_controller(struct pci_controller *phb);
+
/* Return values for ppc_md.pci_probe_mode function */
#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */
#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */
Index: linux-work/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_64.c 2005-11-15 13:31:57.000000000 +1100
+++ linux-work/arch/ppc64/kernel/pci.c 2005-11-15 15:53:07.000000000 +1100
@@ -187,7 +187,7 @@
/*
* pci_controller(phb) initialized common variables.
*/
-void __devinit pci_setup_pci_controller(struct pci_controller *hose)
+static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
{
memset(hose, 0, sizeof(struct pci_controller));
@@ -197,6 +197,65 @@
spin_unlock(&hose_spinlock);
}
+static void add_linux_pci_domain(struct device_node *dev,
+ struct pci_controller *phb)
+{
+ struct property *of_prop;
+ unsigned int size;
+
+ of_prop = (struct property *)
+ get_property(dev, "linux,pci-domain", &size);
+ if (of_prop != NULL)
+ return;
+ WARN_ON(of_prop && size < sizeof(int));
+ if (of_prop && size < sizeof(int))
+ of_prop = NULL;
+ size = sizeof(struct property) + sizeof(int);
+ if (of_prop == NULL) {
+ if (mem_init_done)
+ of_prop = kmalloc(size, GFP_KERNEL);
+ else
+ of_prop = alloc_bootmem(size);
+ }
+ memset(of_prop, 0, sizeof(struct property));
+ of_prop->name = "linux,pci-domain";
+ of_prop->length = sizeof(int);
+ of_prop->value = (unsigned char *)&of_prop[1];
+ *((int *)of_prop->value) = phb->global_number;
+ prom_add_property(dev, of_prop);
+}
+
+struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
+{
+ struct pci_controller *phb;
+
+ if (mem_init_done)
+ phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
+ else
+ phb = alloc_bootmem(sizeof (struct pci_controller));
+ if (phb == NULL)
+ return NULL;
+ pci_setup_pci_controller(phb);
+ phb->arch_data = dev;
+ phb->is_dynamic = mem_init_done;
+ if (dev)
+ add_linux_pci_domain(dev, phb);
+ return phb;
+}
+
+void pcibios_free_controller(struct pci_controller *phb)
+{
+ if (phb->arch_data) {
+ struct device_node *np = phb->arch_data;
+ int *domain = (int *)get_property(np,
+ "linux,pci-domain", NULL);
+ if (domain)
+ *domain = -1;
+ }
+ if (phb->is_dynamic)
+ kfree(phb);
+}
+
static void __init pcibios_claim_one_bus(struct pci_bus *b)
{
struct pci_dev *dev;
@@ -907,9 +966,10 @@
* (size depending on dev->n_addr_cells)
* cells 4+5 or 5+6: the size of the range
*/
- rlen = 0;
- hose->io_base_phys = 0;
ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+ if (ranges == NULL)
+ return;
+ hose->io_base_phys = 0;
while ((rlen -= np * sizeof(unsigned int)) >= 0) {
res = NULL;
pci_space = ranges[0];
@@ -1107,6 +1167,8 @@
if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
return 1;
+ if (start_phys == 0)
+ return 1;
printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
if (__ioremap_explicit(start_phys, start_virt, size,
_PAGE_NO_CACHE | _PAGE_GUARDED))
Index: linux-work/include/asm-powerpc/ppc-pci.h
===================================================================
--- linux-work.orig/include/asm-powerpc/ppc-pci.h 2005-11-11 10:14:49.000000000 +1100
+++ linux-work/include/asm-powerpc/ppc-pci.h 2005-11-15 14:57:24.000000000 +1100
@@ -14,7 +14,6 @@
extern unsigned long isa_io_base;
-extern void pci_setup_pci_controller(struct pci_controller *hose);
extern void pci_setup_phb_io(struct pci_controller *hose, int primary);
extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary);
_______________________________________________
Linuxppc64-dev mailing list
Linuxppc64-dev at ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc64-dev
linux-2.6.15-rc1-ppc64-syscallpath.patch:
arch/powerpc/kernel/asm-offsets.c | 4
arch/powerpc/kernel/entry_32.S | 167 +++++++++++++++++------------
arch/powerpc/kernel/entry_64.S | 214 ++++++++++++++++++++------------------
arch/powerpc/kernel/signal_32.c | 59 ++++------
arch/powerpc/kernel/signal_64.c | 23 +++-
arch/powerpc/kernel/systbl.S | 10 -
include/asm-powerpc/ptrace.h | 2
include/asm-powerpc/thread_info.h | 12 +-
8 files changed, 269 insertions(+), 222 deletions(-)
--- NEW FILE linux-2.6.15-rc1-ppc64-syscallpath.patch ---
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 91538d2..3bf89d1 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -92,9 +92,9 @@ int main(void)
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
- DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror));
-#ifdef CONFIG_PPC32
+ DEFINE(TI_SIGFRAME, offsetof(struct thread_info, nvgprs_frame));
DEFINE(TI_TASK, offsetof(struct thread_info, task));
+#ifdef CONFIG_PPC32
DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
#endif /* CONFIG_PPC32 */
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 2e99ae4..8fed953 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -200,8 +200,6 @@ _GLOBAL(DoSyscall)
bl do_show_syscall
#endif /* SHOW_SYSCALLS */
rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
- li r11,0
- stb r11,TI_SC_NOERR(r10)
lwz r11,TI_FLAGS(r10)
andi. r11,r11,_TIF_SYSCALL_T_OR_A
bne- syscall_dotrace
@@ -222,25 +220,21 @@ ret_from_syscall:
bl do_show_syscall_exit
#endif
mr r6,r3
- li r11,-_LAST_ERRNO
- cmplw 0,r3,r11
rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
- blt+ 30f
- lbz r11,TI_SC_NOERR(r12)
- cmpwi r11,0
- bne 30f
- neg r3,r3
- lwz r10,_CCR(r1) /* Set SO bit in CR */
- oris r10,r10,0x1000
- stw r10,_CCR(r1)
-
/* disable interrupts so current_thread_info()->flags can't change */
-30: LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
+ LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
SYNC
MTMSRD(r10)
lwz r9,TI_FLAGS(r12)
- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+ li r8,-_LAST_ERRNO
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
bne- syscall_exit_work
+ cmplw 0,r3,r8
+ blt+ syscall_exit_cont
+ lwz r11,_CCR(r1) /* Load CR */
+ neg r3,r3
+ oris r11,r11,0x1000 /* Set SO bit in CR */
+ stw r11,_CCR(r1)
syscall_exit_cont:
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
/* If the process has its own DBCR0 value, load it up. The single
@@ -292,46 +286,113 @@ syscall_dotrace:
b syscall_dotrace_cont
syscall_exit_work:
- stw r6,RESULT(r1) /* Save result */
+ andi. r0,r9,_TIF_RESTOREALL
+ bne- 2f
+ cmplw 0,r3,r8
+ blt+ 1f
+ andi. r0,r9,_TIF_NOERROR
+ bne- 1f
+ lwz r11,_CCR(r1) /* Load CR */
+ neg r3,r3
+ oris r11,r11,0x1000 /* Set SO bit in CR */
+ stw r11,_CCR(r1)
+
+1: stw r6,RESULT(r1) /* Save result */
stw r3,GPR3(r1) /* Update return value */
- andi. r0,r9,_TIF_SYSCALL_T_OR_A
- beq 5f
- ori r10,r10,MSR_EE
- SYNC
- MTMSRD(r10) /* re-enable interrupts */
+2: andi. r0,r9,(_TIF_PERSYSCALL_MASK)
+ beq 4f
+
+ /* Clear per-syscall TIF flags if any are set, but _leave_
+ _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that
+ yet. */
+
+ li r11,_TIF_PERSYSCALL_MASK
+ addi r12,r12,TI_FLAGS
+3: lwarx r8,0,r12
+ andc r8,r8,r11
+#ifdef CONFIG_IBM405_ERR77
+ dcbt 0,r12
+#endif
+ stwcx. r8,0,r12
+ bne- 3b
+ subi r12,r12,TI_FLAGS
+
+4: /* Anything which requires enabling interrupts? */
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS)
+ beq 7f
+
+ /* Save NVGPRS if they're not saved already */
lwz r4,_TRAP(r1)
andi. r4,r4,1
- beq 4f
+ beq 5f
SAVE_NVGPRS(r1)
li r4,0xc00
stw r4,_TRAP(r1)
-4:
+
+ /* Re-enable interrupts */
+5: ori r10,r10,MSR_EE
+ SYNC
+ MTMSRD(r10)
+
+ andi. r0,r9,_TIF_SAVE_NVGPRS
+ bne save_user_nvgprs
+
+save_user_nvgprs_cont:
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
+ beq 7f
+
addi r3,r1,STACK_FRAME_OVERHEAD
bl do_syscall_trace_leave
REST_NVGPRS(r1)
-2:
- lwz r3,GPR3(r1)
+
+6: lwz r3,GPR3(r1)
LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
SYNC
MTMSRD(r10) /* disable interrupts again */
rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
lwz r9,TI_FLAGS(r12)
-5:
+7:
andi. r0,r9,_TIF_NEED_RESCHED
- bne 1f
+ bne 8f
lwz r5,_MSR(r1)
andi. r5,r5,MSR_PR
- beq syscall_exit_cont
+ beq ret_from_except
andi. r0,r9,_TIF_SIGPENDING
- beq syscall_exit_cont
+ beq ret_from_except
b do_user_signal
-1:
+8:
ori r10,r10,MSR_EE
SYNC
MTMSRD(r10) /* re-enable interrupts */
bl schedule
- b 2b
+ b 6b
+
+save_user_nvgprs:
+ ld r8,TI_SIGFRAME(r12)
+.macro savewords start, end
+ 1: stw \start,4*(\start)(r8)
+ .section __ex_table,"a"
+ .align 2
+ .long 1b,save_user_nvgprs_fault
+ .previous
+ .if \end - \start
+ savewords "(\start+1)",\end
+ .endif
+.endm
+ savewords 14,31
+ b save_user_nvgprs_cont
+
+
+save_user_nvgprs_fault:
+ li r3,11 /* SIGSEGV */
+ ld r4,TI_TASK(r12)
+ bl force_sigsegv
+
+ rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
+ ld r9,TI_FLAGS(r12)
+ b save_user_nvgprs_cont
+
#ifdef SHOW_SYSCALLS
do_show_syscall:
#ifdef SHOW_SYSCALLS_TASK
@@ -401,28 +462,10 @@ show_syscalls_task:
#endif /* SHOW_SYSCALLS */
/*
- * The sigsuspend and rt_sigsuspend system calls can call do_signal
- * and thus put the process into the stopped state where we might
- * want to examine its user state with ptrace. Therefore we need
- * to save all the nonvolatile registers (r13 - r31) before calling
- * the C code.
+ * The fork/clone functions need to copy the full register set into
+ * the child process. Therefore we need to save all the nonvolatile
+ * registers (r13 - r31) before calling the C code.
*/
- .globl ppc_sigsuspend
-ppc_sigsuspend:
- SAVE_NVGPRS(r1)
- lwz r0,_TRAP(r1)
- rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
- stw r0,_TRAP(r1) /* register set saved */
- b sys_sigsuspend
-
- .globl ppc_rt_sigsuspend
-ppc_rt_sigsuspend:
- SAVE_NVGPRS(r1)
- lwz r0,_TRAP(r1)
- rlwinm r0,r0,0,0,30
- stw r0,_TRAP(r1)
- b sys_rt_sigsuspend
-
.globl ppc_fork
ppc_fork:
SAVE_NVGPRS(r1)
@@ -447,14 +490,6 @@ ppc_clone:
stw r0,_TRAP(r1) /* register set saved */
b sys_clone
- .globl ppc_swapcontext
-ppc_swapcontext:
- SAVE_NVGPRS(r1)
- lwz r0,_TRAP(r1)
- rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */
- stw r0,_TRAP(r1) /* register set saved */
- b sys_swapcontext
-
/*
* Top-level page fault handling.
* This is in assembler because if do_page_fault tells us that
@@ -626,16 +661,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_601)
.long ret_from_except
#endif
- .globl sigreturn_exit
-sigreturn_exit:
- subi r1,r3,STACK_FRAME_OVERHEAD
- rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
- lwz r9,TI_FLAGS(r12)
- andi. r0,r9,_TIF_SYSCALL_T_OR_A
- beq+ ret_from_except_full
- bl do_syscall_trace_leave
- /* fall through */
-
.globl ret_from_except_full
ret_from_except_full:
REST_NVGPRS(r1)
@@ -658,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KE
/* Check current_thread_info()->flags */
rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
lwz r9,TI_FLAGS(r9)
- andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+ andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL)
bne do_work
restore_user:
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 2d22bf0..83b9edf 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -113,9 +113,7 @@ system_call_common:
addi r9,r1,STACK_FRAME_OVERHEAD
#endif
clrrdi r11,r1,THREAD_SHIFT
- li r12,0
ld r10,TI_FLAGS(r11)
- stb r12,TI_SC_NOERR(r11)
andi. r11,r10,_TIF_SYSCALL_T_OR_A
bne- syscall_dotrace
syscall_dotrace_cont:
@@ -144,24 +142,12 @@ system_call: /* label this so stack tr
bctrl /* Call handler */
syscall_exit:
+ std r3,RESULT(r1)
#ifdef SHOW_SYSCALLS
- std r3,GPR3(r1)
bl .do_show_syscall_exit
- ld r3,GPR3(r1)
+ ld r3,RESULT(r1)
#endif
- std r3,RESULT(r1)
- ld r5,_CCR(r1)
- li r10,-_LAST_ERRNO
- cmpld r3,r10
clrrdi r12,r1,THREAD_SHIFT
- bge- syscall_error
-syscall_error_cont:
-
- /* check for syscall tracing or audit */
- ld r9,TI_FLAGS(r12)
- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
- bne- syscall_exit_trace
-syscall_exit_trace_cont:
/* disable interrupts so current_thread_info()->flags can't change,
and so that we don't get interrupted after loading SRR0/1. */
@@ -173,8 +159,13 @@ syscall_exit_trace_cont:
rotldi r10,r10,16
mtmsrd r10,1
ld r9,TI_FLAGS(r12)
- andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+ li r11,-_LAST_ERRNO
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR)
bne- syscall_exit_work
+ cmpld r3,r11
+ ld r5,_CCR(r1)
+ bge- syscall_error
+syscall_error_cont:
ld r7,_NIP(r1)
stdcx. r0,0,r1 /* to clear the reservation */
andi. r6,r8,MSR_PR
@@ -193,21 +184,12 @@ syscall_exit_trace_cont:
rfid
b . /* prevent speculative execution */
-syscall_enosys:
- li r3,-ENOSYS
- std r3,RESULT(r1)
- clrrdi r12,r1,THREAD_SHIFT
- ld r5,_CCR(r1)
-
-syscall_error:
- lbz r11,TI_SC_NOERR(r12)
- cmpwi 0,r11,0
- bne- syscall_error_cont
- neg r3,r3
+syscall_error:
oris r5,r5,0x1000 /* Set SO bit in CR */
+ neg r3,r3
std r5,_CCR(r1)
b syscall_error_cont
-
+
/* Traced system call support */
syscall_dotrace:
bl .save_nvgprs
@@ -225,21 +207,69 @@ syscall_dotrace:
ld r10,TI_FLAGS(r10)
b syscall_dotrace_cont
-syscall_exit_trace:
- std r3,GPR3(r1)
- bl .save_nvgprs
+syscall_enosys:
+ li r3,-ENOSYS
+ b syscall_exit
+
+syscall_exit_work:
+ /* If TIF_RESTOREALL is set, don't scribble on either r3 or ccr.
+ If TIF_NOERROR is set, just save r3 as it is. */
+
+ andi. r0,r9,_TIF_RESTOREALL
+ bne- 2f
+ cmpld r3,r11 /* r10 is -LAST_ERRNO */
+ blt+ 1f
+ andi. r0,r9,_TIF_NOERROR
+ bne- 1f
+ ld r5,_CCR(r1)
+ neg r3,r3
+ oris r5,r5,0x1000 /* Set SO bit in CR */
+ std r5,_CCR(r1)
+1: std r3,GPR3(r1)
+2: andi. r0,r9,(_TIF_PERSYSCALL_MASK)
+ beq 4f
+
+ /* Clear per-syscall TIF flags if any are set, but _leave_
+ _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that
+ yet. */
+
+ li r11,_TIF_PERSYSCALL_MASK
+ addi r12,r12,TI_FLAGS
+3: ldarx r10,0,r12
+ andc r10,r10,r11
+ stdcx. r10,0,r12
+ bne- 3b
+ subi r12,r12,TI_FLAGS
+
+4: bl save_nvgprs
+ /* Anything else left to do? */
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS)
+ beq .ret_from_except_lite
+
+ /* Re-enable interrupts */
+ mfmsr r10
+ ori r10,r10,MSR_EE
+ mtmsrd r10,1
+
+ andi. r0,r9,_TIF_SAVE_NVGPRS
+ bne save_user_nvgprs
+
+ /* If tracing, re-enable interrupts and do it */
+save_user_nvgprs_cont:
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
+ beq 5f
+
addi r3,r1,STACK_FRAME_OVERHEAD
bl .do_syscall_trace_leave
REST_NVGPRS(r1)
- ld r3,GPR3(r1)
- ld r5,_CCR(r1)
clrrdi r12,r1,THREAD_SHIFT
- b syscall_exit_trace_cont
-/* Stuff to do on exit from a system call. */
-syscall_exit_work:
- std r3,GPR3(r1)
- std r5,_CCR(r1)
+ /* Disable interrupts again and handle other work if any */
+5: mfmsr r10
+ rldicl r10,r10,48,1
+ rotldi r10,r10,16
+ mtmsrd r10,1
+
b .ret_from_except_lite
/* Save non-volatile GPRs, if not already saved. */
@@ -252,6 +282,52 @@ _GLOBAL(save_nvgprs)
std r0,_TRAP(r1)
blr
+
+save_user_nvgprs:
+ ld r10,TI_SIGFRAME(r12)
+ andi. r0,r9,_TIF_32BIT
+ beq- save_user_nvgprs_64
+
+ /* 32-bit save to userspace */
+
+.macro savewords start, end
+ 1: stw \start,4*(\start)(r10)
+ .section __ex_table,"a"
+ .align 3
+ .llong 1b,save_user_nvgprs_fault
+ .previous
+ .if \end - \start
+ savewords "(\start+1)",\end
+ .endif
+.endm
+ savewords 14,31
+ b save_user_nvgprs_cont
+
+save_user_nvgprs_64:
+ /* 64-bit save to userspace */
+
+.macro savelongs start, end
+ 1: std \start,8*(\start)(r10)
+ .section __ex_table,"a"
+ .align 3
+ .llong 1b,save_user_nvgprs_fault
+ .previous
+ .if \end - \start
+ savelongs "(\start+1)",\end
+ .endif
+.endm
+ savelongs 14,31
+ b save_user_nvgprs_cont
+
+save_user_nvgprs_fault:
+ li r3,11 /* SIGSEGV */
+ ld r4,TI_TASK(r12)
+ bl .force_sigsegv
+
+ clrrdi r12,r1,THREAD_SHIFT
+ ld r9,TI_FLAGS(r12)
+ b save_user_nvgprs_cont
+
/*
* The sigsuspend and rt_sigsuspend system calls can call do_signal
* and thus put the process into the stopped state where we might
@@ -260,35 +336,6 @@ _GLOBAL(save_nvgprs)
* the C code. Similarly, fork, vfork and clone need the full
* register state on the stack so that it can be copied to the child.
*/
-_GLOBAL(ppc32_sigsuspend)
- bl .save_nvgprs
- bl .compat_sys_sigsuspend
- b 70f
-
-_GLOBAL(ppc64_rt_sigsuspend)
- bl .save_nvgprs
- bl .sys_rt_sigsuspend
- b 70f
-
-_GLOBAL(ppc32_rt_sigsuspend)
- bl .save_nvgprs
- bl .compat_sys_rt_sigsuspend
-70: cmpdi 0,r3,0
- /* If it returned an error, we need to return via syscall_exit to set
- the SO bit in cr0 and potentially stop for ptrace. */
- bne syscall_exit
- /* If sigsuspend() returns zero, we are going into a signal handler. We
- may need to call audit_syscall_exit() to mark the exit from sigsuspend() */
-#ifdef CONFIG_AUDITSYSCALL
- ld r3,PACACURRENT(r13)
- ld r4,AUDITCONTEXT(r3)
- cmpdi 0,r4,0
- beq .ret_from_except /* No audit_context: Leave immediately. */
- li r4, 2 /* AUDITSC_FAILURE */
- li r5,-4 /* It's always -EINTR */
- bl .audit_syscall_exit
-#endif
- b .ret_from_except
_GLOBAL(ppc_fork)
bl .save_nvgprs
@@ -305,37 +352,6 @@ _GLOBAL(ppc_clone)
bl .sys_clone
b syscall_exit
-_GLOBAL(ppc32_swapcontext)
- bl .save_nvgprs
- bl .compat_sys_swapcontext
- b 80f
-
-_GLOBAL(ppc64_swapcontext)
- bl .save_nvgprs
- bl .sys_swapcontext
- b 80f
-
-_GLOBAL(ppc32_sigreturn)
- bl .compat_sys_sigreturn
- b 80f
-
-_GLOBAL(ppc32_rt_sigreturn)
- bl .compat_sys_rt_sigreturn
- b 80f
-
-_GLOBAL(ppc64_rt_sigreturn)
- bl .sys_rt_sigreturn
-
-80: cmpdi 0,r3,0
- blt syscall_exit
- clrrdi r4,r1,THREAD_SHIFT
- ld r4,TI_FLAGS(r4)
- andi. r4,r4,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
- beq+ 81f
- addi r3,r1,STACK_FRAME_OVERHEAD
- bl .do_syscall_trace_leave
-81: b .ret_from_except
-
_GLOBAL(ret_from_fork)
bl .schedule_tail
REST_NVGPRS(r1)
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 5a2eba6..c9d0275 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -76,7 +76,6 @@
* registers from *regs. This is what we need
* to do when a signal has been delivered.
*/
-#define sigreturn_exit(regs) return 0
#define GP_REGS_SIZE min(sizeof(elf_gregset_t32), sizeof(struct pt_regs32))
#undef __SIGNAL_FRAMESIZE
@@ -156,9 +155,17 @@ static inline int save_general_regs(stru
elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
int i;
- for (i = 0; i <= PT_RESULT; i ++)
+ if (!FULL_REGS(regs)) {
+ set_thread_flag(TIF_SAVE_NVGPRS);
+ current_thread_info()->nvgprs_frame = frame->mc_gregs;
+ }
+
+ for (i = 0; i <= PT_RESULT; i ++) {
+ if (i == 14 && !FULL_REGS(regs))
+ i = 32;
if (__put_user((unsigned int)gregs[i], &frame->mc_gregs[i]))
return -EFAULT;
+ }
return 0;
}
@@ -179,8 +186,6 @@ static inline int restore_general_regs(s
#else /* CONFIG_PPC64 */
-extern void sigreturn_exit(struct pt_regs *);
-
#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
static inline int put_sigset_t(sigset_t __user *uset, sigset_t *set)
@@ -256,8 +261,10 @@ long sys_sigsuspend(old_sigset_t mask, i
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(&saveset, regs))
- sigreturn_exit(regs);
+ if (do_signal(&saveset, regs)) {
+ set_thread_flag(TIF_RESTOREALL);
+ return 0;
+ }
}
}
@@ -292,8 +299,10 @@ long sys_rt_sigsuspend(
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(&saveset, regs))
- sigreturn_exit(regs);
+ if (do_signal(&saveset, regs)) {
+ set_thread_flag(TIF_RESTOREALL);
+ return 0;
+ }
}
}
@@ -391,9 +400,6 @@ struct rt_sigframe {
static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
int sigret)
{
-#ifdef CONFIG_PPC32
- CHECK_FULL_REGS(regs);
-#endif
/* Make sure floating point registers are stored in regs */
flush_fp_to_thread(current);
@@ -828,12 +834,6 @@ static int handle_rt_signal(unsigned lon
regs->gpr[6] = (unsigned long) rt_sf;
regs->nip = (unsigned long) ka->sa.sa_handler;
regs->trap = 0;
-#ifdef CONFIG_PPC64
- regs->result = 0;
-
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
-#endif
return 1;
badframe:
@@ -911,8 +911,8 @@ long sys_swapcontext(struct ucontext __u
*/
if (do_setcontext(new_ctx, regs, 0))
do_exit(SIGSEGV);
- sigreturn_exit(regs);
- /* doesn't actually return back to here */
+
+ set_thread_flag(TIF_RESTOREALL);
return 0;
}
@@ -945,12 +945,11 @@ long sys_rt_sigreturn(int r3, int r4, in
* nobody does any...
*/
compat_sys_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs);
- return (int)regs->result;
#else
do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]);
- sigreturn_exit(regs); /* doesn't return here */
- return 0;
#endif
+ set_thread_flag(TIF_RESTOREALL);
+ return 0;
bad:
force_sig(SIGSEGV, current);
@@ -1041,9 +1040,7 @@ int sys_debug_setcontext(struct ucontext
*/
do_sigaltstack(&ctx->uc_stack, NULL, regs->gpr[1]);
- sigreturn_exit(regs);
- /* doesn't actually return back to here */
-
+ set_thread_flag(TIF_RESTOREALL);
out:
return 0;
}
@@ -1107,12 +1104,6 @@ static int handle_signal(unsigned long s
regs->gpr[4] = (unsigned long) sc;
regs->nip = (unsigned long) ka->sa.sa_handler;
regs->trap = 0;
-#ifdef CONFIG_PPC64
- regs->result = 0;
-
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
-#endif
return 1;
@@ -1160,12 +1151,8 @@ long sys_sigreturn(int r3, int r4, int r
|| restore_user_regs(regs, sr, 1))
goto badframe;
-#ifdef CONFIG_PPC64
- return (int)regs->result;
-#else
- sigreturn_exit(regs); /* doesn't return */
+ set_thread_flag(TIF_RESTOREALL);
return 0;
-#endif
badframe:
force_sig(SIGSEGV, current);
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 1decf27..5462bef 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -96,8 +96,10 @@ long sys_rt_sigsuspend(sigset_t __user *
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(&saveset, regs))
+ if (do_signal(&saveset, regs)) {
+ set_thread_flag(TIF_RESTOREALL);
return 0;
+ }
}
}
@@ -152,6 +154,14 @@ static long setup_sigcontext(struct sigc
err |= __put_user(0, &sc->v_regs);
#endif /* CONFIG_ALTIVEC */
err |= __put_user(&sc->gp_regs, &sc->regs);
+ if (!FULL_REGS(regs)) {
+ /* Zero out the unsaved GPRs to avoid information
+ leak, and set TIF_SAVE_NVGPRS to ensure that the
+ registers do actually get saved later. */
+ memset(®s->gpr[14], 0, 18 * sizeof(unsigned long));
+ set_thread_flag(TIF_SAVE_NVGPRS);
+ current_thread_info()->nvgprs_frame = &sc->gp_regs;
+ }
err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE);
err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE);
err |= __put_user(signr, &sc->signal);
@@ -340,6 +350,7 @@ int sys_swapcontext(struct ucontext __us
do_exit(SIGSEGV);
/* This returns like rt_sigreturn */
+ set_thread_flag(TIF_RESTOREALL);
return 0;
}
@@ -372,7 +383,8 @@ int sys_rt_sigreturn(unsigned long r3, u
*/
do_sigaltstack(&uc->uc_stack, NULL, regs->gpr[1]);
- return regs->result;
+ set_thread_flag(TIF_RESTOREALL);
+ return 0;
badframe:
#if DEBUG_SIG
@@ -454,9 +466,6 @@ static int setup_rt_frame(int signr, str
if (err)
goto badframe;
- if (test_thread_flag(TIF_SINGLESTEP))
- ptrace_notify(SIGTRAP);
-
return 1;
badframe:
@@ -502,6 +511,8 @@ static inline void syscall_restart(struc
* we only get here if there is a handler, we dont restart.
*/
regs->result = -EINTR;
+ regs->gpr[3] = EINTR;
+ regs->ccr |= 0x10000000;
break;
case -ERESTARTSYS:
/* ERESTARTSYS means to restart the syscall if there is no
@@ -509,6 +520,8 @@ static inline void syscall_restart(struc
*/
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->result = -EINTR;
+ regs->gpr[3] = EINTR;
+ regs->ccr |= 0x10000000;
break;
}
/* fallthrough */
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 65eaea9..4bb3650 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -113,7 +113,7 @@ SYSCALL(sgetmask)
COMPAT_SYS(ssetmask)
SYSCALL(setreuid)
SYSCALL(setregid)
-SYSX(sys_ni_syscall,ppc32_sigsuspend,ppc_sigsuspend)
+SYS32ONLY(sigsuspend)
COMPAT_SYS(sigpending)
COMPAT_SYS(sethostname)
COMPAT_SYS(setrlimit)
@@ -160,7 +160,7 @@ SYSCALL(swapoff)
COMPAT_SYS(sysinfo)
COMPAT_SYS(ipc)
SYSCALL(fsync)
-SYSX(sys_ni_syscall,ppc32_sigreturn,sys_sigreturn)
+SYS32ONLY(sigreturn)
PPC_SYS(clone)
COMPAT_SYS(setdomainname)
PPC_SYS(newuname)
@@ -213,13 +213,13 @@ COMPAT_SYS(nfsservctl)
SYSCALL(setresgid)
SYSCALL(getresgid)
COMPAT_SYS(prctl)
-SYSX(ppc64_rt_sigreturn,ppc32_rt_sigreturn,sys_rt_sigreturn)
+COMPAT_SYS(rt_sigreturn)
COMPAT_SYS(rt_sigaction)
COMPAT_SYS(rt_sigprocmask)
COMPAT_SYS(rt_sigpending)
COMPAT_SYS(rt_sigtimedwait)
COMPAT_SYS(rt_sigqueueinfo)
-SYSX(ppc64_rt_sigsuspend,ppc32_rt_sigsuspend,ppc_rt_sigsuspend)
+COMPAT_SYS(rt_sigsuspend)
COMPAT_SYS(pread64)
COMPAT_SYS(pwrite64)
SYSCALL(chown)
@@ -290,7 +290,7 @@ COMPAT_SYS(clock_settime)
COMPAT_SYS(clock_gettime)
COMPAT_SYS(clock_getres)
COMPAT_SYS(clock_nanosleep)
-SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext)
+COMPAT_SYS(swapcontext)
COMPAT_SYS(tgkill)
COMPAT_SYS(utimes)
COMPAT_SYS(statfs64)
diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h
index 1f7ecdb..9c550b3 100644
--- a/include/asm-powerpc/ptrace.h
+++ b/include/asm-powerpc/ptrace.h
@@ -87,7 +87,7 @@ extern unsigned long profile_pc(struct p
#define force_successful_syscall_return() \
do { \
- current_thread_info()->syscall_noerror = 1; \
+ set_thread_flag(TIF_NOERROR); \
} while(0)
/*
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index e525f49..ac1e80e 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -37,8 +37,7 @@ struct thread_info {
int preempt_count; /* 0 => preemptable,
<0 => BUG */
struct restart_block restart_block;
- /* set by force_successful_syscall_return */
- unsigned char syscall_noerror;
+ void *nvgprs_frame;
/* low level flags - has atomic operations done on it */
unsigned long flags ____cacheline_aligned_in_smp;
};
@@ -123,6 +122,9 @@ static inline struct thread_info *curren
#define TIF_SINGLESTEP 9 /* singlestepping active */
#define TIF_MEMDIE 10
#define TIF_SECCOMP 11 /* secure computing */
+#define TIF_RESTOREALL 12 /* Restore all regs (implies NOERROR) */
+#define TIF_SAVE_NVGPRS 13 /* Save r14-r31 in signal frame */
+#define TIF_NOERROR 14 /* Force successful syscall return */
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -136,10 +138,14 @@ static inline struct thread_info *curren
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+#define _TIF_RESTOREALL (1<<TIF_RESTOREALL)
+#define _TIF_SAVE_NVGPRS (1<<TIF_SAVE_NVGPRS)
+#define _TIF_NOERROR (1<<TIF_NOERROR)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
- _TIF_NEED_RESCHED)
+ _TIF_NEED_RESCHED | _TIF_RESTOREALL)
+#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR|_TIF_SAVE_NVGPRS)
#endif /* __KERNEL__ */
Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/devel/kernel-2.6.spec,v
retrieving revision 1.1677
retrieving revision 1.1678
diff -u -r1.1677 -r1.1678
--- kernel-2.6.spec 15 Nov 2005 17:34:30 -0000 1.1677
+++ kernel-2.6.spec 15 Nov 2005 17:55:25 -0000 1.1678
@@ -220,6 +220,8 @@
Patch301: linux-2.6-ppc64-eeh-panic.patch
Patch302: linux-2.6-serial-of.patch
Patch303: linux-2.6.15-rc1-ppc-vdso-2.patch
+Patch304: linux-2.6.15-rc1-ppc64-syscallpath.patch
+Patch305: linux-2.6.15-rc1-ppc64-pci.patch
# 400 - 499 ia64
# 500 - 599 s390(x)
@@ -598,6 +600,8 @@
# Don't probe serial ports if they don't exist
%patch302 -p1
%patch303 -p1
+%patch304 -p1
+%patch305 -p1
#
# Xen
@@ -1295,6 +1299,10 @@
%endif
%changelog
+* Tue Nov 15 2005 David Woodhouse <dwmw2 at redhat.com>
+- Revamp ppc32 and ppc64 system call entry/exit paths
+- Fix up PCI initialisation on ppc64 to prevent parport_pc killing G5s
+
* Tue Nov 15 2005 Dave Jones <davej at redhat.com>
- 2.6.15-rc1-git3
- Make lrmi using apps (ddcprobe et al) work again.
More information about the fedora-cvs-commits
mailing list