[Linux-ia64] kernel update (relative to 2.4.0-test9)

David Mosberger
2000-10-31T08:55:03Z

Here is a quick kernel update. I anticipate another update shortly
after Linus releases test10. Thus, this patch hasn't received as much
testing as I usually do. The kernel is known to work fine on 2P Big
Sur and a slightly earlier version also worked fine on Lion and the
simulator. As usual, YMMV.

Summary of changes:

- Asit & Goutham: fixed IOSAPIC support to work correctly when
irq lines are shared by PCI devices
- Asit: fix to unaligned access handler
- Goutham: workaround for lost IPI problem
- Don: IA-32 fixes & updates, in particular the beginnings of
DRM support
- Takayoshi: early-printk fixes to kernel startup code
- Jun: optimized copy_user() for case where pointers are not co-aligned
- Johannes: add VM_NONCACHED and VM_WRITECOMBINE for /dev/mem
- Christophe: fixed unaligned accesses in Tulip (21140) NIC
- BJ: update qla1280 driver to v3.19
- Intel: huge ACPI update (it's not in the diff below; go get the
full patch to get this part)
- Stephane: many performance related updates & fixes; in particular,
the API is now entirely perfmonctl() based (no more ptrace() hacks
needed)
- drop platform_register_iosapic()---it's no longer needed
- add workaround for potential ITC discontiguity
- "backported" ftruncate() fix that caused kernel crash
with certain filesystem stress tests
- memcpy: tuned it some more
- remove off workaround for unsorted unwind tables---it's no longer
needed with the latest toolchain (thanks to Rich!)
- separated IOSAPIC support from DIG, added some documentation,
and restructured the code to make it (hopefully) more readable;
also removed all (hard) IOSAPIC dependencies from acpi code
- dropped BAD_ACPI_TABLE workaround; if you're still running
old Lion firmware, this might bite you; if so, please upgrade
the firmware (I don't think very many systems were shipped
with the broken firmware, so I expect few if any people to
be affected by this)
- added AT_CLKTCK support for ELF binaries

I hope I didn't miss anything. For the full patch, see:

ftp://ftp.kernel.org/pub/linux/kernel/ports/ia64/

as usual.

--david

diff -urN linux-davidm/arch/ia64/dig/dig_irq.c lia64/arch/ia64/dig/dig_irq.c
--- linux-davidm/arch/ia64/dig/dig_irq.c Wed Dec 31 16:00:00 1969
+++ lia64/arch/ia64/dig/dig_irq.c Mon Oct 30 23:40:05 2000
@@ -0,0 +1,10 @@
+void
+dig_irq_init (void)
+{
+ /*
+ * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
+ * enabled.
+ */
+ outb(0xff, 0xA1);
+ outb(0xff, 0x21);
+}
diff -urN linux-davidm/arch/ia64/dig/iosapic.c lia64/arch/ia64/dig/iosapic.c
--- linux-davidm/arch/ia64/dig/iosapic.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/dig/iosapic.c Wed Dec 31 16:00:00 1969
@@ -1,409 +0,0 @@
-/*
- * Streamlined APIC support.
- *
- * Copyright (C) 1999 Intel Corp.
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 1999-2000 Hewlett-Packard Co.
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
- *
- * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O APIC code.
- * In particular, we now have separate handlers for edge
- * and level triggered interrupts.
- */
-#include <linux/config.h>
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/string.h>
-#include <linux/irq.h>
-
-#include <asm/acpi-ext.h>
-#include <asm/delay.h>
-#include <asm/io.h>
-#include <asm/iosapic.h>
-#include <asm/machvec.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/system.h>
-
-#ifdef CONFIG_ACPI_KERNEL_CONFIG
-# include <asm/acpikcfg.h>
-#endif
-
-#undef DEBUG_IRQ_ROUTING
-
-static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
-
-struct iosapic_vector iosapic_vector[NR_IRQS] = {
- [0 ... NR_IRQS-1] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
-};
-
-/*
- * find the IRQ in the IOSAPIC map for the PCI device on bus/slot/pin
- */
-int
-iosapic_get_PCI_irq_vector (int bus, int slot, int pci_pin)
-{
- int i;
-
- for (i = 0; i < NR_IRQS; i++) {
- if ((iosapic_bustype(i) = BUS_PCI) &&
- (iosapic_bus(i) = bus) &&
- (iosapic_busdata(i) = ((slot << 16) | pci_pin))) {
- return i;
- }
- }
- return -1;
-}
-
-static void
-set_rte (unsigned long iosapic_addr, int entry, int pol, int trigger, int delivery,
- long dest, int vector)
-{
- u32 low32;
- u32 high32;
-
- low32 = ((pol << IO_SAPIC_POLARITY_SHIFT) |
- (trigger << IO_SAPIC_TRIGGER_SHIFT) |
- (delivery << IO_SAPIC_DELIVERY_SHIFT) |
- vector);
-
-#ifdef CONFIG_IA64_AZUSA_HACKS
- /* set Flush Disable bit */
- if (iosapic_addr != 0xc0000000fec00000)
- low32 |= (1 << 17);
-#endif
-
- /* dest contains both id and eid */
- high32 = (dest << IO_SAPIC_DEST_SHIFT);
-
- writel(IO_SAPIC_RTE_HIGH(entry), iosapic_addr + IO_SAPIC_REG_SELECT);
- writel(high32, iosapic_addr + IO_SAPIC_WINDOW);
- writel(IO_SAPIC_RTE_LOW(entry), iosapic_addr + IO_SAPIC_REG_SELECT);
- writel(low32, iosapic_addr + IO_SAPIC_WINDOW);
-}
-
-static void
-nop (unsigned int irq)
-{
- /* do nothing... */
-}
-
-static void
-mask_irq (unsigned int irq)
-{
- unsigned long flags, iosapic_addr = iosapic_addr(irq);
- u32 low32;
-
- spin_lock_irqsave(&iosapic_lock, flags);
- {
- writel(IO_SAPIC_RTE_LOW(iosapic_pin(irq)), iosapic_addr + IO_SAPIC_REG_SELECT);
- low32 = readl(iosapic_addr + IO_SAPIC_WINDOW);
-
- low32 |= (1 << IO_SAPIC_MASK_SHIFT); /* Zero only the mask bit */
- writel(low32, iosapic_addr + IO_SAPIC_WINDOW);
- }
- spin_unlock_irqrestore(&iosapic_lock, flags);
-}
-
-static void
-unmask_irq (unsigned int irq)
-{
- unsigned long flags, iosapic_addr = iosapic_addr(irq);
- u32 low32;
-
- spin_lock_irqsave(&iosapic_lock, flags);
- {
- writel(IO_SAPIC_RTE_LOW(iosapic_pin(irq)), iosapic_addr + IO_SAPIC_REG_SELECT);
- low32 = readl(iosapic_addr + IO_SAPIC_WINDOW);
-
- low32 &= ~(1 << IO_SAPIC_MASK_SHIFT); /* Zero only the mask bit */
- writel(low32, iosapic_addr + IO_SAPIC_WINDOW);
- }
- spin_unlock_irqrestore(&iosapic_lock, flags);
-}
-
-
-static void
-iosapic_set_affinity (unsigned int irq, unsigned long mask)
-{
- printk("iosapic_set_affinity: not implemented yet\n");
-}
-
-/*
- * Handlers for level-triggered interrupts.
- */
-
-static unsigned int
-iosapic_startup_level_irq (unsigned int irq)
-{
- unmask_irq(irq);
- return 0;
-}
-
-static void
-iosapic_end_level_irq (unsigned int irq)
-{
- writel(irq, iosapic_addr(irq) + IO_SAPIC_EOI);
-}
-
-#define iosapic_shutdown_level_irq mask_irq
-#define iosapic_enable_level_irq unmask_irq
-#define iosapic_disable_level_irq mask_irq
-#define iosapic_ack_level_irq nop
-
-struct hw_interrupt_type irq_type_iosapic_level = {
- typename: "IO-SAPIC-level",
- startup: iosapic_startup_level_irq,
- shutdown: iosapic_shutdown_level_irq,
- enable: iosapic_enable_level_irq,
- disable: iosapic_disable_level_irq,
- ack: iosapic_ack_level_irq,
- end: iosapic_end_level_irq,
- set_affinity: iosapic_set_affinity
-};
-
-/*
- * Handlers for edge-triggered interrupts.
- */
-
-static unsigned int
-iosapic_startup_edge_irq (unsigned int irq)
-{
- unmask_irq(irq);
- /*
- * IOSAPIC simply drops interrupts pended while the
- * corresponding pin was masked, so we can't know if an
- * interrupt is pending already. Let's hope not...
- */
- return 0;
-}
-
-static void
-iosapic_ack_edge_irq (unsigned int irq)
-{
- /*
- * Once we have recorded IRQ_PENDING already, we can mask the
- * interrupt for real. This prevents IRQ storms from unhandled
- * devices.
- */
- if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED)) = (IRQ_PENDING | IRQ_DISABLED))
- mask_irq(irq);
-}
-
-#define iosapic_enable_edge_irq unmask_irq
-#define iosapic_disable_edge_irq nop
-#define iosapic_end_edge_irq nop
-
-struct hw_interrupt_type irq_type_iosapic_edge = {
- typename: "IO-SAPIC-edge",
- startup: iosapic_startup_edge_irq,
- shutdown: iosapic_disable_edge_irq,
- enable: iosapic_enable_edge_irq,
- disable: iosapic_disable_edge_irq,
- ack: iosapic_ack_edge_irq,
- end: iosapic_end_edge_irq,
- set_affinity: iosapic_set_affinity
-};
-
-unsigned int
-iosapic_version (unsigned long base_addr)
-{
- /*
- * IOSAPIC Version Register return 32 bit structure like:
- * {
- * unsigned int version : 8;
- * unsigned int reserved1 : 8;
- * unsigned int pins : 8;
- * unsigned int reserved2 : 8;
- * }
- */
- writel(IO_SAPIC_VERSION, base_addr + IO_SAPIC_REG_SELECT);
- return readl(IO_SAPIC_WINDOW + base_addr);
-}
-
-void
-iosapic_init (unsigned long address, int irqbase)
-{
- struct hw_interrupt_type *irq_type;
- struct pci_vector_struct *vectors;
- int i, irq, num_pci_vectors;
-
- if (irqbase = 0)
- /*
- * Map the legacy ISA devices into the IOSAPIC data.
- * Some of these may get reprogrammed later on with
- * data from the ACPI Interrupt Source Override table.
- */
- for (i = 0; i < 16; i++) {
- irq = isa_irq_to_vector(i);
- iosapic_pin(irq) = i;
- iosapic_bus(irq) = BUS_ISA;
- iosapic_busdata(irq) = 0;
- iosapic_dmode(irq) = IO_SAPIC_LOWEST_PRIORITY;
- iosapic_trigger(irq) = IO_SAPIC_EDGE;
- iosapic_polarity(irq) = IO_SAPIC_POL_HIGH;
-#ifdef DEBUG_IRQ_ROUTING
- printk("ISA: IRQ %02x -> Vector %02x IOSAPIC Pin %d\n",
- i, irq, iosapic_pin(irq));
-#endif
- }
-
-#ifndef CONFIG_IA64_SOFTSDV_HACKS
- /*
- * Map the PCI Interrupt data into the ACPI IOSAPIC data using
- * the info that the bootstrap loader passed to us.
- */
-# ifdef CONFIG_ACPI_KERNEL_CONFIG
- acpi_cf_get_pci_vectors(&vectors, &num_pci_vectors);
-# else
- ia64_boot_param.pci_vectors = (__u64) __va(ia64_boot_param.pci_vectors);
- vectors = (struct pci_vector_struct *) ia64_boot_param.pci_vectors;
- num_pci_vectors = ia64_boot_param.num_pci_vectors;
-# endif
- for (i = 0; i < num_pci_vectors; i++) {
- irq = vectors[i].irq;
- if (irq < 16)
- irq = isa_irq_to_vector(irq);
- if (iosapic_baseirq(irq) != irqbase)
- continue;
-
- iosapic_bustype(irq) = BUS_PCI;
- iosapic_pin(irq) = irq - iosapic_baseirq(irq);
- iosapic_bus(irq) = vectors[i].bus;
- /*
- * Map the PCI slot and pin data into iosapic_busdata()
- */
- iosapic_busdata(irq) = (vectors[i].pci_id & 0xffff0000) | vectors[i].pin;
-
- /* Default settings for PCI */
- iosapic_dmode(irq) = IO_SAPIC_LOWEST_PRIORITY;
- iosapic_trigger(irq) = IO_SAPIC_LEVEL;
- iosapic_polarity(irq) = IO_SAPIC_POL_LOW;
-
-# ifdef DEBUG_IRQ_ROUTING
- printk("PCI: BUS %d Slot %x Pin %x IRQ %02x --> Vector %02x IOSAPIC Pin %d\n",
- vectors[i].bus, vectors[i].pci_id>>16, vectors[i].pin, vectors[i].irq,
- irq, iosapic_pin(irq));
-# endif
- }
-#endif /* CONFIG_IA64_SOFTSDV_HACKS */
-
- for (i = 0; i < NR_IRQS; ++i) {
- if (iosapic_baseirq(i) != irqbase)
- continue;
-
- if (iosapic_pin(i) != -1) {
- if (iosapic_trigger(i) = IO_SAPIC_LEVEL)
- irq_type = &irq_type_iosapic_level;
- else
- irq_type = &irq_type_iosapic_edge;
- if (irq_desc[i].handler != &no_irq_type)
- printk("dig_irq_init: warning: changing vector %d from %s to %s\n",
- i, irq_desc[i].handler->typename,
- irq_type->typename);
- irq_desc[i].handler = irq_type;
-
- /* program the IOSAPIC routing table: */
- set_rte(iosapic_addr(i), iosapic_pin(i), iosapic_polarity(i),
- iosapic_trigger(i), iosapic_dmode(i),
- (ia64_get_lid() >> 16) & 0xffff, i);
- }
- }
-}
-
-void
-dig_irq_init (void)
-{
- /*
- * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
- * enabled.
- */
- outb(0xff, 0xA1);
- outb(0xff, 0x21);
-}
-
-void
-dig_pci_fixup (void)
-{
- struct pci_dev *dev;
- int irq;
- unsigned char pin;
-
- pci_for_each_dev(dev) {
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
- if (pin) {
- pin--; /* interrupt pins are numbered starting from 1 */
- irq = iosapic_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn),
- pin);
- if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
- struct pci_dev * bridge = dev->bus->self;
-
- /* allow for multiple bridges on an adapter */
- do {
- /* do the bridge swizzle... */
- pin = (pin + PCI_SLOT(dev->devfn)) % 4;
- irq = iosapic_get_PCI_irq_vector(bridge->bus->number,
- PCI_SLOT(bridge->devfn), pin);
- } while (irq < 0 && (bridge = bridge->bus->self));
- if (irq >= 0)
- printk(KERN_WARNING
- "PCI: using PPB(B%d,I%d,P%d) to get irq %02x\n",
- bridge->bus->number, PCI_SLOT(bridge->devfn),
- pin, irq);
- else
- printk(KERN_WARNING
- "PCI: Couldn't map irq for B%d,I%d,P%d\n",
- bridge->bus->number, PCI_SLOT(bridge->devfn),
- pin);
- }
- if (irq >= 0) {
- printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %02x\n",
- dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
- dev->irq = irq;
- }
- }
- /*
- * Nothing to fixup
- * Fix out-of-range IRQ numbers
- */
- if (dev->irq >= NR_IRQS)
- dev->irq = 15; /* Spurious interrupts */
- }
-}
-
-/*
- * Register an IOSAPIC discovered via ACPI.
- */
-void __init
-dig_register_iosapic (acpi_entry_iosapic_t *iosapic)
-{
- unsigned int ver, v;
- int l, max_pin;
-
- ver = iosapic_version((unsigned long) ioremap(iosapic->address, 0));
- max_pin = (ver >> 16) & 0xff;
-
- printk("IOSAPIC Version %x.%x: address 0x%lx IRQs 0x%x - 0x%x\n",
- (ver & 0xf0) >> 4, (ver & 0x0f), iosapic->address,
- iosapic->irq_base, iosapic->irq_base + max_pin);
-
- for (l = 0; l <= max_pin; l++) {
- v = iosapic->irq_base + l;
- if (v < 16)
- v = isa_irq_to_vector(v);
- if (v > IA64_MAX_VECTORED_IRQ) {
- printk(" !!! bad IOSAPIC interrupt vector: %u\n", v);
- continue;
- }
- /* XXX Check for IOSAPIC collisions */
- iosapic_addr(v) = (unsigned long) ioremap(iosapic->address, 0);
- iosapic_baseirq(v) = iosapic->irq_base;
- }
- iosapic_init(iosapic->address, iosapic->irq_base);
-}
diff -urN linux-davidm/arch/ia64/dig/setup.c lia64/arch/ia64/dig/setup.c
--- linux-davidm/arch/ia64/dig/setup.c Thu Aug 24 08:17:30 2000
+++ lia64/arch/ia64/dig/setup.c Mon Oct 30 22:28:55 2000
@@ -84,3 +84,14 @@
screen_info.orig_video_isVGA = 1; /* XXX fake */
screen_info.orig_video_ega_bx = 3; /* XXX fake */
}
+
+void
+dig_irq_init (void)
+{
+ /*
+ * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
+ * enabled.
+ */
+ outb(0xff, 0xA1);
+ outb(0xff, 0x21);
+}
diff -urN linux-davidm/arch/ia64/ia32/binfmt_elf32.c lia64/arch/ia64/ia32/binfmt_elf32.c
--- linux-davidm/arch/ia64/ia32/binfmt_elf32.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/ia32/binfmt_elf32.c Mon Oct 30 22:29:21 2000
@@ -9,6 +9,7 @@

#include <linux/types.h>

+#include <asm/param.h>
#include <asm/signal.h>
#include <asm/ia32.h>

@@ -31,6 +32,9 @@
# define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE
#endif

+#undef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC IA32_CLOCKS_PER_SEC
+
extern void ia64_elf32_init(struct pt_regs *regs);
extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address);

@@ -239,6 +243,12 @@
if (eppnt->p_memsz >= (1UL<<32) || addr > (1UL<<32) - eppnt->p_memsz)
return -EINVAL;

+ /*
+ * Make sure the elf interpreter doesn't get loaded at location 0
+ * so that NULL pointers correctly cause segfaults.
+ */
+ if (addr = 0)
+ addr += PAGE_SIZE;
#if 1
set_brk(ia32_mm_addr(addr), addr + eppnt->p_memsz);
memset((char *) addr + eppnt->p_filesz, 0, eppnt->p_memsz - eppnt->p_filesz);
diff -urN linux-davidm/arch/ia64/ia32/ia32_entry.S lia64/arch/ia64/ia32/ia32_entry.S
--- linux-davidm/arch/ia64/ia32/ia32_entry.S Fri Sep 8 14:34:53 2000
+++ lia64/arch/ia64/ia32/ia32_entry.S Mon Oct 30 22:29:33 2000
@@ -291,11 +291,43 @@
data8 sys_getcwd
data8 sys_capget
data8 sys_capset /* 185 */
- data8 sys_sigaltstack
+ data8 sys32_sigaltstack
data8 sys_sendfile
data8 sys32_ni_syscall /* streams1 */
data8 sys32_ni_syscall /* streams2 */
data8 sys32_vfork /* 190 */
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall /* 195 */
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall /* 200 */
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall /* 205 */
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall /* 210 */
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall /* 215 */
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall /* 220 */
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
/*
* CAUTION: If any system calls are added beyond this point
* then the check in `arch/ia64/kernel/ivt.S' will have
diff -urN linux-davidm/arch/ia64/ia32/ia32_ioctl.c lia64/arch/ia64/ia32/ia32_ioctl.c
--- linux-davidm/arch/ia64/ia32/ia32_ioctl.c Wed Aug 2 18:54:01 2000
+++ lia64/arch/ia64/ia32/ia32_ioctl.c Mon Oct 30 22:29:51 2000
@@ -22,81 +22,158 @@
#include <linux/if_ppp.h>
#include <linux/ixjuser.h>
#include <linux/i2o-dev.h>
+#include <../drivers/char/drm/drm.h>
+
+#define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
+
+#define DO_IOCTL(fd, cmd, arg) ({ \
+ int _ret; \
+ mm_segment_t _old_fs = get_fs(); \
+ \
+ set_fs(KERNEL_DS); \
+ _ret = sys_ioctl(fd, cmd, (unsigned long)arg); \
+ set_fs(_old_fs); \
+ _ret; \
+})
+
+#define P(i) ((void *)(long)(i))
+

asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);

asmlinkage long ia32_ioctl(unsigned int fd, unsigned int cmd, unsigned int arg)
{
+ long ret;
+
+ switch (IOCTL_NR(cmd)) {
+
+ case IOCTL_NR(DRM_IOCTL_VERSION):
+ break;
+ case IOCTL_NR(DRM_IOCTL_GET_UNIQUE):
+ {
+ drm_unique_t un;
+ struct {
+ unsigned int unique_len;
+ unsigned int unique;
+ } un32;
+
+ if (copy_from_user(&un32, P(arg), sizeof(un32)))
+ return -EFAULT;
+ un.unique_len = un32.unique_len;
+ un.unique = P(un32.unique);
+ ret = DO_IOCTL(fd, cmd, &un);
+ if (ret >= 0) {
+ un32.unique_len = un.unique_len;
+ if (copy_to_user(P(arg), &un32, sizeof(un32)))
+ return -EFAULT;
+ }
+ return(ret);
+ }
+ case IOCTL_NR(DRM_IOCTL_SET_UNIQUE):
+ case IOCTL_NR(DRM_IOCTL_ADD_MAP):
+ case IOCTL_NR(DRM_IOCTL_ADD_BUFS):
+ case IOCTL_NR(DRM_IOCTL_MARK_BUFS):
+ case IOCTL_NR(DRM_IOCTL_INFO_BUFS):
+ case IOCTL_NR(DRM_IOCTL_MAP_BUFS):
+ case IOCTL_NR(DRM_IOCTL_FREE_BUFS):
+ case IOCTL_NR(DRM_IOCTL_ADD_CTX):
+ case IOCTL_NR(DRM_IOCTL_RM_CTX):
+ case IOCTL_NR(DRM_IOCTL_MOD_CTX):
+ case IOCTL_NR(DRM_IOCTL_GET_CTX):
+ case IOCTL_NR(DRM_IOCTL_SWITCH_CTX):
+ case IOCTL_NR(DRM_IOCTL_NEW_CTX):
+ case IOCTL_NR(DRM_IOCTL_RES_CTX):
+
+ case IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE):
+ case IOCTL_NR(DRM_IOCTL_AGP_RELEASE):
+ case IOCTL_NR(DRM_IOCTL_AGP_ENABLE):
+ case IOCTL_NR(DRM_IOCTL_AGP_INFO):
+ case IOCTL_NR(DRM_IOCTL_AGP_ALLOC):
+ case IOCTL_NR(DRM_IOCTL_AGP_FREE):
+ case IOCTL_NR(DRM_IOCTL_AGP_BIND):
+ case IOCTL_NR(DRM_IOCTL_AGP_UNBIND):
+
+ /* Mga specific ioctls */
+
+ case IOCTL_NR(DRM_IOCTL_MGA_INIT):
+
+ /* I810 specific ioctls */
+
+ case IOCTL_NR(DRM_IOCTL_I810_GETBUF):
+ case IOCTL_NR(DRM_IOCTL_I810_COPY):
+
+ /* Rage 128 specific ioctls */

- switch (cmd) {
+ case IOCTL_NR(DRM_IOCTL_R128_PACKET):

- case VFAT_IOCTL_READDIR_BOTH:
- case VFAT_IOCTL_READDIR_SHORT:
- case MTIOCGET:
- case MTIOCPOS:
- case MTIOCGETCONFIG:
- case MTIOCSETCONFIG:
- case PPPIOCSCOMPRESS:
- case PPPIOCGIDLE:
- case NCP_IOC_GET_FS_INFO_V2:
- case NCP_IOC_GETOBJECTNAME:
- case NCP_IOC_SETOBJECTNAME:
- case NCP_IOC_GETPRIVATEDATA:
- case NCP_IOC_SETPRIVATEDATA:
- case NCP_IOC_GETMOUNTUID2:
- case CAPI_MANUFACTURER_CMD:
- case VIDIOCGTUNER:
- case VIDIOCSTUNER:
- case VIDIOCGWIN:
- case VIDIOCSWIN:
- case VIDIOCGFBUF:
- case VIDIOCSFBUF:
- case MGSL_IOCSPARAMS:
- case MGSL_IOCGPARAMS:
- case ATM_GETNAMES:
- case ATM_GETLINKRATE:
- case ATM_GETTYPE:
- case ATM_GETESI:
- case ATM_GETADDR:
- case ATM_RSTADDR:
- case ATM_ADDADDR:
- case ATM_DELADDR:
- case ATM_GETCIRANGE:
- case ATM_SETCIRANGE:
- case ATM_SETESI:
- case ATM_SETESIF:
- case ATM_GETSTAT:
- case ATM_GETSTATZ:
- case ATM_GETLOOP:
- case ATM_SETLOOP:
- case ATM_QUERYLOOP:
- case ENI_SETMULT:
- case NS_GETPSTAT:
- /* case NS_SETBUFLEV: This is a duplicate case with ZATM_GETPOOLZ */
- case ZATM_GETPOOLZ:
- case ZATM_GETPOOL:
- case ZATM_SETPOOL:
- case ZATM_GETTHIST:
- case IDT77105_GETSTAT:
- case IDT77105_GETSTATZ:
- case IXJCTL_TONE_CADENCE:
- case IXJCTL_FRAMES_READ:
- case IXJCTL_FRAMES_WRITTEN:
- case IXJCTL_READ_WAIT:
- case IXJCTL_WRITE_WAIT:
- case IXJCTL_DRYBUFFER_READ:
- case I2OHRTGET:
- case I2OLCTGET:
- case I2OPARMSET:
- case I2OPARMGET:
- case I2OSWDL:
- case I2OSWUL:
- case I2OSWDEL:
- case I2OHTML:
- printk("%x:unimplemented IA32 ioctl system call\n", cmd);
- return(-EINVAL);
+ case IOCTL_NR(VFAT_IOCTL_READDIR_BOTH):
+ case IOCTL_NR(VFAT_IOCTL_READDIR_SHORT):
+ case IOCTL_NR(MTIOCGET):
+ case IOCTL_NR(MTIOCPOS):
+ case IOCTL_NR(MTIOCGETCONFIG):
+ case IOCTL_NR(MTIOCSETCONFIG):
+ case IOCTL_NR(PPPIOCSCOMPRESS):
+ case IOCTL_NR(PPPIOCGIDLE):
+ case IOCTL_NR(NCP_IOC_GET_FS_INFO_V2):
+ case IOCTL_NR(NCP_IOC_GETOBJECTNAME):
+ case IOCTL_NR(NCP_IOC_SETOBJECTNAME):
+ case IOCTL_NR(NCP_IOC_GETPRIVATEDATA):
+ case IOCTL_NR(NCP_IOC_SETPRIVATEDATA):
+ case IOCTL_NR(NCP_IOC_GETMOUNTUID2):
+ case IOCTL_NR(CAPI_MANUFACTURER_CMD):
+ case IOCTL_NR(VIDIOCGTUNER):
+ case IOCTL_NR(VIDIOCSTUNER):
+ case IOCTL_NR(VIDIOCGWIN):
+ case IOCTL_NR(VIDIOCSWIN):
+ case IOCTL_NR(VIDIOCGFBUF):
+ case IOCTL_NR(VIDIOCSFBUF):
+ case IOCTL_NR(MGSL_IOCSPARAMS):
+ case IOCTL_NR(MGSL_IOCGPARAMS):
+ case IOCTL_NR(ATM_GETNAMES):
+ case IOCTL_NR(ATM_GETLINKRATE):
+ case IOCTL_NR(ATM_GETTYPE):
+ case IOCTL_NR(ATM_GETESI):
+ case IOCTL_NR(ATM_GETADDR):
+ case IOCTL_NR(ATM_RSTADDR):
+ case IOCTL_NR(ATM_ADDADDR):
+ case IOCTL_NR(ATM_DELADDR):
+ case IOCTL_NR(ATM_GETCIRANGE):
+ case IOCTL_NR(ATM_SETCIRANGE):
+ case IOCTL_NR(ATM_SETESI):
+ case IOCTL_NR(ATM_SETESIF):
+ case IOCTL_NR(ATM_GETSTAT):
+ case IOCTL_NR(ATM_GETSTATZ):
+ case IOCTL_NR(ATM_GETLOOP):
+ case IOCTL_NR(ATM_SETLOOP):
+ case IOCTL_NR(ATM_QUERYLOOP):
+ case IOCTL_NR(ENI_SETMULT):
+ case IOCTL_NR(NS_GETPSTAT):
+ /* case IOCTL_NR(NS_SETBUFLEV): This is a duplicate case with ZATM_GETPOOLZ */
+ case IOCTL_NR(ZATM_GETPOOLZ):
+ case IOCTL_NR(ZATM_GETPOOL):
+ case IOCTL_NR(ZATM_SETPOOL):
+ case IOCTL_NR(ZATM_GETTHIST):
+ case IOCTL_NR(IDT77105_GETSTAT):
+ case IOCTL_NR(IDT77105_GETSTATZ):
+ case IOCTL_NR(IXJCTL_TONE_CADENCE):
+ case IOCTL_NR(IXJCTL_FRAMES_READ):
+ case IOCTL_NR(IXJCTL_FRAMES_WRITTEN):
+ case IOCTL_NR(IXJCTL_READ_WAIT):
+ case IOCTL_NR(IXJCTL_WRITE_WAIT):
+ case IOCTL_NR(IXJCTL_DRYBUFFER_READ):
+ case IOCTL_NR(I2OHRTGET):
+ case IOCTL_NR(I2OLCTGET):
+ case IOCTL_NR(I2OPARMSET):
+ case IOCTL_NR(I2OPARMGET):
+ case IOCTL_NR(I2OSWDL):
+ case IOCTL_NR(I2OSWUL):
+ case IOCTL_NR(I2OSWDEL):
+ case IOCTL_NR(I2OHTML):
+ break;
default:
return(sys_ioctl(fd, cmd, (unsigned long)arg));

}
+ printk("%x:unimplemented IA32 ioctl system call\n", cmd);
+ return(-EINVAL);
}
diff -urN linux-davidm/arch/ia64/ia32/ia32_traps.c lia64/arch/ia64/ia32/ia32_traps.c
--- linux-davidm/arch/ia64/ia32/ia32_traps.c Thu Jun 22 07:09:44 2000
+++ lia64/arch/ia64/ia32/ia32_traps.c Mon Oct 30 22:30:04 2000
@@ -119,6 +119,6 @@
default:
return -1;
}
- force_sig_info(SIGTRAP, &siginfo, current);
+ force_sig_info(siginfo.si_signo, &siginfo, current);
return 0;
}
diff -urN linux-davidm/arch/ia64/ia32/sys_ia32.c lia64/arch/ia64/ia32/sys_ia32.c
--- linux-davidm/arch/ia64/ia32/sys_ia32.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/ia32/sys_ia32.c Mon Oct 30 22:32:34 2000
@@ -236,8 +236,6 @@

if (OFFSET4K(addr) || OFFSET4K(off))
return -EINVAL;
- if (prot & PROT_WRITE)
- prot |= PROT_EXEC;
prot |= PROT_WRITE;
front = NULL;
back = NULL;
@@ -287,23 +285,20 @@
unsigned int poff;

flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ prot |= PROT_EXEC;

if ((flags & MAP_FIXED) && ((addr & ~PAGE_MASK) || (offset & ~PAGE_MASK)))
error = do_mmap_fake(file, addr, len, prot, flags, (loff_t)offset);
- else if (!addr && (offset & ~PAGE_MASK)) {
+ else {
poff = offset & PAGE_MASK;
len += offset - poff;

down(&current->mm->mmap_sem);
- error = do_mmap(file, addr, len, prot, flags, poff);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, poff >> PAGE_SHIFT);
up(&current->mm->mmap_sem);

if (!IS_ERR((void *) error))
error += offset - poff;
- } else {
- down(&current->mm->mmap_sem);
- error = do_mmap(file, addr, len, prot, flags, offset);
- up(&current->mm->mmap_sem);
}
return error;
}
@@ -2032,14 +2027,14 @@
ret = sys_times(tbuf ? &t : NULL);
set_fs (old_fs);
if (tbuf) {
- err = put_user (t.tms_utime, &tbuf->tms_utime);
- err |= __put_user (t.tms_stime, &tbuf->tms_stime);
- err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
- err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
+ err = put_user (IA32_TICK(t.tms_utime), &tbuf->tms_utime);
+ err |= __put_user (IA32_TICK(t.tms_stime), &tbuf->tms_stime);
+ err |= __put_user (IA32_TICK(t.tms_cutime), &tbuf->tms_cutime);
+ err |= __put_user (IA32_TICK(t.tms_cstime), &tbuf->tms_cstime);
if (err)
ret = -EFAULT;
}
- return ret;
+ return IA32_TICK(ret);
}

unsigned int
@@ -2617,6 +2612,45 @@
* manipulating the page protections...
*/
return(sys_iopl(3, 0, 0, 0));
+}
+
+typedef struct {
+ unsigned int ss_sp;
+ unsigned int ss_flags;
+ unsigned int ss_size;
+} ia32_stack_t;
+
+asmlinkage long
+sys32_sigaltstack (const ia32_stack_t *uss32, ia32_stack_t *uoss32,
+long arg2, long arg3, long arg4,
+long arg5, long arg6, long arg7,
+long stack)
+{
+ struct pt_regs *pt = (struct pt_regs *) &stack;
+ stack_t uss, uoss;
+ ia32_stack_t buf32;
+ int ret;
+ mm_segment_t old_fs = get_fs();
+
+ if (uss32)
+ if (copy_from_user(&buf32, (void *)A(uss32), sizeof(ia32_stack_t)))
+ return(-EFAULT);
+ uss.ss_sp = buf32.ss_sp;
+ uss.ss_flags = buf32.ss_flags;
+ uss.ss_size = buf32.ss_size;
+ set_fs(KERNEL_DS);
+ ret = do_sigaltstack(uss32 ? &uss : NULL, &uoss, pt->r12);
+ set_fs(old_fs);
+ if (ret < 0)
+ return(ret);
+ if (uoss32) {
+ buf32.ss_sp = uoss.ss_sp;
+ buf32.ss_flags = uoss.ss_flags;
+ buf32.ss_size = uoss.ss_size;
+ if (copy_to_user((void*)A(uoss32), &buf32, sizeof(ia32_stack_t)))
+ return(-EFAULT);
+ }
+ return(ret);
}

#ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */
diff -urN linux-davidm/arch/ia64/kernel/Makefile lia64/arch/ia64/kernel/Makefile
--- linux-davidm/arch/ia64/kernel/Makefile Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/Makefile Mon Oct 30 22:33:15 2000
@@ -13,7 +13,8 @@
machvec.o pal.o pci-dma.o process.o perfmon.o ptrace.o sal.o semaphore.o setup.o \
signal.o sys_ia64.o traps.o time.o unaligned.o unwind.o

-obj-$(CONFIG_IA64_GENERIC) += machvec.o
+obj-$(CONFIG_IA64_GENERIC) += machvec.o iosapic.o
+obj-$(CONFIG_IA64_DIG) += iosapic.o
obj-$(CONFIG_IA64_PALINFO) += palinfo.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_SMP) += smp.o smpboot.o
@@ -21,7 +22,7 @@
obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o

O_TARGET := kernel.o
-O_OBJS := $(obj-y)
+O_OBJS := $(obj-y)
OX_OBJS := ia64_ksyms.o

clean::
diff -urN linux-davidm/arch/ia64/kernel/acpi.c lia64/arch/ia64/kernel/acpi.c
--- linux-davidm/arch/ia64/kernel/acpi.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/acpi.c Mon Oct 30 22:33:27 2000
@@ -6,6 +6,8 @@
*
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 2000 Hewlett-Packard Co.
+ * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
*/

#include <linux/config.h>
@@ -36,11 +38,14 @@

void (*pm_idle)(void);

+asm (".weak iosapic_register_legacy_irq");
+asm (".weak iosapic_init");
+
/*
* Identify usable CPU's and remember them for SMP bringup later.
*/
static void __init
-acpi_lsapic(char *p)
+acpi_lsapic (char *p)
{
int add = 1;

@@ -58,7 +63,7 @@
printk("Performance Restricted; ignoring.\n");
add = 0;
}
-
+
#ifdef CONFIG_SMP
smp_boot_data.cpu_phys_id[total_cpus] = -1;
#endif
@@ -73,83 +78,40 @@
}

/*
- * Configure legacy IRQ information in iosapic_vector
+ * Configure legacy IRQ information.
*/
static void __init
-acpi_legacy_irq(char *p)
+acpi_legacy_irq (char *p)
{
- /*
- * This is not good. ACPI is not necessarily limited to CONFIG_IA64_DIG, yet
- * ACPI does not necessarily imply IOSAPIC either. Perhaps there should be
- * a means for platform_setup() to register ACPI handlers?
- */
-#ifdef CONFIG_IA64_IRQ_ACPI
acpi_entry_int_override_t *legacy = (acpi_entry_int_override_t *) p;
- unsigned char vector;
- int i;
-
- vector = isa_irq_to_vector(legacy->isa_irq);
+ unsigned long polarity = 0, edge_triggered = 0;

/*
- * Clobber any old pin mapping. It may be that it gets replaced later on
+ * If the platform we're running doesn't define
+ * iosapic_register_legacy_irq(), we ignore this info...
*/
- for (i = 0; i < IA64_MAX_VECTORED_IRQ; i++) {
- if (i = vector)
- continue;
- if (iosapic_pin(i) = iosapic_pin(vector))
- iosapic_pin(i) = 0xff;
- }
-
- iosapic_pin(vector) = legacy->pin;
- iosapic_bus(vector) = BUS_ISA; /* This table only overrides the ISA devices */
- iosapic_busdata(vector) = 0;
-
- /*
- * External timer tick is special...
- */
- if (vector != TIMER_IRQ)
- iosapic_dmode(vector) = IO_SAPIC_LOWEST_PRIORITY;
- else
- iosapic_dmode(vector) = IO_SAPIC_FIXED;
-
+ if (!iosapic_register_legacy_irq)
+ return;
+
/* See MPS 1.4 section 4.3.4 */
switch (legacy->flags) {
- case 0x5:
- iosapic_polarity(vector) = IO_SAPIC_POL_HIGH;
- iosapic_trigger(vector) = IO_SAPIC_EDGE;
- break;
- case 0x8:
- iosapic_polarity(vector) = IO_SAPIC_POL_LOW;
- iosapic_trigger(vector) = IO_SAPIC_EDGE;
- break;
- case 0xd:
- iosapic_polarity(vector) = IO_SAPIC_POL_HIGH;
- iosapic_trigger(vector) = IO_SAPIC_LEVEL;
- break;
- case 0xf:
- iosapic_polarity(vector) = IO_SAPIC_POL_LOW;
- iosapic_trigger(vector) = IO_SAPIC_LEVEL;
- break;
- default:
+ case 0x5: polarity = 1; edge_triggered = 1; break;
+ case 0x8: polarity = 0; edge_triggered = 1; break;
+ case 0xd: polarity = 1; edge_triggered = 0; break;
+ case 0xf: polarity = 0; edge_triggered = 0; break;
+ default:
printk(" ACPI Legacy IRQ 0x%02x: Unknown flags 0x%x\n", legacy->isa_irq,
legacy->flags);
break;
}
-
-# ifdef ACPI_DEBUG
- printk("Legacy ISA IRQ %x -> IA64 Vector %x IOSAPIC Pin %x Active %s %s Trigger\n",
- legacy->isa_irq, vector, iosapic_pin(vector),
- ((iosapic_polarity(vector) = IO_SAPIC_POL_LOW) ? "Low" : "High"),
- ((iosapic_trigger(vector) = IO_SAPIC_LEVEL) ? "Level" : "Edge"));
-# endif /* ACPI_DEBUG */
-#endif /* CONFIG_IA64_IRQ_ACPI */
+ iosapic_register_legacy_irq(legacy->isa_irq, legacy->pin, polarity, edge_triggered);
}

/*
* Info on platform interrupt sources: NMI. PMI, INIT, etc.
*/
static void __init
-acpi_platform(char *p)
+acpi_platform (char *p)
{
acpi_entry_platform_src_t *plat = (acpi_entry_platform_src_t *) p;

@@ -161,8 +123,9 @@
* Parse the ACPI Multiple SAPIC Table
*/
static void __init
-acpi_parse_msapic(acpi_sapic_t *msapic)
+acpi_parse_msapic (acpi_sapic_t *msapic)
{
+ acpi_entry_iosapic_t *iosapic;
char *p, *end;

/* Base address of IPI Message Block */
@@ -172,41 +135,31 @@
end = p + (msapic->header.length - sizeof(acpi_sapic_t));

while (p < end) {
-
switch (*p) {
- case ACPI_ENTRY_LOCAL_SAPIC:
+ case ACPI_ENTRY_LOCAL_SAPIC:
acpi_lsapic(p);
break;

- case ACPI_ENTRY_IO_SAPIC:
- platform_register_iosapic((acpi_entry_iosapic_t *) p);
+ case ACPI_ENTRY_IO_SAPIC:
+ iosapic = (acpi_entry_iosapic_t *) p;
+ if (iosapic_init)
+ iosapic_init(iosapic->address, iosapic->irq_base);
break;

- case ACPI_ENTRY_INT_SRC_OVERRIDE:
+ case ACPI_ENTRY_INT_SRC_OVERRIDE:
acpi_legacy_irq(p);
break;
-
- case ACPI_ENTRY_PLATFORM_INT_SOURCE:
+
+ case ACPI_ENTRY_PLATFORM_INT_SOURCE:
acpi_platform(p);
break;
-
- default:
+
+ default:
break;
}

/* Move to next table entry. */
-#define BAD_ACPI_TABLE
-#ifdef BAD_ACPI_TABLE
- /*
- * Some prototype Lion's have a bad ACPI table
- * requiring this fix. Without this fix, those
- * machines crash during bootup.
- */
- if (p[1] = 0)
- p = end;
- else
-#endif
- p += p[1];
+ p += p[1];
}

/* Make bootup pretty */
@@ -214,7 +167,7 @@
}

int __init
-acpi_parse(acpi_rsdp_t *rsdp)
+acpi_parse (acpi_rsdp_t *rsdp)
{
acpi_rsdt_t *rsdt;
acpi_desc_table_hdr_t *hdrp;
@@ -256,7 +209,7 @@
}

#ifdef CONFIG_ACPI_KERNEL_CONFIG
- acpi_cf_terminate();
+ acpi_cf_terminate();
#endif

#ifdef CONFIG_SMP
diff -urN linux-davidm/arch/ia64/kernel/efi.c lia64/arch/ia64/kernel/efi.c
--- linux-davidm/arch/ia64/kernel/efi.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/efi.c Mon Oct 30 22:33:51 2000
@@ -363,7 +363,7 @@
#if EFI_DEBUG
/* print EFI memory map: */
{
- efi_memory_desc_t *md = p;
+ efi_memory_desc_t *md;
void *p;

for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
diff -urN linux-davidm/arch/ia64/kernel/head.S lia64/arch/ia64/kernel/head.S
--- linux-davidm/arch/ia64/kernel/head.S Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/head.S Mon Oct 30 22:34:49 2000
@@ -74,8 +74,8 @@
;;

#ifdef CONFIG_IA64_EARLY_PRINTK
- mov r2=6
- mov r3=(8<<8) | (28<<2)
+ mov r3=(6<<8) | (28<<2)
+ movl r2=6<<61
;;
mov rr[r2]=r3
;;
@@ -181,7 +181,8 @@

GLOBAL_ENTRY(ia64_load_debug_regs)
alloc r16=ar.pfs,1,0,0,0
-#if !(defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC))
+#if !(defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) \
+ || defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC))
lfetch.nta [in0]
#endif
mov r20=ar.lc // preserve ar.lc
@@ -754,7 +755,7 @@
mov tmp=ar.itc
(p15) br.cond.sptk .wait
;;
- ld1 tmp=[r31]
+ ld4 tmp=[r31]
;;
cmp.ne p15,p0=tmp,r0
mov tmp=ar.itc
@@ -764,7 +765,7 @@
mov tmp=1
;;
IA64_SEMFIX_INSN
- cmpxchg1.acq tmp=[r31],tmp,ar.ccv
+ cmpxchg4.acq tmp=[r31],tmp,ar.ccv
;;
cmp.eq p15,p0=tmp,r0

diff -urN linux-davidm/arch/ia64/kernel/iosapic.c lia64/arch/ia64/kernel/iosapic.c
--- linux-davidm/arch/ia64/kernel/iosapic.c Wed Dec 31 16:00:00 1969
+++ lia64/arch/ia64/kernel/iosapic.c Mon Oct 30 22:28:42 2000
@@ -0,0 +1,495 @@
+/*
+ * I/O SAPIC support.
+ *
+ * Copyright (C) 1999 Intel Corp.
+ * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
+ * Copyright (C) 1999-2000 Hewlett-Packard Co.
+ * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
+ *
+ * 00/04/19 D. Mosberger Rewritten to mirror more closely the x86 I/O APIC code.
+ * In particular, we now have separate handlers for edge
+ * and level triggered interrupts.
+ * 00/10/27 Asit Mallick, Goutham Rao <goutham.rao@intel.com> IRQ vector allocation
+ * PCI to vector mapping, shared PCI interrupts.
+ * 00/10/27 D. Mosberger Document things a bit more to make them more understandable.
+ * Clean up much of the old IOSAPIC cruft.
+ */
+/*
+ * Here is what the interrupt logic between a PCI device and the CPU looks like:
+ *
+ * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, INTD). The
+ * device is uniquely identified by its bus-, device-, and slot-number (the function
+ * number does not matter here because all functions share the same interrupt
+ * lines).
+ *
+ * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC controller.
+ * Multiple interrupt lines may have to share the same IOSAPIC pin (if they're level
+ * triggered and use the same polarity). Each interrupt line has a unique IOSAPIC
+ * irq number which can be calculated as the sum of the controller's base irq number
+ * and the IOSAPIC pin number to which the line connects.
+ *
+ * (3) The IOSAPIC uses an internal table to map the IOSAPIC pin into the IA-64 interrupt
+ * vector. This interrupt vector is then sent to the CPU.
+ *
+ * In other words, there are two levels of indirections involved:
+ *
+ * pci pin -> iosapic irq -> IA-64 vector
+ *
+ * Note: outside this module, IA-64 vectors are called "irqs". This is because that's
+ * the traditional name Linux uses for interrupt vectors.
+ */
+#include <linux/config.h>
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/string.h>
+#include <linux/irq.h>
+
+#include <asm/acpi-ext.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/iosapic.h>
+#include <asm/machvec.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+#ifdef CONFIG_ACPI_KERNEL_CONFIG
+# include <asm/acpikcfg.h>
+#endif
+
+#undef DEBUG_IRQ_ROUTING
+
+static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
+
+/* PCI pin to IOSAPIC irq routing information. This info typically comes from ACPI. */
+
+static struct {
+ int num_routes;
+ struct pci_vector_struct *route;
+} pci_irq;
+
+/* This tables maps IA-64 vectors to the IOSAPIC pin that generates this vector. */
+
+static struct iosapic_irq {
+ char *addr; /* base address of IOSAPIC */
+ unsigned char base_irq; /* first irq assigned to this IOSAPIC */
+ char pin; /* IOSAPIC pin (-1 => not an IOSAPIC irq) */
+ unsigned char dmode : 3; /* delivery mode (see iosapic.h) */
+ unsigned char polarity : 1; /* interrupt polarity (see iosapic.h) */
+ unsigned char trigger : 1; /* trigger mode (see iosapic.h) */
+} iosapic_irq[NR_IRQS];
+
+/*
+ * Translate IOSAPIC irq number to the corresponding IA-64 interrupt vector. If no
+ * entry exists, return -1.
+ */
+static int
+iosapic_irq_to_vector (int irq)
+{
+ int vector;
+
+ for (vector = 0; vector < NR_IRQS; ++vector)
+ if (iosapic_irq[vector].base_irq + iosapic_irq[vector].pin = irq)
+ return vector;
+ return -1;
+}
+
+/*
+ * Map PCI pin to the corresponding IA-64 interrupt vector. If no such mapping exists,
+ * return -1.
+ */
+static int
+pci_pin_to_vector (int bus, int slot, int pci_pin)
+{
+ struct pci_vector_struct *r;
+
+ for (r = pci_irq.route; r < pci_irq.route + pci_irq.num_routes; ++r)
+ if (r->bus = bus && (r->pci_id >> 16) = slot && r->pin = pci_pin)
+ return iosapic_irq_to_vector(r->irq);
+ return -1;
+}
+
+static void
+set_rte (unsigned int vector, unsigned long dest)
+{
+ unsigned long pol, trigger, dmode;
+ u32 low32, high32;
+ char *addr;
+ int pin;
+
+ pin = iosapic_irq[vector].pin;
+ if (pin < 0)
+ return; /* not an IOSAPIC interrupt */
+
+ addr = iosapic_irq[vector].addr;
+ pol = iosapic_irq[vector].polarity;
+ trigger = iosapic_irq[vector].trigger;
+ dmode = iosapic_irq[vector].dmode;
+
+ low32 = ((pol << IOSAPIC_POLARITY_SHIFT) |
+ (trigger << IOSAPIC_TRIGGER_SHIFT) |
+ (dmode << IOSAPIC_DELIVERY_SHIFT) |
+ vector);
+
+#ifdef CONFIG_IA64_AZUSA_HACKS
+ /* set Flush Disable bit */
+ if (addr != (char *) 0xc0000000fec00000)
+ low32 |= (1 << 17);
+#endif
+
+ /* dest contains both id and eid */
+ high32 = (dest << IOSAPIC_DEST_SHIFT);
+
+ writel(IOSAPIC_RTE_HIGH(pin), addr + IOSAPIC_REG_SELECT);
+ writel(high32, addr + IOSAPIC_WINDOW);
+ writel(IOSAPIC_RTE_LOW(pin), addr + IOSAPIC_REG_SELECT);
+ writel(low32, addr + IOSAPIC_WINDOW);
+}
+
+static void
+nop (unsigned int vector)
+{
+ /* do nothing... */
+}
+
+static void
+mask_irq (unsigned int vector)
+{
+ unsigned long flags;
+ char *addr;
+ u32 low32;
+ int pin;
+
+ addr = iosapic_irq[vector].addr;
+ pin = iosapic_irq[vector].pin;
+
+ if (pin < 0)
+ return; /* not an IOSAPIC interrupt! */
+
+ spin_lock_irqsave(&iosapic_lock, flags);
+ {
+ writel(IOSAPIC_RTE_LOW(pin), addr + IOSAPIC_REG_SELECT);
+ low32 = readl(addr + IOSAPIC_WINDOW);
+
+ low32 |= (1 << IOSAPIC_MASK_SHIFT); /* set only the mask bit */
+ writel(low32, addr + IOSAPIC_WINDOW);
+ }
+ spin_unlock_irqrestore(&iosapic_lock, flags);
+}
+
+static void
+unmask_irq (unsigned int vector)
+{
+ unsigned long flags;
+ char *addr;
+ u32 low32;
+ int pin;
+
+ addr = iosapic_irq[vector].addr;
+ pin = iosapic_irq[vector].pin;
+ if (pin < 0)
+ return; /* not an IOSAPIC interrupt! */
+
+ spin_lock_irqsave(&iosapic_lock, flags);
+ {
+ writel(IOSAPIC_RTE_LOW(pin), addr + IOSAPIC_REG_SELECT);
+ low32 = readl(addr + IOSAPIC_WINDOW);
+
+ low32 &= ~(1 << IOSAPIC_MASK_SHIFT); /* clear only the mask bit */
+ writel(low32, addr + IOSAPIC_WINDOW);
+ }
+ spin_unlock_irqrestore(&iosapic_lock, flags);
+}
+
+
+static void
+iosapic_set_affinity (unsigned int vector, unsigned long mask)
+{
+ printk("iosapic_set_affinity: not implemented yet\n");
+}
+
+/*
+ * Handlers for level-triggered interrupts.
+ */
+
+static unsigned int
+iosapic_startup_level_irq (unsigned int vector)
+{
+ unmask_irq(vector);
+ return 0;
+}
+
+static void
+iosapic_end_level_irq (unsigned int vector)
+{
+ writel(vector, iosapic_irq[vector].addr + IOSAPIC_EOI);
+}
+
+#define iosapic_shutdown_level_irq mask_irq
+#define iosapic_enable_level_irq unmask_irq
+#define iosapic_disable_level_irq mask_irq
+#define iosapic_ack_level_irq nop
+
+struct hw_interrupt_type irq_type_iosapic_level = {
+ typename: "IO-SAPIC-level",
+ startup: iosapic_startup_level_irq,
+ shutdown: iosapic_shutdown_level_irq,
+ enable: iosapic_enable_level_irq,
+ disable: iosapic_disable_level_irq,
+ ack: iosapic_ack_level_irq,
+ end: iosapic_end_level_irq,
+ set_affinity: iosapic_set_affinity
+};
+
+/*
+ * Handlers for edge-triggered interrupts.
+ */
+
+static unsigned int
+iosapic_startup_edge_irq (unsigned int vector)
+{
+ unmask_irq(vector);
+ /*
+ * IOSAPIC simply drops interrupts pended while the
+ * corresponding pin was masked, so we can't know if an
+ * interrupt is pending already. Let's hope not...
+ */
+ return 0;
+}
+
+static void
+iosapic_ack_edge_irq (unsigned int vector)
+{
+ /*
+ * Once we have recorded IRQ_PENDING already, we can mask the
+ * interrupt for real. This prevents IRQ storms from unhandled
+ * devices.
+ */
+ if ((irq_desc[vector].status & (IRQ_PENDING|IRQ_DISABLED)) = (IRQ_PENDING|IRQ_DISABLED))
+ mask_irq(vector);
+}
+
+#define iosapic_enable_edge_irq unmask_irq
+#define iosapic_disable_edge_irq nop
+#define iosapic_end_edge_irq nop
+
+struct hw_interrupt_type irq_type_iosapic_edge = {
+ typename: "IO-SAPIC-edge",
+ startup: iosapic_startup_edge_irq,
+ shutdown: iosapic_disable_edge_irq,
+ enable: iosapic_enable_edge_irq,
+ disable: iosapic_disable_edge_irq,
+ ack: iosapic_ack_edge_irq,
+ end: iosapic_end_edge_irq,
+ set_affinity: iosapic_set_affinity
+};
+
+static unsigned int
+iosapic_version (char *addr)
+{
+ /*
+ * IOSAPIC Version Register return 32 bit structure like:
+ * {
+ * unsigned int version : 8;
+ * unsigned int reserved1 : 8;
+ * unsigned int pins : 8;
+ * unsigned int reserved2 : 8;
+ * }
+ */
+ writel(IOSAPIC_VERSION, addr + IOSAPIC_REG_SELECT);
+ return readl(IOSAPIC_WINDOW + addr);
+}
+
+/*
+ * ACPI calls this when it finds an entry for a legacy ISA interrupt. Note that the
+ * irq_base and IOSAPIC address must be set in iosapic_init().
+ */
+void
+iosapic_register_legacy_irq (unsigned long irq,
+ unsigned long pin, unsigned long polarity,
+ unsigned long edge_triggered)
+{
+ unsigned int vector = isa_irq_to_vector(irq);
+
+#ifdef DEBUG_IRQ_ROUTING
+ printk("ISA: IRQ %u -> IOSAPIC irq 0x%02x (%s, %s) -> vector %02x\n",
+ (unsigned) irq, (unsigned) pin,
+ polarity ? "high" : "low", edge_triggered ? "edge" : "level",
+ vector);
+#endif
+
+ iosapic_irq[vector].pin = pin;
+ iosapic_irq[vector].dmode = IOSAPIC_LOWEST_PRIORITY;
+ iosapic_irq[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;
+ iosapic_irq[vector].trigger = edge_triggered ? IOSAPIC_EDGE : IOSAPIC_LEVEL;
+}
+
+void __init
+iosapic_init (unsigned long phys_addr, unsigned int base_irq)
+{
+ struct hw_interrupt_type *irq_type;
+ int i, irq, max_pin, vector;
+ unsigned int ver;
+ char *addr;
+ static int first_time = 1;
+
+ if (first_time) {
+ first_time = 0;
+
+ for (vector = 0; vector < NR_IRQS; ++vector)
+ iosapic_irq[vector].pin = -1; /* mark as unused */
+
+ /*
+ * Fetch the PCI interrupt routing table:
+ */
+#ifdef CONFIG_ACPI_KERNEL_CONFIG
+ acpi_cf_get_pci_vectors(&pci_irq.route, &pci_irq.num_routes);
+#else
+ pci_irq.route + (struct pci_vector_struct *) __va(ia64_boot_param.pci_vectors);
+ pci_irq.num_routes = ia64_boot_param.num_pci_vectors;
+#endif
+ }
+
+ addr = ioremap(phys_addr, 0);
+
+ ver = iosapic_version(addr);
+ max_pin = (ver >> 16) & 0xff;
+
+ printk("IOSAPIC: version %x.%x, address 0x%lx, IRQs 0x%02x-0x%02x\n",
+ (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, base_irq, base_irq + max_pin);
+
+ if (base_irq = 0)
+ /*
+ * Map the legacy ISA devices into the IOSAPIC data. Some of these may
+ * get reprogrammed later on with data from the ACPI Interrupt Source
+ * Override table.
+ */
+ for (irq = 0; irq < 16; ++irq) {
+ vector = isa_irq_to_vector(irq);
+ iosapic_irq[vector].addr = addr;
+ iosapic_irq[vector].base_irq = 0;
+ if (iosapic_irq[vector].pin = -1)
+ iosapic_irq[vector].pin = irq;
+ iosapic_irq[vector].dmode = IOSAPIC_LOWEST_PRIORITY;
+ iosapic_irq[vector].trigger = IOSAPIC_EDGE;
+ iosapic_irq[vector].polarity = IOSAPIC_POL_HIGH;
+#ifdef DEBUG_IRQ_ROUTING
+ printk("ISA: IRQ %u -> IOSAPIC irq 0x%02x (high, edge) -> vector 0x%02x\n",
+ irq, iosapic_irq[vector].base_irq + iosapic_irq[vector].pin,
+ vector);
+#endif
+ irq_type = &irq_type_iosapic_edge;
+ if (irq_desc[vector].handler != irq_type) {
+ if (irq_desc[vector].handler != &no_irq_type)
+ printk("iosapic_init: changing vector 0x%02x from %s to "
+ "%s\n", irq, irq_desc[vector].handler->typename,
+ irq_type->typename);
+ irq_desc[vector].handler = irq_type;
+ }
+
+ /* program the IOSAPIC routing table: */
+ set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);
+ }
+
+#ifndef CONFIG_IA64_SOFTSDV_HACKS
+ for (i = 0; i < pci_irq.num_routes; i++) {
+ irq = pci_irq.route[i].irq;
+
+ if ((unsigned) (irq - base_irq) > max_pin)
+ /* the interrupt route is for another controller... */
+ continue;
+
+ if (irq < 16)
+ vector = isa_irq_to_vector(irq);
+ else {
+ vector = iosapic_irq_to_vector(irq);
+ if (vector < 0)
+ /* new iosapic irq: allocate a vector for it */
+ vector = ia64_alloc_irq();
+ }
+
+ iosapic_irq[vector].addr = addr;
+ iosapic_irq[vector].base_irq = base_irq;
+ iosapic_irq[vector].pin = (irq - base_irq);
+ iosapic_irq[vector].dmode = IOSAPIC_LOWEST_PRIORITY;
+ iosapic_irq[vector].trigger = IOSAPIC_LEVEL;
+ iosapic_irq[vector].polarity = IOSAPIC_POL_LOW;
+
+# ifdef DEBUG_IRQ_ROUTING
+ printk("PCI: (B%d,I%d,P%d) -> IOSAPIC irq 0x%02x -> vector 0x%02x\n",
+ pci_irq.route[i].bus, pci_irq.route[i].pci_id>>16, pci_irq.route[i].pin,
+ iosapic_irq[vector].base_irq + iosapic_irq[vector].pin, vector);
+# endif
+ irq_type = &irq_type_iosapic_level;
+ if (irq_desc[vector].handler != irq_type){
+ if (irq_desc[vector].handler != &no_irq_type)
+ printk("iosapic_init: changing vector 0x%02x from %s to %s\n",
+ vector, irq_desc[vector].handler->typename,
+ irq_type->typename);
+ irq_desc[vector].handler = irq_type;
+ }
+
+ /* program the IOSAPIC routing table: */
+ set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);
+ }
+#endif /* !CONFIG_IA64_SOFTSDV_HACKS */
+}
+
+void
+iosapic_pci_fixup (void)
+{
+ struct pci_dev *dev;
+ unsigned char pin;
+ int vector;
+
+ pci_for_each_dev(dev) {
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (pin) {
+ pin--; /* interrupt pins are numbered starting from 1 */
+ vector = pci_pin_to_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
+ if (vector < 0 && dev->bus->parent) {
+ /* go back to the bridge */
+ struct pci_dev *bridge = dev->bus->self;
+
+ if (bridge) {
+ /* allow for multiple bridges on an adapter */
+ do {
+ /* do the bridge swizzle... */
+ pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+ vector = pci_pin_to_vector(bridge->bus->number,
+ PCI_SLOT(bridge->devfn),
+ pin);
+ } while (vector < 0 && (bridge = bridge->bus->self));
+ }
+ if (vector >= 0)
+ printk(KERN_WARNING
+ "PCI: using PPB(B%d,I%d,P%d) to get vector %02x\n",
+ bridge->bus->number, PCI_SLOT(bridge->devfn),
+ pin, vector);
+ else
+ printk(KERN_WARNING
+ "PCI: Couldn't map irq for (B%d,I%d,P%d)o\n",
+ bridge->bus->number, PCI_SLOT(bridge->devfn),
+ pin);
+ }
+ if (vector >= 0) {
+ printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> 0x%02x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn), pin, vector);
+ dev->irq = vector;
+ }
+ }
+ /*
+ * Nothing to fixup
+ * Fix out-of-range IRQ numbers
+ */
+ if (dev->irq >= NR_IRQS)
+ dev->irq = 15; /* Spurious interrupts */
+ }
+}
diff -urN linux-davidm/arch/ia64/kernel/irq_ia64.c lia64/arch/ia64/kernel/irq_ia64.c
--- linux-davidm/arch/ia64/kernel/irq_ia64.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/irq_ia64.c Mon Oct 30 22:35:56 2000
@@ -7,6 +7,9 @@
*
* 6/10/99: Updated to bring in sync with x86 version to facilitate
* support for SMP and different interrupt controllers.
+ *
+ * 09/15/00 Goutham Rao <goutham.rao@intel.com> Implemented pci_irq_to_vector
+ * PCI to vector allocation routine.
*/

#include <linux/config.h>
@@ -43,15 +46,25 @@
unsigned long ipi_base_addr = (__IA64_UNCACHED_OFFSET | IPI_DEFAULT_BASE_ADDR);

/*
- * Legacy IRQ to IA-64 vector translation table. Any vector not in
- * this table maps to itself (ie: irq 0x30 => IA64 vector 0x30)
+ * Legacy IRQ to IA-64 vector translation table.
*/
__u8 isa_irq_to_vector_map[16] = {
/* 8259 IRQ translation, first 16 entries */
- 0x60, 0x50, 0x10, 0x51, 0x52, 0x53, 0x43, 0x54,
- 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x40, 0x41
+ 0x2f, 0x20, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
+ 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21
};

+int
+ia64_alloc_irq (void)
+{
+ static int next_irq = FIRST_DEVICE_IRQ;
+
+ if (next_irq > LAST_DEVICE_IRQ)
+ /* XXX could look for sharable vectors instead of panic'ing... */
+ panic("ia64_alloc_irq: out of interrupt vectors!");
+ return next_irq++;
+}
+
#ifdef CONFIG_ITANIUM_A1_SPECIFIC

int usbfix;
@@ -217,7 +230,7 @@
}

void
-ipi_send (int cpu, int vector, int delivery_mode, int redirect)
+ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect)
{
unsigned long ipi_addr;
unsigned long ipi_data;
diff -urN linux-davidm/arch/ia64/kernel/ivt.S lia64/arch/ia64/kernel/ivt.S
--- linux-davidm/arch/ia64/kernel/ivt.S Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/ivt.S Tue Oct 31 00:02:02 2000
@@ -924,7 +924,7 @@
alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
;;
ld4 r8=[r14],8 // r8 = EAX (syscall number)
- mov r15\x190 // sys_vfork - last implemented system call
+ mov r15"2 // sys_vfork - last implemented system call
;;
cmp.leu.unc p6,p7=r8,r15
ld4 out1=[r14],8 // r9 = ecx
diff -urN linux-davidm/arch/ia64/kernel/mca.c lia64/arch/ia64/kernel/mca.c
--- linux-davidm/arch/ia64/kernel/mca.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/mca.c Mon Oct 30 23:56:26 2000
@@ -19,6 +19,7 @@
#include <linux/irq.h>
#include <linux/smp_lock.h>

+#include <asm/machvec.h>
#include <asm/page.h>
#include <asm/ptrace.h>
#include <asm/system.h>
@@ -365,7 +366,7 @@
void
ia64_mca_wakeup(int cpu)
{
- ipi_send(cpu, IA64_MCA_WAKEUP_INT_VECTOR, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(cpu, IA64_MCA_WAKEUP_INT_VECTOR, IA64_IPI_DM_INT, 0);
ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;

}
diff -urN linux-davidm/arch/ia64/kernel/pci.c lia64/arch/ia64/kernel/pci.c
--- linux-davidm/arch/ia64/kernel/pci.c Thu Jun 22 07:09:44 2000
+++ lia64/arch/ia64/kernel/pci.c Mon Oct 30 22:36:54 2000
@@ -56,7 +56,8 @@

/* Macro to build a PCI configuration address to be passed as a parameter to SAL. */

-#define PCI_CONFIG_ADDRESS(dev, where) (((u64) dev->bus->number << 16) | ((u64) (dev->devfn & 0xff) << 8) | (where & 0xff))
+#define PCI_CONFIG_ADDRESS(dev, where) \
+ (((u64) dev->bus->number << 16) | ((u64) (dev->devfn & 0xff) << 8) | (where & 0xff))

static int
pci_conf_read_config_byte(struct pci_dev *dev, int where, u8 *value)
@@ -109,7 +110,6 @@
return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS(dev, where), 4, value);
}

-
static struct pci_ops pci_conf = {
pci_conf_read_config_byte,
pci_conf_read_config_word,
@@ -120,35 +120,18 @@
};

/*
- * Try to find PCI BIOS. This will always work for IA64.
- */
-
-static struct pci_ops * __init
-pci_find_bios(void)
-{
- return &pci_conf;
-}
-
-/*
* Initialization. Uses the SAL interface
*/
-
-#define PCI_BUSES_TO_SCAN 255
-
void __init
pcibios_init(void)
{
+# define PCI_BUSES_TO_SCAN 255
struct pci_ops *ops = NULL;
int i;

- if ((ops = pci_find_bios()) = NULL) {
- printk("PCI: No PCI bus detected\n");
- return;
- }
-
printk("PCI: Probing PCI hardware\n");
for (i = 0; i < PCI_BUSES_TO_SCAN; i++)
- pci_scan_bus(i, ops, NULL);
+ pci_scan_bus(i, &pci_conf, NULL);
platform_pci_fixup();
return;
}
@@ -157,7 +140,6 @@
* Called after each bus is probed, but before its children
* are examined.
*/
-
void __init
pcibios_fixup_bus(struct pci_bus *b)
{
@@ -207,7 +189,6 @@
/*
* PCI BIOS setup, always defaults to SAL interface
*/
-
char * __init
pcibios_setup(char *str)
{
diff -urN linux-davidm/arch/ia64/kernel/perfmon.c lia64/arch/ia64/kernel/perfmon.c
--- linux-davidm/arch/ia64/kernel/perfmon.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/perfmon.c Mon Oct 30 22:37:23 2000
@@ -4,18 +4,20 @@
*
* Originaly Written by Ganesh Venkitachalam, IBM Corp.
* Modifications by David Mosberger-Tang, Hewlett-Packard Co.
+ * Modifications by Stephane Eranian, Hewlett-Packard Co.
* Copyright (C) 1999 Ganesh Venkitachalam <venkitac@us.ibm.com>
* Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
*/

#include <linux/config.h>
+
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/proc_fs.h>
-#include <linux/ptrace.h>

#include <asm/errno.h>
#include <asm/hw_irq.h>
@@ -58,19 +60,51 @@
#define MAX_PERF_COUNTER 4 /* true for Itanium, at least */
#define PMU_FIRST_COUNTER 4 /* first generic counter */

-#define WRITE_PMCS_AND_START 0xa0
-#define WRITE_PMCS 0xa1
-#define READ_PMDS 0xa2
-#define STOP_PMCS 0xa3
+#define PFM_WRITE_PMCS 0xa0
+#define PFM_WRITE_PMDS 0xa1
+#define PFM_READ_PMDS 0xa2
+#define PFM_STOP 0xa3
+#define PFM_START 0xa4
+#define PFM_ENABLE 0xa5 /* unfreeze only */
+#define PFM_DISABLE 0xa6 /* freeze only */
+/*
+ * Those 2 are just meant for debugging. I considered using sysctl() for
+ * that but it is a little bit too pervasive. This solution is at least
+ * self-contained.
+ */
+#define PFM_DEBUG_ON 0xe0
+#define PFM_DEBUG_OFF 0xe1
+
+#ifdef CONFIG_SMP
+#define cpu_is_online(i) (cpu_online_map & (1UL << i))
+#else
+#define cpu_is_online(i) 1
+#endif

+#define PMC_IS_IMPL(i) (pmu_conf.impl_regs[i>>6] & (1<< (i&~(64-1))))
+#define PMD_IS_IMPL(i) (pmu_conf.impl_regs[4+(i>>6)] & (1<< (i&~(64-1))))
+#define PMD_IS_COUNTER(i) (i>=PMU_FIRST_COUNTER && i < (PMU_FIRST_COUNTER+pmu_conf.max_counters))
+#define PMC_IS_COUNTER(i) (i>=PMU_FIRST_COUNTER && i < (PMU_FIRST_COUNTER+pmu_conf.max_counters))

/*
* this structure needs to be enhanced
*/
typedef struct {
+ unsigned long pfr_reg_num; /* which register */
+ unsigned long pfr_reg_value; /* configuration (PMC) or initial value (PMD) */
+ unsigned long pfr_reg_reset; /* reset value on overflow (PMD) */
+ void *pfr_smpl_buf; /* pointer to user buffer for EAR/BTB */
+ unsigned long pfr_smpl_size; /* size of user buffer for EAR/BTB */
+ pid_t pfr_notify_pid; /* process to notify */
+ int pfr_notify_sig; /* signal for notification, 0=no notification */
+} perfmon_req_t;
+
+#if 0
+typedef struct {
unsigned long pmu_reg_data; /* generic PMD register */
unsigned long pmu_reg_num; /* which register number */
} perfmon_reg_t;
+#endif

/*
* This structure is initialize at boot time and contains
@@ -78,86 +112,141 @@
* by PAL
*/
typedef struct {
- unsigned long perf_ovfl_val; /* overflow value for generic counters */
- unsigned long max_pmc; /* highest PMC */
- unsigned long max_pmd; /* highest PMD */
- unsigned long max_counters; /* number of generic counter pairs (PMC/PMD) */
+ unsigned long perf_ovfl_val; /* overflow value for generic counters */
+ unsigned long max_counters; /* upper limit on counter pair (PMC/PMD) */
+ unsigned long impl_regs[16]; /* buffer used to hold implememted PMC/PMD mask */
} pmu_config_t;

-/* XXX will go static when ptrace() is cleaned */
-unsigned long perf_ovfl_val; /* overflow value for generic counters */
-
static pmu_config_t pmu_conf;

+/* for debug only */
+static unsigned long pfm_debug=1; /* 0= nodebug, >0= debug output on */
+#define DBprintk(a) {\
+ if (pfm_debug >0) { printk a; } \
+}
+
/*
- * could optimize to avoid cache conflicts in SMP
+ * could optimize to avoid cache line conflicts in SMP
*/
-unsigned long pmds[NR_CPUS][MAX_PERF_COUNTER];
+static struct task_struct *pmu_owners[NR_CPUS];

-asmlinkage unsigned long
-sys_perfmonctl (int cmd, int count, void *ptr, long arg4, long arg5, long arg6, long arg7, long arg8, long stack)
+static int
+do_perfmonctl (struct task_struct *task, int cmd, int flags, perfmon_req_t *req, int count, struct pt_regs *regs)
{
- struct pt_regs *regs = (struct pt_regs *) &stack;
- perfmon_reg_t tmp, *cptr = ptr;
- unsigned long cnum;
+ perfmon_req_t tmp;
int i;

switch (cmd) {
- case WRITE_PMCS: /* Writes to PMC's and clears PMDs */
- case WRITE_PMCS_AND_START: /* Also starts counting */
+ case PFM_WRITE_PMCS:
+ /* we don't quite support this right now */
+ if (task != current) return -EINVAL;
+
+ if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
+
+ for (i = 0; i < count; i++, req++) {
+ copy_from_user(&tmp, req, sizeof(tmp));
+
+ /* XXX needs to check validity of the data maybe */
+
+ if (!PMC_IS_IMPL(tmp.pfr_reg_num)) {
+ DBprintk((__FUNCTION__ " invalid pmc[%ld]\n", tmp.pfr_reg_num));
+ return -EINVAL;
+ }
+
+ /* XXX: for counters, need to some checks */
+ if (PMC_IS_COUNTER(tmp.pfr_reg_num)) {
+ current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].sig = tmp.pfr_notify_sig;
+ current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].pid = tmp.pfr_notify_pid;
+
+ DBprintk((__FUNCTION__" setting PMC[%ld] send sig %d to %d\n",tmp.pfr_reg_num, tmp.pfr_notify_sig, tmp.pfr_notify_pid));
+ }
+ ia64_set_pmc(tmp.pfr_reg_num, tmp.pfr_reg_value);
+
+ DBprintk((__FUNCTION__" setting PMC[%ld]=0x%lx\n", tmp.pfr_reg_num, tmp.pfr_reg_value));
+ }
+ /*
+ * we have to set this here event hough we haven't necessarily started monitoring
+ * because we may be context switched out
+ */
+ current->thread.flags |= IA64_THREAD_PM_VALID;
+ break;
+
+ case PFM_WRITE_PMDS:
+ /* we don't quite support this right now */
+ if (task != current) return -EINVAL;
+
+ if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
+
+ for (i = 0; i < count; i++, req++) {
+ copy_from_user(&tmp, req, sizeof(tmp));
+
+ if (!PMD_IS_IMPL(tmp.pfr_reg_num)) return -EINVAL;
+
+ /* update virtualized (64bits) counter */
+ if (PMD_IS_COUNTER(tmp.pfr_reg_num)) {
+ current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].val = tmp.pfr_reg_value & ~pmu_conf.perf_ovfl_val;
+ current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].rval = tmp.pfr_reg_reset;
+ }
+ /* writes to unimplemented part is ignored, so this is safe */
+ ia64_set_pmd(tmp.pfr_reg_num, tmp.pfr_reg_value);
+ /* to go away */
+ ia64_srlz_d();
+ DBprintk((__FUNCTION__" setting PMD[%ld]: pmod.val=0x%lx pmd=0x%lx rval=0x%lx\n", tmp.pfr_reg_num, current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].val, ia64_get_pmd(tmp.pfr_reg_num),current->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].rval));
+ }
+ /*
+ * we have to set this here event hough we haven't necessarily started monitoring
+ * because we may be context switched out
+ */
+ current->thread.flags |= IA64_THREAD_PM_VALID;
+ break;
+
+ case PFM_START:
+ /* we don't quite support this right now */
+ if (task != current) return -EINVAL;

- if (!access_ok(VERIFY_READ, cptr, sizeof(struct perfmon_reg_t)*count))
- return -EFAULT;
+ pmu_owners[smp_processor_id()] = current;

- for (i = 0; i < count; i++, cptr++) {
+ /* will start monitoring right after rfi */
+ ia64_psr(regs)->up = 1;

- copy_from_user(&tmp, cptr, sizeof(tmp));
+ /*
+ * mark the state as valid.
+ * this will trigger save/restore at context switch
+ */
+ current->thread.flags |= IA64_THREAD_PM_VALID;

- /* XXX need to check validity of pmu_reg_num and perhaps data!! */
+ ia64_set_pmc(0, 0);

- if (tmp.pmu_reg_num > pmu_conf.max_pmc || tmp.pmu_reg_num = 0) return -EFAULT;
+ break;

- ia64_set_pmc(tmp.pmu_reg_num, tmp.pmu_reg_data);
+ case PFM_ENABLE:
+ /* we don't quite support this right now */
+ if (task != current) return -EINVAL;

- /* to go away */
- if (tmp.pmu_reg_num >= PMU_FIRST_COUNTER && tmp.pmu_reg_num < PMU_FIRST_COUNTER+pmu_conf.max_counters) {
- ia64_set_pmd(tmp.pmu_reg_num, 0);
- pmds[smp_processor_id()][tmp.pmu_reg_num - PMU_FIRST_COUNTER] = 0;
+ pmu_owners[smp_processor_id()] = current;

- printk(__FUNCTION__" setting PMC/PMD[%ld] es=0x%lx pmd[%ld]=%lx\n", tmp.pmu_reg_num, (tmp.pmu_reg_data>>8) & 0x7f, tmp.pmu_reg_num, ia64_get_pmd(tmp.pmu_reg_num));
- } else
- printk(__FUNCTION__" setting PMC[%ld]=0x%lx\n", tmp.pmu_reg_num, tmp.pmu_reg_data);
- }
-
- if (cmd = WRITE_PMCS_AND_START) {
-#if 0
-/* irrelevant with user monitors */
- local_irq_save(flags);
-
- dcr = ia64_get_dcr();
- dcr |= IA64_DCR_PP;
- ia64_set_dcr(dcr);
-
- local_irq_restore(flags);
-#endif
+ /*
+ * mark the state as valid.
+ * this will trigger save/restore at context switch
+ */
+ current->thread.flags |= IA64_THREAD_PM_VALID;

+ /* simply unfreeze */
ia64_set_pmc(0, 0);
+ break;

- /* will start monitoring right after rfi */
- ia64_psr(regs)->up = 1;
- }
- /*
- * mark the state as valid.
- * this will trigger save/restore at context switch
- */
- current->thread.flags |= IA64_THREAD_PM_VALID;
- break;
-
- case READ_PMDS:
- if (count <= 0 || count > MAX_PERF_COUNTER)
- return -EINVAL;
- if (!access_ok(VERIFY_WRITE, cptr, sizeof(struct perfmon_reg_t)*count))
- return -EFAULT;
+ case PFM_DISABLE:
+ /* we don't quite support this right now */
+ if (task != current) return -EINVAL;
+
+ /* simply unfreeze */
+ ia64_set_pmc(0, 1);
+ ia64_srlz_d();
+ break;
+
+ case PFM_READ_PMDS:
+ if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;
+ if (!access_ok(VERIFY_WRITE, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;

/* This looks shady, but IMHO this will work fine. This is
* the sequence that I could come up with to avoid races
@@ -187,16 +276,31 @@
* is the irq_save/restore needed?
*/

+ for (i = 0; i < count; i++, req++) {
+ unsigned long val=0;

- /* XXX: This needs to change to read more than just the counters */
- for (i = 0, cnum = PMU_FIRST_COUNTER;i < count; i++, cnum++, cptr++) {
+ copy_from_user(&tmp, req, sizeof(tmp));

- tmp.pmu_reg_data = (pmds[smp_processor_id()][i]
- + (ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val));
+ if (!PMD_IS_IMPL(tmp.pfr_reg_num)) return -EINVAL;

- tmp.pmu_reg_num = cnum;
+ if (PMD_IS_COUNTER(tmp.pfr_reg_num)) {
+ if (task = current){
+ val = ia64_get_pmd(tmp.pfr_reg_num) & pmu_conf.perf_ovfl_val;
+ } else {
+ val = task->thread.pmd[tmp.pfr_reg_num - PMU_FIRST_COUNTER] & pmu_conf.perf_ovfl_val;
+ }
+ val += task->thread.pmu_counters[tmp.pfr_reg_num - PMU_FIRST_COUNTER].val;
+ } else {
+ /* for now */
+ if (task != current) return -EINVAL;
+
+ val = ia64_get_pmd(tmp.pfr_reg_num);
+ }
+ tmp.pfr_reg_value = val;

- if (copy_to_user(cptr, &tmp, sizeof(tmp))) return -EFAULT;
+DBprintk((__FUNCTION__" reading PMD[%ld]=0x%lx\n", tmp.pfr_reg_num, val));
+
+ if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
}
#if 0
/* irrelevant with user monitors */
@@ -209,11 +313,18 @@
#endif
break;

- case STOP_PMCS:
+ case PFM_STOP:
+ /* we don't quite support this right now */
+ if (task != current) return -EINVAL;
+
ia64_set_pmc(0, 1);
ia64_srlz_d();
- for (i = 0; i < MAX_PERF_COUNTER; ++i)
- ia64_set_pmc(4+i, 0);
+
+ ia64_psr(regs)->up = 0;
+
+ current->thread.flags &= ~IA64_THREAD_PM_VALID;
+
+ pmu_owners[smp_processor_id()] = NULL;

#if 0
/* irrelevant with user monitors */
@@ -225,48 +336,140 @@
ia64_psr(regs)->up = 0;
#endif

- current->thread.flags &= ~(IA64_THREAD_PM_VALID);
-
break;

+ case PFM_DEBUG_ON:
+ printk(__FUNCTION__" debuggin on\n");
+ pfm_debug = 1;
+ break;
+
+ case PFM_DEBUG_OFF:
+ printk(__FUNCTION__" debuggin off\n");
+ pfm_debug = 0;
+ break;
+
default:
+ DBprintk((__FUNCTION__" UNknown command 0x%x\n", cmd));
return -EINVAL;
break;
}
return 0;
}

-static inline void
-update_counters (void)
+asmlinkage int
+sys_perfmonctl (int pid, int cmd, int flags, perfmon_req_t *req, int count, long arg6, long arg7, long arg8, long stack)
{
- unsigned long mask, i, cnum, val;
+ struct pt_regs *regs = (struct pt_regs *) &stack;
+ struct task_struct *child = current;
+ int ret;

- mask = ia64_get_pmc(0) >> 4;
- for (i = 0, cnum = PMU_FIRST_COUNTER ; i < pmu_conf.max_counters; cnum++, i++, mask >>= 1) {
+ if (pid != current->pid) {
+ read_lock(&tasklist_lock);
+ {
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ }
+ if (!child) {
+ read_unlock(&tasklist_lock);
+ return -ESRCH;
+ }
+ /*
+ * XXX: need to do more checking here
+ */
+ if (child->state != TASK_ZOMBIE) {
+ DBprintk((__FUNCTION__" warning process %d not in stable state %ld\n", pid, child->state));
+ }
+ }
+ ret = do_perfmonctl(child, cmd, flags, req, count, regs);

+ if (child != current) read_unlock(&tasklist_lock);

- val = mask & 0x1 ? pmu_conf.perf_ovfl_val + 1 : 0;
+ return ret;
+}

- if (mask & 0x1)
- printk(__FUNCTION__ " PMD%ld overflowed pmd=%lx pmod=%lx\n", cnum, ia64_get_pmd(cnum), pmds[smp_processor_id()][i]);

- /* since we got an interrupt, might as well clear every pmd. */
- val += ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val;
+static inline int
+update_counters (u64 pmc0)
+{
+ unsigned long mask, i, cnum;
+ struct thread_struct *th;
+ struct task_struct *ta;
+
+ if (pmu_owners[smp_processor_id()] = NULL) {
+ DBprintk((__FUNCTION__" Spurious overflow interrupt: PMU not owned\n"));
+ return 0;
+ }
+
+ /*
+ * It is never safe to access the task for which the overflow interrupt is destinated
+ * using the current variable as the interrupt may occur in the middle of a context switch
+ * where current does not hold the task that is running yet.
+ *
+ * For monitoring, however, we do need to get access to the task which caused the overflow
+ * to account for overflow on the counters.
+ * We accomplish this by maintaining a current owner of the PMU per CPU. During context
+ * switch the ownership is changed in a way such that the reflected owner is always the
+ * valid one, i.e. the one that caused the interrupt.
+ */
+ ta = pmu_owners[smp_processor_id()];
+ th = &pmu_owners[smp_processor_id()]->thread;

- printk(__FUNCTION__ " adding val=%lx to pmod[%ld]=%lx \n", val, i, pmds[smp_processor_id()][i]);
+ /*
+ * Don't think this could happen given first test. Keep as sanity check
+ */
+ if ((th->flags & IA64_THREAD_PM_VALID) = 0) {
+ DBprintk((__FUNCTION__" Spurious overflow interrupt: process %d not using perfmon\n", ta->pid));
+ return 0;
+ }
+
+ /*
+ * if PMU not frozen: spurious from previous context
+ * if PMC[0] = 0x1 : frozen but no overflow reported: leftover from previous context
+ *
+ * in either case we don't touch the state upon return from handler
+ */
+ if ((pmc0 & 0x1) = 0 || pmc0 = 0x1) {
+ DBprintk((__FUNCTION__" Spurious overflow interrupt: process %d freeze=0\n",ta->pid));
+ return 0;
+ }

- pmds[smp_processor_id()][i] += val;
+ mask = pmc0 >> 4;

- ia64_set_pmd(cnum, 0);
+ for (i = 0, cnum = PMU_FIRST_COUNTER; i < pmu_conf.max_counters; cnum++, i++, mask >>= 1) {
+
+ if (mask & 0x1) {
+ DBprintk((__FUNCTION__ " PMD[%ld] overflowed pmd=0x%lx pmod.val=0x%lx\n", cnum, ia64_get_pmd(cnum), th->pmu_counters[i].val));
+
+ /*
+ * Because we somtimes (EARS/BTB) reset to a specific value, we cannot simply use
+ * val to count the number of times we overflowed. Otherwise we would loose the value
+ * current in the PMD (which can be >0). So to make sure we don't loose
+ * the residual counts we set val to contain full 64bits value of the counter.
+ */
+ th->pmu_counters[i].val += 1+pmu_conf.perf_ovfl_val+(ia64_get_pmd(cnum) &pmu_conf.perf_ovfl_val);
+
+ /* writes to upper part are ignored, so this is safe */
+ ia64_set_pmd(cnum, th->pmu_counters[i].rval);
+
+ DBprintk((__FUNCTION__ " pmod[%ld].val=0x%lx pmd=0x%lx\n", i, th->pmu_counters[i].val, ia64_get_pmd(cnum)&pmu_conf.perf_ovfl_val));
+
+ if (th->pmu_counters[i].pid != 0 && th->pmu_counters[i].sig>0) {
+ DBprintk((__FUNCTION__ " shouild notify process %d with signal %d\n",th->pmu_counters[i].pid, th->pmu_counters[i].sig));
+ }
+ }
}
+ return 1;
}

static void
perfmon_interrupt (int irq, void *arg, struct pt_regs *regs)
{
- update_counters();
- ia64_set_pmc(0, 0);
- ia64_srlz_d();
+ /* unfreeze if not spurious */
+ if ( update_counters(ia64_get_pmc(0)) ) {
+ ia64_set_pmc(0, 0);
+ ia64_srlz_d();
+ }
}

static struct irqaction perfmon_irqaction = {
@@ -280,9 +483,13 @@
{
char *p = page;
u64 pmc0 = ia64_get_pmc(0);
+ int i;

- p += sprintf(p, "PMC[0]=%lx\n", pmc0);
-
+ p += sprintf(p, "PMC[0]=%lx\nPerfmon debug: %s\n", pmc0, pfm_debug ? "On" : "Off");
+ for(i=0; i < NR_CPUS; i++) {
+ if (cpu_is_online(i))
+ p += sprintf(p, "CPU%d.PMU %d\n", i, pmu_owners[i] ? pmu_owners[i]->pid: -1);
+ }
return p - page;
}

@@ -308,7 +515,6 @@
perfmon_init (void)
{
pal_perf_mon_info_u_t pm_info;
- u64 pm_buffer[16];
s64 status;

irq_desc[PERFMON_IRQ].status |= IRQ_PER_CPU;
@@ -320,15 +526,13 @@

printk("perfmon: Initialized vector to %u\n",PERFMON_IRQ);

- if ((status=ia64_pal_perf_mon_info(pm_buffer, &pm_info)) != 0) {
+ if ((status=ia64_pal_perf_mon_info(pmu_conf.impl_regs, &pm_info)) != 0) {
printk(__FUNCTION__ " pal call failed (%ld)\n", status);
return;
}
- pmu_conf.perf_ovfl_val = perf_ovfl_val = (1L << pm_info.pal_perf_mon_info_s.width) - 1;
+ pmu_conf.perf_ovfl_val = (1L << pm_info.pal_perf_mon_info_s.width) - 1;

/* XXX need to use PAL instead */
- pmu_conf.max_pmc = 13;
- pmu_conf.max_pmd = 17;
pmu_conf.max_counters = pm_info.pal_perf_mon_info_s.generic;

printk("perfmon: Counters are %d bits\n", pm_info.pal_perf_mon_info_s.width);
@@ -347,36 +551,137 @@
ia64_srlz_d();
}

+/*
+ * XXX: for system wide this function MUST never be called
+ */
void
-ia64_save_pm_regs (struct thread_struct *t)
+ia64_save_pm_regs (struct task_struct *ta)
{
- int i;
+ struct thread_struct *t = &ta->thread;
+ u64 pmc0, psr;
+ int i,j;
+
+ /*
+ * We must maek sure that we don't loose any potential overflow
+ * interrupt while saving PMU context. In this code, external
+ * interrupts are always enabled.
+ */
+
+ /*
+ * save current PSR: needed because we modify it
+ */
+ __asm__ __volatile__ ("mov %0=psr;;": "=r"(psr) :: "memory");
+
+ /*
+ * stop monitoring:
+ * This is the only way to stop monitoring without destroying overflow
+ * information in PMC[0..3].
+ * This is the last instruction which can cause overflow when monitoring
+ * in kernel.
+ * By now, we could still have an overflow interrupt in flight.
+ */
+ __asm__ __volatile__ ("rsm psr.up;;"::: "memory");
+
+ /*
+ * read current overflow status:
+ *
+ * We may be reading stale information at this point, if we got interrupt
+ * just before the read(pmc0) but that's all right. However, if we did
+ * not get the interrupt before, this read reflects LAST state.
+ *
+ */
+ pmc0 = ia64_get_pmc(0);

+ /*
+ * freeze PMU:
+ *
+ * This destroys the overflow information. This is required to make sure
+ * next process does not start with monitoring on if not requested
+ * (PSR.up may not be enough).
+ *
+ * We could still get an overflow interrupt by now. However the handler
+ * will not do anything if is sees PMC[0].fr=1 but no overflow bits
+ * are set. So PMU will stay in frozen state. This implies that pmc0
+ * will still be holding the correct unprocessed information.
+ *
+ */
ia64_set_pmc(0, 1);
ia64_srlz_d();
+
+ /*
+ * check for overflow bits set:
+ *
+ * If pmc0 reports PMU frozen, this means we have a pending overflow,
+ * therefore we invoke the handler. Handler is reentrant with regards
+ * to PMC[0] so it is safe to call it twice.
+ *
+ * IF pmc0 reports overflow, we need to reread current PMC[0] value
+ * in case the handler was invoked right after the first pmc0 read.
+ * it is was not invoked then pmc0=PMC[0], otherwise it's been invoked
+ * and overflow information has been processed, so we don't need to call.
+ *
+ * Test breakdown:
+ * - pmc0 & ~0x1: test if overflow happened
+ * - second part: check if current register reflects this as well.
+ *
+ * NOTE: testing for pmc0 & 0x1 is not enough has it would trigger call
+ * when PM_VALID and PMU.fr which is common when setting up registers
+ * just before actually starting monitors.
+ *
+ */
+ if ((pmc0 & ~0x1) && ((pmc0=ia64_get_pmc(0)) &~0x1) ) {
+ printk(__FUNCTION__" Warning: pmc[0]=0x%lx\n", pmc0);
+ update_counters(pmc0);
+ /*
+ * XXX: not sure that's enough. the next task may still get the
+ * interrupt.
+ */
+ }
+
+ /*
+ * restore PSR for context switch to save
+ */
+ __asm__ __volatile__ ("mov psr.l=%0;;"::"r"(psr): "memory");
+
/*
* XXX: this will need to be extended beyong just counters
*/
- for (i=0; i< IA64_NUM_PM_REGS; i++) {
- t->pmd[i] = ia64_get_pmd(4+i);
- t->pmod[i] = pmds[smp_processor_id()][i];
- t->pmc[i] = ia64_get_pmc(4+i);
+ for (i=0,j=4; i< IA64_NUM_PMD_COUNTERS; i++,j++) {
+ t->pmd[i] = ia64_get_pmd(j);
+ t->pmc[i] = ia64_get_pmc(j);
}
+ /*
+ * PMU is frozen, PMU context is saved: nobody owns the PMU on this CPU
+ * At this point, we should not receive any pending interrupt from the
+ * 'switched out' task
+ */
+ pmu_owners[smp_processor_id()] = NULL;
}

void
-ia64_load_pm_regs (struct thread_struct *t)
+ia64_load_pm_regs (struct task_struct *ta)
{
- int i;
+ struct thread_struct *t = &ta->thread;
+ int i,j;
+
+ /*
+ * we first restore ownership of the PMU to the 'soon to be current'
+ * context. This way, if, as soon as we unfreeze the PMU at the end
+ * of this function, we get an interrupt, we attribute it to the correct
+ * task
+ */
+ pmu_owners[smp_processor_id()] = ta;

/*
* XXX: this will need to be extended beyong just counters
*/
- for (i=0; i< IA64_NUM_PM_REGS ; i++) {
- ia64_set_pmd(4+i, t->pmd[i]);
- pmds[smp_processor_id()][i] = t->pmod[i];
- ia64_set_pmc(4+i, t->pmc[i]);
+ for (i=0,j=4; i< IA64_NUM_PMD_COUNTERS; i++,j++) {
+ ia64_set_pmd(j, t->pmd[i]);
+ ia64_set_pmc(j, t->pmc[i]);
}
+ /*
+ * unfreeze PMU
+ */
ia64_set_pmc(0, 0);
ia64_srlz_d();
}
diff -urN linux-davidm/arch/ia64/kernel/process.c lia64/arch/ia64/kernel/process.c
--- linux-davidm/arch/ia64/kernel/process.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/process.c Mon Oct 30 22:38:03 2000
@@ -164,7 +164,7 @@
ia64_save_debug_regs(&task->thread.dbr[0]);
#ifdef CONFIG_PERFMON
if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
- ia64_save_pm_regs(&task->thread);
+ ia64_save_pm_regs(task);
#endif
if (IS_IA32_PROCESS(ia64_task_regs(task)))
ia32_save_state(&task->thread);
@@ -177,7 +177,7 @@
ia64_load_debug_regs(&task->thread.dbr[0]);
#ifdef CONFIG_PERFMON
if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
- ia64_load_pm_regs(&task->thread);
+ ia64_load_pm_regs(task);
#endif
if (IS_IA32_PROCESS(ia64_task_regs(task)))
ia32_load_state(&task->thread);
@@ -299,6 +299,14 @@
# define THREAD_FLAGS_TO_SET 0
p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
| THREAD_FLAGS_TO_SET);
+#ifdef CONFIG_IA32_SUPPORT
+ /*
+ * If we're cloning an IA32 task then save the IA32 extra
+ * state from the current task to the new task
+ */
+ if (IS_IA32_PROCESS(ia64_task_regs(current)))
+ ia32_save_state(&p->thread);
+#endif
return 0;
}

@@ -554,7 +562,7 @@
* we garantee no race. this call we also stop
* monitoring
*/
- ia64_save_pm_regs(&current->thread);
+ ia64_save_pm_regs(current);
/*
* make sure that switch_to() will not save context again
*/
diff -urN linux-davidm/arch/ia64/kernel/ptrace.c lia64/arch/ia64/kernel/ptrace.c
--- linux-davidm/arch/ia64/kernel/ptrace.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/ptrace.c Mon Oct 30 22:38:17 2000
@@ -794,11 +794,7 @@
addr);
return -1;
}
- } else
-#ifdef CONFIG_PERFMON
- if (addr < PT_PMD)
-#endif
- {
+ } else {
/* access debug registers */

if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {
@@ -820,33 +816,14 @@
}

ptr += regnum;
- }
-#ifdef CONFIG_PERFMON
- else {
- /*
- * XXX: will eventually move back to perfmonctl()
- */
- unsigned long pmd = (addr - PT_PMD) >> 3;
- extern unsigned long perf_ovfl_val;
-
- /* we just use ptrace to read */
- if (write_access) return -1;
-
- if (pmd > 3) {
- printk("ptrace: rejecting access to PMD[%ld] address 0x%lx\n", pmd, addr);
- return -1;
- }

- /*
- * We always need to mask upper 32bits of pmd because value is random
- */
- pmd_tmp = child->thread.pmod[pmd]+(child->thread.pmd[pmd]& perf_ovfl_val);
-
- /*printk(__FUNCTION__" child=%d reading pmd[%ld]=%lx\n", child->pid, pmd, pmd_tmp);*/
-
- ptr = &pmd_tmp;
+ if (write_access)
+ /* don't let the user set kernel-level breakpoints... */
+ *ptr = *data & ~(7UL << 56);
+ else
+ *data = *ptr;
+ return 0;
}
-#endif
if (write_access)
*ptr = *data;
else
@@ -977,11 +954,7 @@
/* disallow accessing anything else... */
return -1;
}
- } else
-#ifdef CONFIG_PERFMON
- if (addr < PT_PMD)
-#endif
- {
+ } else {

/* access debug registers */

@@ -1002,34 +975,14 @@
return -1;

ptr += regnum;
- }
-#ifdef CONFIG_PERFMON
- else {
- /*
- * XXX: will eventually move back to perfmonctl()
- */
- unsigned long pmd = (addr - PT_PMD) >> 3;
- extern unsigned long perf_ovfl_val;

- /* we just use ptrace to read */
- if (write_access) return -1;
-
- if (pmd > 3) {
- printk("ptrace: rejecting access to PMD[%ld] address 0x%lx\n", pmd, addr);
- return -1;
- }
-
- /*
- * We always need to mask upper 32bits of pmd because value is random
- */
- pmd_tmp = child->thread.pmod[pmd]+(child->thread.pmd[pmd]& perf_ovfl_val);
-
- /*printk(__FUNCTION__" child=%d reading pmd[%ld]=%lx\n", child->pid, pmd, pmd_tmp);*/
-
- ptr = &pmd_tmp;
+ if (write_access)
+ /* don't let the user set kernel-level breakpoints... */
+ *ptr = *data & ~(7UL << 56);
+ else
+ *data = *ptr;
+ return 0;
}
-#endif
-
if (write_access)
*ptr = *data;
else
diff -urN linux-davidm/arch/ia64/kernel/smp.c lia64/arch/ia64/kernel/smp.c
--- linux-davidm/arch/ia64/kernel/smp.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/smp.c Mon Oct 30 23:57:04 2000
@@ -11,6 +11,8 @@
* 00/03/31 Rohit Seth <rohit.seth@intel.com> Fixes for Bootstrap Processor & cpu_online_map
* now gets done here (instead of setup.c)
* 99/10/05 davidm Update to bring it in sync with new command-line processing scheme.
+ * 10/13/00 Goutham Rao <goutham.rao@intel.com> Updated smp_call_function and
+ * smp_call_function_single to resend IPI on timeouts
*/
#define __KERNEL_SYSCALLS__

@@ -30,6 +32,7 @@
#include <asm/current.h>
#include <asm/delay.h>
#include <asm/efi.h>
+#include <asm/machvec.h>

#include <asm/io.h>
#include <asm/irq.h>
@@ -276,7 +279,7 @@
return;

set_bit(op, &ipi_op[dest_cpu]);
- ipi_send(dest_cpu, IPI_IRQ, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(dest_cpu, IPI_IRQ, IA64_IPI_DM_INT, 0);
}

static inline void
@@ -358,6 +361,7 @@
if (pointer_lock(&smp_call_function_data, &data, retry))
return -EBUSY;

+resend:
/* Send a message to all other CPUs and wait for them to respond */
send_IPI_single(cpuid, IPI_CALL_FUNC);

@@ -366,8 +370,12 @@
while ((atomic_read(&data.unstarted_count) > 0) && time_before(jiffies, timeout))
barrier();
if (atomic_read(&data.unstarted_count) > 0) {
+#if (defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC))
+ goto resend;
+#else
smp_call_function_data = NULL;
return -ETIMEDOUT;
+#endif
}
if (wait)
while (atomic_read(&data.unfinished_count) > 0)
@@ -411,13 +419,23 @@
/* Send a message to all other CPUs and wait for them to respond */
send_IPI_allbutself(IPI_CALL_FUNC);

+retry:
/* Wait for response */
timeout = jiffies + HZ;
while ((atomic_read(&data.unstarted_count) > 0) && time_before(jiffies, timeout))
barrier();
if (atomic_read(&data.unstarted_count) > 0) {
+#if (defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC))
+ int i;
+ for (i = 0; i < smp_num_cpus; i++) {
+ if (i != smp_processor_id())
+ ia64_send_ipi(i, IPI_IRQ, IA64_IPI_DM_INT, 0);
+ }
+ goto retry;
+#else
smp_call_function_data = NULL;
return -ETIMEDOUT;
+#endif
}
if (wait)
while (atomic_read(&data.unfinished_count) > 0)
@@ -569,7 +587,7 @@
cpu_now_booting = cpu;

/* Kick the AP in the butt */
- ipi_send(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);

/* wait up to 10s for the AP to start */
for (timeout = 0; timeout < 100000; timeout++) {
diff -urN linux-davidm/arch/ia64/kernel/traps.c lia64/arch/ia64/kernel/traps.c
--- linux-davidm/arch/ia64/kernel/traps.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/traps.c Mon Oct 30 22:40:14 2000
@@ -544,7 +544,7 @@

case 46:
printk("Unexpected IA-32 intercept trap (Trap 46)\n");
- printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n", regs->cr_iip, ifa, isr);
+ printk(" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n", regs->cr_iip, ifa, isr, iim);
force_sig(SIGSEGV, current);
return;

diff -urN linux-davidm/arch/ia64/kernel/unaligned.c lia64/arch/ia64/kernel/unaligned.c
--- linux-davidm/arch/ia64/kernel/unaligned.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/unaligned.c Mon Oct 30 22:40:27 2000
@@ -572,7 +572,8 @@
*/
if (regnum = 0) {
*val = 0;
- *nat = 0;
+ if (nat)
+ *nat = 0;
return;
}

diff -urN linux-davidm/arch/ia64/kernel/unwind.c lia64/arch/ia64/kernel/unwind.c
--- linux-davidm/arch/ia64/kernel/unwind.c Mon Oct 30 23:54:13 2000
+++ lia64/arch/ia64/kernel/unwind.c Mon Oct 30 22:40:45 2000
@@ -46,16 +46,6 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define p5 5

-/*
- * The unwind tables are supposed to be sorted, but the GNU toolchain
- * currently fails to produce a sorted table in the presence of
- * functions that go into sections other than .text. For example, the
- * kernel likes to put initialization code into .text.init, which
- * messes up the sort order. Hopefully, this will get fixed sometime
- * soon. --davidm 00/05/23
- */
-#define UNWIND_TABLE_SORT_BUG
-
#define UNW_LOG_CACHE_SIZE 7 /* each unw_script is ~256 bytes in size */
#define UNW_CACHE_SIZE (1 << UNW_LOG_CACHE_SIZE)

@@ -63,7 +53,7 @@
#define UNW_HASH_SIZE (1 << UNW_LOG_HASH_SIZE)

#define UNW_DEBUG 0
-#define UNW_STATS 0 /* WARNING: this disabled interrupts for long time-spans!! */
+#define UNW_STATS 1 /* WARNING: this disabled interrupts for long time-spans!! */

#if UNW_DEBUG
static long unw_debug_level = 255;
@@ -1964,23 +1954,6 @@
{
struct unw_table_entry *start = table_start, *end = table_end;

-#ifdef UNWIND_TABLE_SORT_BUG
- {
- struct unw_table_entry *e1, *e2, tmp;
-
- /* stupid bubble sort... */
-
- for (e1 = start; e1 < end; ++e1) {
- for (e2 = e1 + 1; e2 < end; ++e2) {
- if (e2->start_offset < e1->start_offset) {
- tmp = *e1;
- *e1 = *e2;
- *e2 = tmp;
- }
- }
- }
- }
-#endif
table->name = name;
table->segment_base = segment_base;
table->gp = gp;
diff -urN linux-davidm/arch/ia64/lib/copy_user.S lia64/arch/ia64/lib/copy_user.S
--- linux-davidm/arch/ia64/lib/copy_user.S Wed Aug 2 18:54:02 2000
+++ lia64/arch/ia64/lib/copy_user.S Mon Oct 30 23:45:16 2000
@@ -65,6 +65,12 @@
//
// local registers
//
+#define t1 r2 // rshift in bytes
+#define t2 r3 // lshift in bytes
+#define rshift r14 // right shift in bits
+#define lshift r15 // left shift in bits
+#define word1 r16
+#define word2 r17
#define cnt r18
#define len2 r19
#define saved_lc r20
@@ -134,6 +140,190 @@
br.ret.sptk.few rp // end of short memcpy

//
+ // Not 8-byte aligned
+ //
+diff_align_copy_user:
+ // At this point we know we have more than 16 bytes to copy
+ // and also that src and dest do _not_ have the same alignment.
+ and src2=0x7,src1 // src offset
+ and dst2=0x7,dst1 // dst offset
+ ;;
+ // The basic idea is that we copy byte-by-byte at the head so
+ // that we can reach 8-byte alignment for both src1 and dst1.
+ // Then copy the body using software pipelined 8-byte copy,
+ // shifting the two back-to-back words right and left, then copy
+ // the tail by copying byte-by-byte.
+ //
+ // Fault handling. If the byte-by-byte at the head fails on the
+ // load, then restart and finish the pipleline by copying zeros
+ // to the dst1. Then copy zeros for the rest of dst1.
+ // If 8-byte software pipeline fails on the load, do the same as
+ // failure_in3 does. If the byte-by-byte at the tail fails, it is
+ // handled simply by failure_in_pipe1.
+ //
+ // The case p14 represents the source has more bytes in the
+ // the first word (by the shifted part), whereas the p15 needs to
+ // copy some bytes from the 2nd word of the source that has the
+ // tail of the 1st of the destination.
+ //
+
+ //
+ // Optimization. If dst1 is 8-byte aligned (not rarely), we don't need
+ // to copy the head to dst1, to start 8-byte copy software pipleline.
+ // We know src1 is not 8-byte aligned in this case.
+ //
+ cmp.eq p14,p15=r0,dst2
+(p15) br.cond.spnt.few 1f
+ ;;
+ sub t1=8,src2
+ mov t2=src2
+ ;;
+ shl rshift=t2,3
+ sub len1=len,t1 // set len1
+ ;;
+ sub lshiftd,rshift
+ ;;
+ br.cond.spnt.few word_copy_user
+ ;;
+1:
+ cmp.leu p14,p15=src2,dst2
+ sub t1=dst2,src2
+ ;;
+ .pred.rel "mutex", p14, p15
+(p14) sub word1=8,src2 // (8 - src offset)
+(p15) sub t1=r0,t1 // absolute value
+(p15) sub word1=8,dst2 // (8 - dst offset)
+ ;;
+ // For the case p14, we don't need to copy the shifted part to
+ // the 1st word of destination.
+ sub t2=8,t1
+(p14) sub word1=word1,t1
+ ;;
+ sub len1=len,word1 // resulting len
+(p15) shl rshift=t1,3 // in bits
+(p14) shl rshift=t2,3
+ ;;
+(p14) sub len1=len1,t1
+ adds cnt=-1,word1
+ ;;
+ sub lshiftd,rshift
+ mov ar.ec=PIPE_DEPTH
+ mov pr.rot=1<<16 // p16=true all others are false
+ mov ar.lc=cnt
+ ;;
+2:
+ EX(failure_in_pipe2,(p16) ld1 val1[0]=[src1],1)
+ ;;
+ EX(failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
+ br.ctop.dptk.few 2b
+ ;;
+ clrrrb
+ ;;
+word_copy_user:
+ cmp.gtu p9,p0\x16,len1
+(p9) br.cond.spnt.few 4f // if (16 > len1) skip 8-byte copy
+ ;;
+ shr.u cnt=len1,3 // number of 64-bit words
+ ;;
+ adds cnt=-1,cnt
+ ;;
+ .pred.rel "mutex", p14, p15
+(p14) sub src1=src1,t2
+(p15) sub src1=src1,t1
+ //
+ // Now both src1 and dst1 point to an 8-byte aligned address. And
+ // we have more than 8 bytes to copy.
+ //
+ mov ar.lc=cnt
+ mov ar.ec=PIPE_DEPTH
+ mov pr.rot=1<<16 // p16=true all others are false
+ ;;
+3:
+ //
+ // The pipleline consists of 3 stages:
+ // 1 (p16): Load a word from src1
+ // 2 (EPI_1): Shift right pair, saving to tmp
+ // 3 (EPI): Store tmp to dst1
+ //
+ // To make it simple, use at least 2 (p16) loops to set up val1[n]
+ // because we need 2 back-to-back val1[] to get tmp.
+ // Note that this implies EPI_2 must be p18 or greater.
+ //
+
+#define EPI_1 p[PIPE_DEPTH-2]
+#define SWITCH(pred, shift) cmp.eq pred,p0=shift,rshift
+#define CASE(pred, shift) \
+ (pred) br.cond.spnt.few copy_user_bit##shift
+#define BODY(rshift) \
+copy_user_bit##rshift: \
+1: \
+ EX(failure_out,(EPI) st8 [dst1]=tmp,8); \
+(EPI_1) shrp tmp=val1[PIPE_DEPTH-3],val1[PIPE_DEPTH-2],rshift; \
+ EX(failure_in2,(p16) ld8 val1[0]=[src1],8); \
+ br.ctop.dptk.few 1b; \
+ ;; \
+ br.cond.spnt.few .diff_align_do_tail
+
+ //
+ // Since the instruction 'shrp' requires a fixed 128-bit value
+ // specifying the bits to shift, we need to provide 7 cases
+ // below.
+ //
+ SWITCH(p6, 8)
+ SWITCH(p7, 16)
+ SWITCH(p8, 24)
+ SWITCH(p9, 32)
+ SWITCH(p10, 40)
+ SWITCH(p11, 48)
+ SWITCH(p12, 56)
+ ;;
+ CASE(p6, 8)
+ CASE(p7, 16)
+ CASE(p8, 24)
+ CASE(p9, 32)
+ CASE(p10, 40)
+ CASE(p11, 48)
+ CASE(p12, 56)
+ ;;
+ BODY(8)
+ BODY(16)
+ BODY(24)
+ BODY(32)
+ BODY(40)
+ BODY(48)
+ BODY(56)
+ ;;
+.diff_align_do_tail:
+ .pred.rel "mutex", p14, p15
+(p14) sub src1=src1,t1
+(p14) adds dst1=-8,dst1
+(p15) sub dst1=dst1,t1
+ ;;
+4:
+ // Tail correction.
+ //
+ // The problem with this piplelined loop is that the last word is not
+ // loaded and thus parf of the last word written is not correct.
+ // To fix that, we simply copy the tail byte by byte.
+
+ sub len1=endsrc,src1,1
+ clrrrb
+ ;;
+ mov ar.ec=PIPE_DEPTH
+ mov pr.rot=1<<16 // p16=true all others are false
+ mov ar.lc=len1
+ ;;
+5:
+ EX(failure_in_pipe1,(p16) ld1 val1[0]=[src1],1)
+
+ EX(failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
+ br.ctop.dptk.few 5b
+ ;;
+ mov pr=saved_pr,0xffffffffffff0000
+ mov ar.pfs=saved_pfs
+ br.ret.dptk.few rp
+
+ //
// Beginning of long mempcy (i.e. > 16 bytes)
//
long_copy_user:
@@ -142,7 +332,7 @@
;;
cmp.eq p10,p8=r0,tmp
mov len1=len // copy because of rotation
-(p8) br.cond.dpnt.few 1b // XXX Fixme. memcpy_diff_align
+(p8) br.cond.dpnt.few diff_align_copy_user
;;
// At this point we know we have more than 16 bytes to copy
// and also that both src and dest have the same alignment
@@ -267,6 +457,21 @@
mov ar.pfs=saved_pfs
br.ret.dptk.few rp

+ //
+ // This is the case where the byte by byte copy fails on the load
+ // when we copy the head. We need to finish the pipeline and copy
+ // zeros for the rest of the destination. Since this happens
+ // at the top we still need to fill the body and tail.
+failure_in_pipe2:
+ sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
+2:
+(p16) mov val1[0]=r0
+(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1
+ br.ctop.dptk.few 2b
+ ;;
+ sub len=enddst,dst1,1 // precompute len
+ br.cond.dptk.few failure_in1bis
+ ;;

//
// Here we handle the head & tail part when we check for alignment.
@@ -395,6 +600,23 @@
mov ar.pfs=saved_pfs
br.ret.dptk.few rp

+failure_in2:
+ sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
+ ;;
+3:
+(p16) mov val1[0]=r0
+(EPI) st8 [dst1]=val1[PIPE_DEPTH-1],8
+ br.ctop.dptk.few 3b
+ ;;
+ cmp.ne p6,p0=dst1,enddst // Do we need to finish the tail ?
+ sub len=enddst,dst1,1 // precompute len
+(p6) br.cond.dptk.few failure_in1bis
+ ;;
+ mov pr=saved_pr,0xffffffffffff0000
+ mov ar.lc=saved_lc
+ mov ar.pfs=saved_pfs
+ br.ret.dptk.few rp
+
//
// handling of failures on stores: that's the easy part
//
diff -urN linux-davidm/arch/ia64/lib/memcpy.S lia64/arch/ia64/lib/memcpy.S
--- linux-davidm/arch/ia64/lib/memcpy.S Thu Aug 24 08:17:30 2000
+++ lia64/arch/ia64/lib/memcpy.S Mon Oct 30 22:45:50 2000
@@ -17,17 +17,24 @@

#include <asm/asmmacro.h>

+#if defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC)
+# define BRP(args...) nop.b 0
+#else
+# define BRP(args...) brp.loop.imp args
+#endif
+
GLOBAL_ENTRY(bcopy)
.regstk 3,0,0,0
mov r8=in0
mov in0=in1
;;
mov in1=r8
+ ;;
END(bcopy)
// FALL THROUGH
GLOBAL_ENTRY(memcpy)

-# define MEM_LAT 2 /* latency to L1 cache */
+# define MEM_LAT 21 /* latency to memory */

# define dst r2
# define src r3
@@ -57,20 +64,17 @@
UNW(.prologue)
UNW(.save ar.pfs, saved_pfs)
alloc saved_pfs=ar.pfs,3,Nrot,0,Nrot
-#if !(defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC))
- lfetch [in1]
-#else
- nop.m 0
-#endif
+ UNW(.save ar.lc, saved_lc)
+ mov saved_lc=ar.lc
or t0=in0,in1
;;

or t0=t0,in2
- UNW(.save ar.lc, saved_lc)
- mov saved_lc=ar.lc
UNW(.save pr, saved_pr)
mov saved_pr=pr

+ UNW(.body)
+
cmp.eq p6,p0=in2,r0 // zero length?
mov retval=in0 // return dst
(p6) br.ret.spnt.many rp // zero length, return immediately
@@ -83,7 +87,6 @@

adds cnt=-1,cnt // br.ctop is repeat/until
cmp.gtu p7,p0\x16,in2 // copying less than 16 bytes?
- UNW(.body)
mov ar.ec=N
;;

@@ -98,10 +101,17 @@
;;
.rotr val[N]
.rotp p[N]
-1:
+ .align 32
+1: { .mib
(p[0]) ld8 val[0]=[src],8
+ nop.i 0
+ BRP(1b, 2f)
+}
+2: { .mfb
(p[N-1])st8 [dst]=val[N-1],8
+ nop.f 0
br.ctop.dptk.few 1b
+}
;;
mov ar.lc=saved_lc
mov pr=saved_pr,-1
@@ -118,6 +128,7 @@
memcpy_short:
adds cnt=-1,in2 // br.ctop is repeat/until
mov ar.ec=MEM_LAT
+ BRP(1f, 2f)
;;
mov ar.lc=cnt
;;
@@ -125,12 +136,17 @@
* It is faster to put a stop bit in the loop here because it makes
* the pipeline shorter (and latency is what matters on short copies).
*/
-1:
+ .align 32
+1: { .mib
(p[0]) ld1 val[0]=[src],1
- ;;
+ nop.i 0
+ BRP(1b, 2f)
+} ;;
+2: { .mfb
(p[MEM_LAT-1])st1 [dst]=val[MEM_LAT-1],1
+ nop.f 0
br.ctop.dptk.few 1b
- ;;
+} ;;
mov ar.lc=saved_lc
mov pr=saved_pr,-1
mov ar.pfs=saved_pfs
@@ -251,17 +267,16 @@
.align 64

#define COPY(shift,index) \
- 1: \
- { .mfi \
+ 1: { .mib \
(p[0]) ld8 val[0]=[src2],8; \
- nop.f 0; \
(p[MEM_LAT+3]) shrp w[0]=val[MEM_LAT+3],val[MEM_LAT+4-index],shift; \
- }; \
- { .mbb \
+ BRP(1b, 2f) \
+ }; \
+ 2: { .mfb \
(p[MEM_LAT+4]) st8 [dst]=w[1],8; \
- nop.b 0; \
+ nop.f 0; \
br.ctop.dptk.few 1b; \
- }; \
+ }; \
;; \
ld8 val[N-1]=[src_end]; /* load last word (may be same as val[N]) */ \
;; \
diff -urN linux-davidm/arch/ia64/mm/tlb.c lia64/arch/ia64/mm/tlb.c
--- linux-davidm/arch/ia64/mm/tlb.c Thu Aug 24 08:17:30 2000
+++ lia64/arch/ia64/mm/tlb.c Mon Oct 30 22:46:48 2000
@@ -6,6 +6,8 @@
*
* 08/02/00 A. Mallick <asit.k.mallick@intel.com>
* Modified RID allocation for SMP
+ * Goutham Rao <goutham.rao@intel.com>
+ * IPI based ptc implementation and A-step IPI implementation.
*/
#include <linux/config.h>
#include <linux/init.h>
@@ -17,6 +19,7 @@
#include <asm/mmu_context.h>
#include <asm/pgalloc.h>
#include <asm/pal.h>
+#include <asm/delay.h>

#define SUPPORTED_PGBITS ( \
1 << _PAGE_SIZE_256M | \
@@ -99,9 +102,22 @@
/*
* Wait for other CPUs to finish purging entries.
*/
+#if (defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC))
+ {
+ unsigned long start = ia64_get_itc();
+ while (atomic_read(&flush_cpu_count) > 0) {
+ if ((ia64_get_itc() - start) > 40000UL) {
+ atomic_set(&flush_cpu_count, smp_num_cpus - 1);
+ smp_send_flush_tlb();
+ start = ia64_get_itc();
+ }
+ }
+ }
+#else
while (atomic_read(&flush_cpu_count)) {
/* Nothing */
}
+#endif
if (!(flags & IA64_PSR_I)) {
local_irq_disable();
ia64_set_tpr(saved_tpr);
diff -urN linux-davidm/drivers/char/drm/vm.c lia64/drivers/char/drm/vm.c
--- linux-davidm/drivers/char/drm/vm.c Wed Oct 4 16:53:20 2000
+++ lia64/drivers/char/drm/vm.c Mon Oct 30 22:48:30 2000
@@ -272,6 +272,7 @@
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_map_t *map = NULL;
+ unsigned long off;
int i;

DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
@@ -288,7 +289,16 @@
bit longer. */
for (i = 0; i < dev->map_count; i++) {
map = dev->maplist[i];
- if (map->offset = VM_OFFSET(vma)) break;
+ off = map->offset ^ VM_OFFSET(vma);
+#ifdef __ia64__
+ /*
+ * Ignore region bits, makes IA32 processes happier
+ * XXX This is a hack...
+ */
+ off &= ~0xe000000000000000;
+#endif // __ia64__
+ if (off = 0)
+ break;
}

if (i >= dev->map_count) return -EINVAL;
diff -urN linux-davidm/drivers/char/mem.c lia64/drivers/char/mem.c
--- linux-davidm/drivers/char/mem.c Wed Oct 4 16:53:21 2000
+++ lia64/drivers/char/mem.c Tue Oct 31 00:13:05 2000
@@ -198,8 +198,12 @@
* through a file pointer that was marked O_SYNC will be
* done non-cached.
*/
- if (noncached_address(offset) || (file->f_flags & O_SYNC))
+ if (noncached_address(offset) || (file->f_flags & O_SYNC)
+ || vma->vm_flags & VM_NONCACHED)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (vma->vm_flags & VM_WRITECOMBINED)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);

/*
* Don't dump addresses that are not real memory to a core file.
diff -urN linux-davidm/drivers/net/tulip/tulip_core.c lia64/drivers/net/tulip/tulip_core.c
--- linux-davidm/drivers/net/tulip/tulip_core.c Wed Oct 4 16:53:25 2000
+++ lia64/drivers/net/tulip/tulip_core.c Mon Oct 30 22:49:57 2000
@@ -52,7 +52,7 @@

/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
- || defined(__sparc_)
+ || defined(__sparc_) || defined(__ia64__)
static int rx_copybreak = 1518;
#else
static int rx_copybreak = 100;
@@ -71,7 +71,7 @@
ToDo: Non-Intel setting could be better.
*/

-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__ia64__)
static int csr0 = 0x01A00000 | 0xE000;
#elif defined(__i386__) || defined(__powerpc__) || defined(__hppa__)
static int csr0 = 0x01A00000 | 0x8000;
diff -urN linux-davidm/drivers/scsi/qla1280.c lia64/drivers/scsi/qla1280.c
--- linux-davidm/drivers/scsi/qla1280.c Mon Oct 30 23:54:14 2000
+++ lia64/drivers/scsi/qla1280.c Mon Oct 30 22:50:11 2000
@@ -16,9 +16,17 @@
* General Public License for more details.
**
******************************************************************************/
-
+#define QLA1280_VERSION "3.19 Beta"
/****************************************************************************
Revision History:
+ Rev 3.19 Beta October 13, 2000 BN Qlogic
+ - Declare driver_template for new kernel
+ (2.4.0 and greater) scsi initialization scheme.
+ - Update /proc/scsi entry for 2.3.18 kernels and
+ above as qla1280
+ Rev 3.18 Beta October 10, 2000 BN Qlogic
+ - Changed scan order of adapters to map
+ the QLA12160 followed by the QLA1280.
Rev 3.17 Beta September 18, 2000 BN Qlogic
- Removed warnings for 32 bit 2.4.x compiles
- Corrected declared size for request and response
@@ -102,8 +110,6 @@
#include <linux/module.h>
#endif

-#define QLA1280_VERSION "3.17 Beta"
-
#include <stdarg.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -408,14 +414,14 @@
struct _qlaboards QL1280BoardTbl[NUM_OF_ISP_DEVICES] =
{
/* Name , Board PCI Device ID, Number of ports */
+ {"QLA12160 ", QLA12160_DEVICE_ID, 2,
+ &fw12160i_code01[0], (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] },
{"QLA1080 ", QLA1080_DEVICE_ID, 1,
&fw1280ei_code01[0], (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },
{"QLA1240 ", QLA1240_DEVICE_ID, 2,
&fw1280ei_code01[0], (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },
{"QLA1280 ", QLA1280_DEVICE_ID, 2,
&fw1280ei_code01[0], (unsigned long *)&fw1280ei_length01,&fw1280ei_addr01, &fw1280ei_version_str[0] },
- {"QLA12160 ", QLA12160_DEVICE_ID, 2,
- &fw12160i_code01[0], (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] },
{"QLA10160 ", QLA10160_DEVICE_ID, 1,
&fw12160i_code01[0], (unsigned long *)&fw12160i_length01,&fw12160i_addr01, &fw12160i_version_str[0] },
{" ", 0, 0}
@@ -739,7 +745,7 @@
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
template->proc_dir = &proc_scsi_qla1280;
#else
- template->proc_name = "qla1x80";
+ template->proc_name = "qla1280";
#endif
/* Try and find each different type of adapter we support */
for( i=0; bdp->device_id != 0 && i < NUM_OF_ISP_DEVICES; i++, bdp++ ) {
@@ -6342,13 +6348,15 @@
return(ret);
}

-
-/*
- * Declarations for load module
- */
-static Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE;
-
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+#ifdef MODULE
+Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE;
#include "scsi_module.c"
+#endif
+#else /* new kernel scsi initialization scheme */
+static Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE;
+#include "scsi_module.c"
+#endif

/************************************************************************
* qla1280_check_for_dead_scsi_bus *
diff -urN linux-davidm/fs/binfmt_elf.c lia64/fs/binfmt_elf.c
--- linux-davidm/fs/binfmt_elf.c Mon Oct 30 23:54:14 2000
+++ lia64/fs/binfmt_elf.c Mon Oct 30 22:50:33 2000
@@ -33,6 +33,7 @@
#include <linux/smp_lock.h>

#include <asm/uaccess.h>
+#include <asm/param.h>
#include <asm/pgalloc.h>

#define DLINFO_ITEMS 13
@@ -159,23 +160,27 @@
sp -= 2;
NEW_AUX_ENT(0, AT_PLATFORM, (elf_addr_t)(unsigned long) u_platform);
}
- sp -= 2;
+ sp -= 2*2;
NEW_AUX_ENT(0, AT_HWCAP, hwcap);
+ NEW_AUX_ENT(1, AT_PAGESZ, ELF_EXEC_PAGESIZE);
+#ifdef CLOCKS_PER_SEC
+ sp -= 2;
+ NEW_AUX_ENT(0, AT_CLKTCK, CLOCKS_PER_SEC);
+#endif

if (exec) {
- sp -= 11*2;
+ sp -= 10*2;

NEW_AUX_ENT(0, AT_PHDR, load_addr + exec->e_phoff);
NEW_AUX_ENT(1, AT_PHENT, sizeof (struct elf_phdr));
NEW_AUX_ENT(2, AT_PHNUM, exec->e_phnum);
- NEW_AUX_ENT(3, AT_PAGESZ, ELF_EXEC_PAGESIZE);
- NEW_AUX_ENT(4, AT_BASE, interp_load_addr);
- NEW_AUX_ENT(5, AT_FLAGS, 0);
- NEW_AUX_ENT(6, AT_ENTRY, load_bias + exec->e_entry);
- NEW_AUX_ENT(7, AT_UID, (elf_addr_t) current->uid);
- NEW_AUX_ENT(8, AT_EUID, (elf_addr_t) current->euid);
- NEW_AUX_ENT(9, AT_GID, (elf_addr_t) current->gid);
- NEW_AUX_ENT(10, AT_EGID, (elf_addr_t) current->egid);
+ NEW_AUX_ENT(3, AT_BASE, interp_load_addr);
+ NEW_AUX_ENT(4, AT_FLAGS, 0);
+ NEW_AUX_ENT(5, AT_ENTRY, load_bias + exec->e_entry);
+ NEW_AUX_ENT(6, AT_UID, (elf_addr_t) current->uid);
+ NEW_AUX_ENT(7, AT_EUID, (elf_addr_t) current->euid);
+ NEW_AUX_ENT(8, AT_GID, (elf_addr_t) current->gid);
+ NEW_AUX_ENT(9, AT_EGID, (elf_addr_t) current->egid);
}
#undef NEW_AUX_ENT

diff -urN linux-davidm/fs/open.c lia64/fs/open.c
--- linux-davidm/fs/open.c Wed Oct 4 16:53:39 2000
+++ lia64/fs/open.c Mon Oct 30 22:50:49 2000
@@ -103,7 +103,7 @@
inode = nd.dentry->d_inode;

error = -EACCES;
- if (S_ISDIR(inode->i_mode))
+ if (!S_ISREG(inode->i_mode))
goto dput_and_out;

error = permission(inode,MAY_WRITE);
@@ -164,7 +164,7 @@
dentry = file->f_dentry;
inode = dentry->d_inode;
error = -EACCES;
- if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
+ if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
goto out_putf;
error = -EPERM;
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
diff -urN linux-davidm/fs/proc/array.c lia64/fs/proc/array.c
--- linux-davidm/fs/proc/array.c Fri Sep 8 14:34:59 2000
+++ lia64/fs/proc/array.c Mon Oct 30 22:51:05 2000
@@ -575,7 +575,7 @@
goto getlen_out;

/* Check whether the mmaps could change if we sleep */
- volatile_task = (task != current || atomic_read(&mm->mm_users) > 1);
+ volatile_task = (task != current || atomic_read(&mm->mm_users) > 2);

/* decode f_pos */
lineno = *ppos >> MAPS_LINE_SHIFT;
diff -urN linux-davidm/include/asm-ia64/delay.h lia64/include/asm-ia64/delay.h
--- linux-davidm/include/asm-ia64/delay.h Mon Oct 30 23:54:14 2000
+++ lia64/include/asm-ia64/delay.h Mon Oct 30 22:51:21 2000
@@ -55,6 +55,10 @@
unsigned long result;

__asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
+#ifdef CONFIG_ITANIUM
+ while (__builtin_expect ((__s32) result = -1, 0))
+ __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
+#endif
return result;
}

diff -urN linux-davidm/include/asm-ia64/hw_irq.h lia64/include/asm-ia64/hw_irq.h
--- linux-davidm/include/asm-ia64/hw_irq.h Mon Oct 30 23:54:14 2000
+++ lia64/include/asm-ia64/hw_irq.h Tue Oct 31 00:15:17 2000
@@ -31,13 +31,22 @@

#define IA64_SPURIOUS_INT 0x0f

-#define IA64_MIN_VECTORED_IRQ 16
-#define IA64_MAX_VECTORED_IRQ 255
+/*
+ * Vectors 0x10-0x1f are used for low priority interrupts, e.g. CMCI.
+ */
+#define PCE_IRQ 0x1e /* platform corrected error interrupt vector */
+#define CMC_IRQ 0x1f /* correctable machine-check interrupt vector */
+/*
+ * Vectors 0x20-0x2f are reserved for legacy ISA IRQs.
+ */
+#define FIRST_DEVICE_IRQ 0x30
+#define LAST_DEVICE_IRQ 0xe7

-#define PERFMON_IRQ 0x28 /* performanc monitor interrupt vector */
+#define MCA_RENDEZ_IRQ 0xe8 /* MCA rendez interrupt */
+#define PERFMON_IRQ 0xee /* performanc monitor interrupt vector */
#define TIMER_IRQ 0xef /* use highest-prio group 15 interrupt for timer */
+#define MCA_WAKEUP_IRQ 0xf0 /* MCA wakeup interrupt (must be higher than MCA_RENDEZ_IRQ) */
#define IPI_IRQ 0xfe /* inter-processor interrupt vector */
-#define CMC_IRQ 0xff /* correctable machine-check interrupt vector */

/* IA64 inter-cpu interrupt related definitions */

@@ -62,12 +71,13 @@

extern struct hw_interrupt_type irq_type_ia64_sapic; /* CPU-internal interrupt controller */

-extern void ipi_send (int cpu, int vector, int delivery_mode, int redirect);
+extern int ia64_alloc_irq (void); /* allocate a free irq */
+extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);

static inline void
hw_resend_irq (struct hw_interrupt_type *h, unsigned int vector)
{
- ipi_send(smp_processor_id(), vector, IA64_IPI_DM_INT, 0);
+ ia64_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0);
}

#endif /* _ASM_IA64_HW_IRQ_H */
diff -urN linux-davidm/include/asm-ia64/ia32.h lia64/include/asm-ia64/ia32.h
--- linux-davidm/include/asm-ia64/ia32.h Mon Oct 30 23:54:14 2000
+++ lia64/include/asm-ia64/ia32.h Mon Oct 30 22:53:22 2000
@@ -5,6 +5,8 @@

#ifdef CONFIG_IA32_SUPPORT

+#include <linux/param.h>
+
/*
* 32 bit structures for IA32 support.
*/
@@ -32,6 +34,8 @@

#define IA32_PAGE_SHIFT 12 /* 4KB pages */
#define IA32_PAGE_SIZE (1ULL << IA32_PAGE_SHIFT)
+#define IA32_CLOCKS_PER_SEC 100 /* Cast in stone for IA32 Linux */
+#define IA32_TICK(tick) ((unsigned long long)(tick) * IA32_CLOCKS_PER_SEC / CLOCKS_PER_SEC)

/* fcntl.h */
struct flock32 {
diff -urN linux-davidm/include/asm-ia64/iosapic.h lia64/include/asm-ia64/iosapic.h
--- linux-davidm/include/asm-ia64/iosapic.h Thu Jun 22 07:09:45 2000
+++ lia64/include/asm-ia64/iosapic.h Mon Oct 30 22:53:32 2000
@@ -3,121 +3,60 @@

#include <linux/config.h>

-#define IO_SAPIC_DEFAULT_ADDR 0xFEC00000
+#define IOSAPIC_DEFAULT_ADDR 0xFEC00000

-#define IO_SAPIC_REG_SELECT 0x0
-#define IO_SAPIC_WINDOW 0x10
-#define IO_SAPIC_EOI 0x40
+#define IOSAPIC_REG_SELECT 0x0
+#define IOSAPIC_WINDOW 0x10
+#define IOSAPIC_EOI 0x40

-#define IO_SAPIC_VERSION 0x1
+#define IOSAPIC_VERSION 0x1

/*
* Redirection table entry
*/
+#define IOSAPIC_RTE_LOW(i) (0x10+i*2)
+#define IOSAPIC_RTE_HIGH(i) (0x11+i*2)

-#define IO_SAPIC_RTE_LOW(i) (0x10+i*2)
-#define IO_SAPIC_RTE_HIGH(i) (0x11+i*2)
-
-
-#define IO_SAPIC_DEST_SHIFT 16
+#define IOSAPIC_DEST_SHIFT 16

/*
* Delivery mode
*/
-
-#define IO_SAPIC_DELIVERY_SHIFT 8
-#define IO_SAPIC_FIXED 0x0
-#define IO_SAPIC_LOWEST_PRIORITY 0x1
-#define IO_SAPIC_PMI 0x2
-#define IO_SAPIC_NMI 0x4
-#define IO_SAPIC_INIT 0x5
-#define IO_SAPIC_EXTINT 0x7
+#define IOSAPIC_DELIVERY_SHIFT 8
+#define IOSAPIC_FIXED 0x0
+#define IOSAPIC_LOWEST_PRIORITY 0x1
+#define IOSAPIC_PMI 0x2
+#define IOSAPIC_NMI 0x4
+#define IOSAPIC_INIT 0x5
+#define IOSAPIC_EXTINT 0x7

/*
* Interrupt polarity
*/
-
-#define IO_SAPIC_POLARITY_SHIFT 13
-#define IO_SAPIC_POL_HIGH 0
-#define IO_SAPIC_POL_LOW 1
+#define IOSAPIC_POLARITY_SHIFT 13
+#define IOSAPIC_POL_HIGH 0
+#define IOSAPIC_POL_LOW 1

/*
* Trigger mode
*/
-
-#define IO_SAPIC_TRIGGER_SHIFT 15
-#define IO_SAPIC_EDGE 0
-#define IO_SAPIC_LEVEL 1
+#define IOSAPIC_TRIGGER_SHIFT 15
+#define IOSAPIC_EDGE 0
+#define IOSAPIC_LEVEL 1

/*
* Mask bit
*/
-
-#define IO_SAPIC_MASK_SHIFT 16
-#define IO_SAPIC_UNMASK 0
-#define IO_SAPIC_MSAK 1
-
-/*
- * Bus types
- */
-#define BUS_ISA 0 /* ISA Bus */
-#define BUS_PCI 1 /* PCI Bus */
-
-#ifndef CONFIG_IA64_PCI_FIRMWARE_IRQ
-struct intr_routing_entry {
- unsigned char srcbus;
- unsigned char srcbusno;
- unsigned char srcbusirq;
- unsigned char iosapic_pin;
- unsigned char dstiosapic;
- unsigned char mode;
- unsigned char trigger;
- unsigned char polarity;
-};
-
-extern struct intr_routing_entry intr_routing[];
-#endif
+#define IOSAPIC_MASK_SHIFT 16
+#define IOSAPIC_UNMASK 0
+#define IOSAPIC_MSAK 1

#ifndef __ASSEMBLY__

-#include <asm/irq.h>
-
-/*
- * IOSAPIC Version Register return 32 bit structure like:
- * {
- * unsigned int version : 8;
- * unsigned int reserved1 : 8;
- * unsigned int pins : 8;
- * unsigned int reserved2 : 8;
- * }
- */
-extern unsigned int iosapic_version(unsigned long);
-extern void iosapic_init(unsigned long, int);
-
-struct iosapic_vector {
- unsigned long iosapic_base; /* IOSAPIC Base address */
- char pin; /* IOSAPIC pin (-1 = No data) */
- unsigned char bus; /* Bus number */
- unsigned char baseirq; /* Base IRQ handled by this IOSAPIC */
- unsigned char bustype; /* Bus type (ISA, PCI, etc) */
- unsigned int busdata; /* Bus specific ID */
- /* These bitfields use the values defined above */
- unsigned char dmode : 3;
- unsigned char polarity : 1;
- unsigned char trigger : 1;
- unsigned char UNUSED : 3;
-};
-extern struct iosapic_vector iosapic_vector[NR_IRQS];
-
-#define iosapic_addr(v) iosapic_vector[v].iosapic_base
-#define iosapic_pin(v) iosapic_vector[v].pin
-#define iosapic_bus(v) iosapic_vector[v].bus
-#define iosapic_baseirq(v) iosapic_vector[v].baseirq
-#define iosapic_bustype(v) iosapic_vector[v].bustype
-#define iosapic_busdata(v) iosapic_vector[v].busdata
-#define iosapic_dmode(v) iosapic_vector[v].dmode
-#define iosapic_trigger(v) iosapic_vector[v].trigger
-#define iosapic_polarity(v) iosapic_vector[v].polarity
+extern void __init iosapic_init (unsigned long address, unsigned int base_irq);
+extern void iosapic_register_legacy_irq (unsigned long irq, unsigned long pin,
+ unsigned long polarity, unsigned long trigger);
+extern void iosapic_pci_fixup (void);

# endif /* !__ASSEMBLY__ */
#endif /* __ASM_IA64_IOSAPIC_H */
diff -urN linux-davidm/include/asm-ia64/machvec.h lia64/include/asm-ia64/machvec.h
--- linux-davidm/include/asm-ia64/machvec.h Thu Aug 24 08:17:47 2000
+++ lia64/include/asm-ia64/machvec.h Mon Oct 30 23:37:09 2000
@@ -31,7 +31,6 @@
typedef void ia64_mv_mca_handler_t (void);
typedef void ia64_mv_cmci_handler_t (int, void *, struct pt_regs *);
typedef void ia64_mv_log_print_t (void);
-typedef void ia64_mv_register_iosapic_t (struct acpi_entry_iosapic *);

extern void machvec_noop (void);

@@ -39,7 +38,7 @@
# include <asm/machvec_hpsim.h>
# elif defined (CONFIG_IA64_DIG)
# include <asm/machvec_dig.h>
-# elif defined (CONFIG_IA64_SGI_SN1_SIM)
+# elif defined (CONFIG_IA64_SGI_SN1)
# include <asm/machvec_sn1.h>
# elif defined (CONFIG_IA64_GENERIC)

@@ -55,7 +54,6 @@
# define platform_cmci_handler ia64_mv.cmci_handler
# define platform_log_print ia64_mv.log_print
# define platform_pci_fixup ia64_mv.pci_fixup
-# define platform_register_iosapic ia64_mv.register_iosapic
# endif

struct ia64_machine_vector {
@@ -68,7 +66,6 @@
ia64_mv_mca_handler_t *mca_handler;
ia64_mv_cmci_handler_t *cmci_handler;
ia64_mv_log_print_t *log_print;
- ia64_mv_register_iosapic_t *register_iosapic;
};

#define MACHVEC_INIT(name) \
@@ -81,8 +78,7 @@
platform_mca_init, \
platform_mca_handler, \
platform_cmci_handler, \
- platform_log_print, \
- platform_register_iosapic \
+ platform_log_print \
}

extern struct ia64_machine_vector ia64_mv;
@@ -116,9 +112,6 @@
#endif
#ifndef platform_pci_fixup
# define platform_pci_fixup ((ia64_mv_pci_fixup_t *) machvec_noop)
-#endif
-#ifndef platform_register_iosapic
-# define platform_register_iosapic ((ia64_mv_register_iosapic_t *) machvec_noop)
#endif

#endif /* _ASM_IA64_MACHVEC_H */
diff -urN linux-davidm/include/asm-ia64/machvec_dig.h lia64/include/asm-ia64/machvec_dig.h
--- linux-davidm/include/asm-ia64/machvec_dig.h Thu Aug 24 08:17:47 2000
+++ lia64/include/asm-ia64/machvec_dig.h Mon Oct 30 22:54:21 2000
@@ -5,7 +5,6 @@
extern ia64_mv_irq_init_t dig_irq_init;
extern ia64_mv_pci_fixup_t dig_pci_fixup;
extern ia64_mv_map_nr_t map_nr_dense;
-extern ia64_mv_register_iosapic_t dig_register_iosapic;

/*
* This stuff has dual use!
@@ -17,8 +16,7 @@
#define platform_name "dig"
#define platform_setup dig_setup
#define platform_irq_init dig_irq_init
-#define platform_pci_fixup dig_pci_fixup
+#define platform_pci_fixup iosapic_pci_fixup
#define platform_map_nr map_nr_dense
-#define platform_register_iosapic dig_register_iosapic

#endif /* _ASM_IA64_MACHVEC_DIG_h */
diff -urN linux-davidm/include/asm-ia64/mca.h lia64/include/asm-ia64/mca.h
--- linux-davidm/include/asm-ia64/mca.h Fri Apr 21 15:21:24 2000
+++ lia64/include/asm-ia64/mca.h Mon Oct 30 22:54:41 2000
@@ -18,6 +18,7 @@
#include <asm/param.h>
#include <asm/sal.h>
#include <asm/processor.h>
+#include <asm/hw_irq.h>

/* These are the return codes from all the IA64_MCA specific interfaces */
typedef int ia64_mca_return_code_t;
@@ -30,9 +31,9 @@
#define IA64_MCA_RENDEZ_TIMEOUT (100 * HZ) /* 1000 milliseconds */

/* Interrupt vectors reserved for MC handling. */
-#define IA64_MCA_RENDEZ_INT_VECTOR 0xF3 /* Rendez interrupt */
-#define IA64_MCA_WAKEUP_INT_VECTOR 0x12 /* Wakeup interrupt */
-#define IA64_MCA_CMC_INT_VECTOR 0xF2 /* Correctable machine check interrupt */
+#define IA64_MCA_RENDEZ_INT_VECTOR MCA_RENDEZ_IRQ /* Rendez interrupt */
+#define IA64_MCA_WAKEUP_INT_VECTOR MCA_WAKEUP_IRQ /* Wakeup interrupt */
+#define IA64_MCA_CMC_INT_VECTOR CMC_IRQ /* Correctable machine check interrupt */

#define IA64_CMC_INT_DISABLE 0
#define IA64_CMC_INT_ENABLE 1
diff -urN linux-davidm/include/asm-ia64/mman.h lia64/include/asm-ia64/mman.h
--- linux-davidm/include/asm-ia64/mman.h Fri Apr 21 15:21:24 2000
+++ lia64/include/asm-ia64/mman.h Mon Oct 30 22:54:48 2000
@@ -23,6 +23,8 @@
#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
#define MAP_LOCKED 0x2000 /* pages are locked */
#define MAP_NORESERVE 0x4000 /* don't check for reservations */
+#define MAP_WRITECOMBINED 0x10000 /* write-combine the area */
+#define MAP_NONCACHED 0x20000 /* don't cache the memory */

#define MS_ASYNC 1 /* sync memory asynchronously */
#define MS_INVALIDATE 2 /* invalidate the caches */
diff -urN linux-davidm/include/asm-ia64/param.h lia64/include/asm-ia64/param.h
--- linux-davidm/include/asm-ia64/param.h Mon Oct 30 23:54:14 2000
+++ lia64/include/asm-ia64/param.h Mon Oct 30 22:55:07 2000
@@ -32,4 +32,8 @@

#define MAXHOSTNAMELEN 64 /* max length of hostname */

+#ifdef __KERNEL__
+# define CLOCKS_PER_SEC HZ /* frequency at which times() counts */
+#endif
+
#endif /* _ASM_IA64_PARAM_H */
diff -urN linux-davidm/include/asm-ia64/processor.h lia64/include/asm-ia64/processor.h
--- linux-davidm/include/asm-ia64/processor.h Mon Oct 30 23:54:14 2000
+++ lia64/include/asm-ia64/processor.h Mon Oct 30 22:56:56 2000
@@ -4,7 +4,7 @@
/*
* Copyright (C) 1998-2000 Hewlett-Packard Co
* Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 1998-2000 Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
* Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
*
@@ -19,7 +19,13 @@
#include <asm/types.h>

#define IA64_NUM_DBG_REGS 8
-#define IA64_NUM_PM_REGS 4
+/*
+ * Limits for PMC and PMD are set to less than maximum architected values
+ * but should be sufficient for a while
+ */
+#define IA64_NUM_PMC_REGS 32
+#define IA64_NUM_PMD_REGS 32
+#define IA64_NUM_PMD_COUNTERS 4

/*
* TASK_SIZE really is a mis-named. It really is the maximum user
@@ -288,10 +294,15 @@
__u64 dbr[IA64_NUM_DBG_REGS];
__u64 ibr[IA64_NUM_DBG_REGS];
#ifdef CONFIG_PERFMON
- __u64 pmc[IA64_NUM_PM_REGS];
- __u64 pmd[IA64_NUM_PM_REGS];
- __u64 pmod[IA64_NUM_PM_REGS];
-# define INIT_THREAD_PM {0, }, {0, }, {0, },
+ __u64 pmc[IA64_NUM_PMC_REGS];
+ __u64 pmd[IA64_NUM_PMD_REGS];
+ struct {
+ __u64 val; /* virtual 64bit counter */
+ __u64 rval; /* reset value on overflow */
+ int sig; /* signal used to notify */
+ int pid; /* process to notify */
+ } pmu_counters[IA64_NUM_PMD_COUNTERS];
+# define INIT_THREAD_PM {0, }, {0, }, {{ 0, 0, 0, 0}, },
#else
# define INIT_THREAD_PM
#endif
@@ -423,8 +434,8 @@
#endif

#ifdef CONFIG_PERFMON
-extern void ia64_save_pm_regs (struct thread_struct *thread);
-extern void ia64_load_pm_regs (struct thread_struct *thread);
+extern void ia64_save_pm_regs (struct task_struct *task);
+extern void ia64_load_pm_regs (struct task_struct *task);
#endif

#define ia64_fph_enable() __asm__ __volatile__ (";; rsm psr.dfh;; srlz.d;;" ::: "memory");
diff -urN linux-davidm/include/asm-ia64/spinlock.h lia64/include/asm-ia64/spinlock.h
--- linux-davidm/include/asm-ia64/spinlock.h Mon Oct 30 23:54:14 2000
+++ lia64/include/asm-ia64/spinlock.h Mon Oct 30 22:57:29 2000
@@ -18,8 +18,9 @@
#undef NEW_LOCK

#ifdef NEW_LOCK
+
typedef struct {
- volatile unsigned char lock;
+ volatile unsigned int lock;
} spinlock_t;

#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
@@ -38,7 +39,7 @@
"mov r30=1\n" \
"mov ar.ccv=r0\n" \
";;\n" \
- IA64_SEMFIX"cmpxchg1.acq r30=[%0],r30,ar.ccv\n" \
+ IA64_SEMFIX"cmpxchg4.acq r30=[%0],r30,ar.ccv\n" \
";;\n" \
"cmp.ne p15,p0=r30,r0\n" \
"(p15) br.call.spnt.few b7=ia64_spinlock_contention\n" \
@@ -48,18 +49,16 @@
: "ar.ccv", "ar.pfs", "b7", "p15", "r28", "r29", "r30", "memory"); \
}

-#define spin_trylock(x) \
-({ \
- register char *addr __asm__ ("r31") = (char *) &(x)->lock; \
- register long result; \
- \
- __asm__ __volatile__ ( \
- "mov r30=1\n" \
- "mov ar.ccv=r0\n" \
- ";;\n" \
- IA64_SEMFIX"cmpxchg1.acq %0=[%1],r30,ar.ccv\n" \
- : "=r"(result) : "r"(addr) : "ar.ccv", "r30", "memory"); \
- (result = 0); \
+#define spin_trylock(x) \
+({ \
+ register long result; \
+ \
+ __asm__ __volatile__ ( \
+ "mov ar.ccv=r0\n" \
+ ";;\n" \
+ IA64_SEMFIX"cmpxchg4.acq %0=[%2],%1,ar.ccv\n" \
+ : "=r"(result) : "r"(1), "r"(&(x)->lock) : "ar.ccv", "memory"); \
+ (result = 0); \
})

#define spin_is_locked(x) ((x)->lock != 0)
diff -urN linux-davidm/include/asm-ia64/system.h lia64/include/asm-ia64/system.h
--- linux-davidm/include/asm-ia64/system.h Mon Oct 30 23:54:14 2000
+++ lia64/include/asm-ia64/system.h Mon Oct 30 22:57:47 2000
@@ -27,7 +27,8 @@

#define GATE_ADDR (0xa000000000000000 + PAGE_SIZE)

-#if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_ITANIUM_BSTEP_SPECIFIC)
+#if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) \
+ || defined(CONFIG_ITANIUM_B0_SPECIFIC) || defined(CONFIG_ITANIUM_B1_SPECIFIC)
/* Workaround for Errata 97. */
# define IA64_SEMFIX_INSN mf;
# define IA64_SEMFIX "mf;"
diff -urN linux-davidm/include/asm-ia64/uaccess.h lia64/include/asm-ia64/uaccess.h
--- linux-davidm/include/asm-ia64/uaccess.h Mon Oct 30 23:54:14 2000
+++ lia64/include/asm-ia64/uaccess.h Mon Oct 30 22:58:00 2000
@@ -125,46 +125,28 @@
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))

-#define __get_user_64(addr) \
+/* We need to declare the __ex_table section before we can use it in .xdata. */
+__asm__ (".section \"__ex_table\", \"a\"\n\t.previous");
+
+#define __get_user_64(addr) \
__asm__ ("\n1:\tld8 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \
- "2:\n" \
- "\t.section __ex_table,\"a\"\n" \
- "\t\tdata4 @gprel(1b)\n" \
- "\t\tdata4 (2b-1b)|1\n" \
- "\t.previous" \
- : "=r"(__gu_val), "=r"(__gu_err) \
- : "m"(__m(addr)), "1"(__gu_err));
+ "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n" \
+ : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));

-#define __get_user_32(addr) \
+#define __get_user_32(addr) \
__asm__ ("\n1:\tld4 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \
- "2:\n" \
- "\t.section __ex_table,\"a\"\n" \
- "\t\tdata4 @gprel(1b)\n" \
- "\t\tdata4 (2b-1b)|1\n" \
- "\t.previous" \
- : "=r"(__gu_val), "=r"(__gu_err) \
- : "m"(__m(addr)), "1"(__gu_err));
+ "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n" \
+ : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));

-#define __get_user_16(addr) \
+#define __get_user_16(addr) \
__asm__ ("\n1:\tld2 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \
- "2:\n" \
- "\t.section __ex_table,\"a\"\n" \
- "\t\tdata4 @gprel(1b)\n" \
- "\t\tdata4 (2b-1b)|1\n" \
- "\t.previous" \
- : "=r"(__gu_val), "=r"(__gu_err) \
- : "m"(__m(addr)), "1"(__gu_err));
+ "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n" \
+ : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));

-#define __get_user_8(addr) \
+#define __get_user_8(addr) \
__asm__ ("\n1:\tld1 %0=%2%P2\t// %0 and %1 get overwritten by exception handler\n" \
- "2:\n" \
- "\t.section __ex_table,\"a\"\n" \
- "\t\tdata4 @gprel(1b)\n" \
- "\t\tdata4 (2b-1b)|1\n" \
- "\t.previous" \
- : "=r"(__gu_val), "=r"(__gu_err) \
- : "m"(__m(addr)), "1"(__gu_err));
-
+ "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)|1\n" \
+ : "=r"(__gu_val), "=r"(__gu_err) : "m"(__m(addr)), "1"(__gu_err));

extern void __put_user_unknown (void);

@@ -206,46 +188,26 @@
#define __put_user_64(x,addr) \
__asm__ __volatile__ ( \
"\n1:\tst8 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \
- "2:\n" \
- "\t.section __ex_table,\"a\"\n" \
- "\t\tdata4 @gprel(1b)\n" \
- "\t\tdata4 2b-1b\n" \
- "\t.previous" \
- : "=r"(__pu_err) \
- : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
+ "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n" \
+ : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))

#define __put_user_32(x,addr) \
__asm__ __volatile__ ( \
"\n1:\tst4 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \
- "2:\n" \
- "\t.section __ex_table,\"a\"\n" \
- "\t\tdata4 @gprel(1b)\n" \
- "\t\tdata4 2b-1b\n" \
- "\t.previous" \
- : "=r"(__pu_err) \
- : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
+ "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n" \
+ : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))

#define __put_user_16(x,addr) \
__asm__ __volatile__ ( \
"\n1:\tst2 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \
- "2:\n" \
- "\t.section __ex_table,\"a\"\n" \
- "\t\tdata4 @gprel(1b)\n" \
- "\t\tdata4 2b-1b\n" \
- "\t.previous" \
- : "=r"(__pu_err) \
- : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
+ "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n" \
+ : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))

#define __put_user_8(x,addr) \
__asm__ __volatile__ ( \
"\n1:\tst1 %1=%r2%P1\t// %0 gets overwritten by exception handler\n" \
- "2:\n" \
- "\t.section __ex_table,\"a\"\n" \
- "\t\tdata4 @gprel(1b)\n" \
- "\t\tdata4 2b-1b\n" \
- "\t.previous" \
- : "=r"(__pu_err) \
- : "m"(__m(addr)), "rO"(x), "0"(__pu_err))
+ "2:\n\t.xdata4 \"__ex_table\", @gprel(1b), (2b-1b)\n" \
+ : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err))

/*
* Complex access routines
diff -urN linux-davidm/include/asm-ia64/unistd.h lia64/include/asm-ia64/unistd.h
--- linux-davidm/include/asm-ia64/unistd.h Mon Oct 30 23:54:14 2000
+++ lia64/include/asm-ia64/unistd.h Tue Oct 31 00:18:03 2000
@@ -160,7 +160,7 @@
#define __NR_nanosleep 1168
#define __NR_nfsservctl 1169
#define __NR_prctl 1170
-#define __NR_getpagesize 1171
+/* 1171 is reserved for backwards compatibility with old __NR_getpagesize */
#define __NR_mmap2 1172
#define __NR_pciconfig_read 1173
#define __NR_pciconfig_write 1174
diff -urN linux-davidm/include/linux/elf.h lia64/include/linux/elf.h
--- linux-davidm/include/linux/elf.h Wed Oct 4 16:53:43 2000
+++ lia64/include/linux/elf.h Mon Oct 30 22:58:27 2000
@@ -165,6 +165,7 @@
#define AT_EGID 14 /* effective gid */
#define AT_PLATFORM 15 /* string identifying CPU for optimizations */
#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */
+#define AT_CLKTCK 17 /* frequency at which times() increments */

typedef struct dynamic{
Elf32_Sword d_tag;
diff -urN linux-davidm/include/linux/mm.h lia64/include/linux/mm.h
--- linux-davidm/include/linux/mm.h Wed Oct 4 16:53:43 2000
+++ lia64/include/linux/mm.h Mon Oct 30 22:58:40 2000
@@ -95,6 +95,8 @@

#define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork */
#define VM_DONTEXPAND 0x00040000 /* Cannot expand with mremap() */
+#define VM_WRITECOMBINED 0x00100000 /* Write-combined */
+#define VM_NONCACHED 0x00200000 /* Noncached access */

#define VM_STACK_FLAGS 0x00000177

diff -urN linux-davidm/mm/mmap.c lia64/mm/mmap.c
--- linux-davidm/mm/mmap.c Fri Sep 8 14:35:08 2000
+++ lia64/mm/mmap.c Mon Oct 30 23:02:32 2000
@@ -151,6 +151,12 @@
_trans(prot, PROT_WRITE, VM_WRITE) |
_trans(prot, PROT_EXEC, VM_EXEC);
flag_bits +#ifdef MAP_WRITECOMBINED
+ _trans(flags, MAP_WRITECOMBINED, VM_WRITECOMBINED) |
+#endif
+#ifdef MAP_NONCACHED
+ _trans(flags, MAP_NONCACHED, VM_NONCACHED) |
+#endif
_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN) |
_trans(flags, MAP_DENYWRITE, VM_DENYWRITE) |
_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE);