[Linux-ia64] kernel update (relative to 2.4.10)

David Mosberger
2001-09-25T07:13:28Z

Here is a long-awaited kernel update which brings us in sync with
2.4.10. As usual, it's available at
ftp://ftp.kernel.org/pub/linux/kernel/ports/ia64/ in file:

linux-2.4.10-ia64-010924.diff*

The major changes this time include:

- Major ia32 subsystem update by yours truly:
- enable use of emulator prefix: for a non-directory file with
path PATH, the ia32 subsystem now uses /emul/ia32-linux/PATH
if the file exists
- fix a nasty bug which caused ia32 binaries to subtly corrupt
page table page (this was the reason "realplay" often crashed
on start up, but the bug could affect any process, not just
ia32 processes)
- make the address space layout of ia32 tasks match that of
a real linux/x86 task; in particular, the stack now starts
at 0xc0000000 (and grows towards lower addresses)
- fix emulated mmap() and mprotect() to work when page size is 4K
and work better when the page size is larger
- fix emulated ptrace() sys x86 strace() works
- fill in missing system calls (pread, pwrite, sendfile, SuS-compliant
getrlimit, mmap2, {,f}truncate64, {,l,f}stat64, 32-bit uid/gid
versions of lchown, getuid etc., pivot_root, mincore, madvise,
getdents64, fcntl64) and drop some unsupported ones
(module related syscalls, vm86, bdflush)
- support signal delivery with SA_RESTORER sigreturn
- don't align shared mmap()s to 1MB---this filled up a 32-bit address
space too quickly
with these fixes in place, I'm able to successfully run the ia32
versions of realplay, OpenOffice, mozilla, netscape, acrobat, strace,
Intel compilers, etc. But as usual, your mileage may vary.
- update perform to v0.3 (Stephane Eranian)
- SN updates from SGI (just a starter, more to follow...)
- be more consistent about using i-cache prefetches (use .few for branches
within a routine, .many otherwise)
- fix alternate stack signal delivery (used to break if the old stack
didn't have enough memory to hold the dirty stacked registers); ironically,
this fix probably also speeds up this case (it's no longer necessary
to do a flushrs...)
- McKinley related I/O SAPIC updates from Alex Williamson
- fix irq bug which caused console keyboard to report timeout when
pressing the caps lock key (Richard Hirst)
- fix ptrace race condition (thanks to Shoichi Sakon for providing
a test case that reproduced this problem)
- turn on dcr.lc by default
- many sync-ups for 2.4.10 (thanks to KOCHI Takayoshi for sending a timely
ACPI update)

I should warn that this kernel has received only moderate testing so
far. The remote access server I'm normally using to access a test
ia64 machine crashed just shortly before making the patch, so I wasn't
able to do my usual round of testing. Having said that, the kernel
seems to work fine on a dual Itanium Big Sur, so there is hope. As
you know, Linus and co decided to basically rewrite the VM system. As
far as I can tell, this hasn't had any negative impact on ia64, but
I'd recommend doing a lot of testing before declaring this kernel as
ready for prime time.

Oh, and as usual, the patch below is fyi, only. The the full patch
for definite answers.

Enjoy,

--david

diff -urN linux-davidm/Documentation/Configure.help linux-2.4.10-lia/Documentation/Configure.help
--- linux-davidm/Documentation/Configure.help Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/Documentation/Configure.help Mon Sep 24 21:34:01 2001
@@ -18686,10 +18686,21 @@
so the "DIG-compliant" option is usually the right choice.

HP-simulator For the HP simulator (http://software.hp.com/ia64linux/).
- SN1-simulator For the SGI SN1 simulator.
+ SGI-SN1 For SGI SN1 Platforms.
+ SGI-SN2 For SGI SN2 Platforms.
DIG-compliant For DIG ("Developer's Interface Guide") compliant system.

If you don't know what to do, choose "generic".
+
+CONFIG_IA64_SGI_SN_SIM
+ Build a kernel that runs on both the SGI simulator AND on hardware.
+ There is a very slight performance penalty on hardware for including this
+ option.
+
+CONFIG_IA64_SGI_SN_DEBUG
+ This enables addition debug code that helps isolate
+ platform/kernel bugs. There is a small but measurable performance
+ degradation when this option is enabled.

Kernel page size
CONFIG_IA64_PAGE_SIZE_4KB
diff -urN linux-davidm/arch/ia64/Makefile linux-2.4.10-lia/arch/ia64/Makefile
--- linux-davidm/arch/ia64/Makefile Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/Makefile Mon Sep 24 22:20:41 2001
@@ -17,7 +17,9 @@
AFLAGS_KERNEL := -mconstant-gp
EXTRA
-CFLAGS := $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-rangeñ0-f15,f32-f127 -falign-functions2
+CFLAGS := $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-rangeñ0-f15,f32-f127 \
+ -falign-functions2 --param max-inline-insns@0
+# -ffunction-sections
CFLAGS_KERNEL := -mconstant-gp

GCC_VERSION=$(shell $(CROSS_COMPILE)$(HOSTCC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
@@ -32,7 +34,7 @@

ifdef CONFIG_IA64_GENERIC
CORE_FILES := arch/$(ARCH)/hp/hp.a \
- arch/$(ARCH)/sn/sn.a \
+ arch/$(ARCH)/sn/sn.o \
arch/$(ARCH)/dig/dig.a \
arch/$(ARCH)/sn/io/sgiio.o \
$(CORE_FILES)
@@ -52,15 +54,14 @@
$(CORE_FILES)
endif

-ifdef CONFIG_IA64_SGI_SN1
+ifdef CONFIG_IA64_SGI_SN
CFLAGS += -DBRINGUP
- SUBDIRS := arch/$(ARCH)/sn/sn1 \
- arch/$(ARCH)/sn \
+ SUBDIRS := arch/$(ARCH)/sn/kernel \
arch/$(ARCH)/sn/io \
arch/$(ARCH)/sn/fprom \
$(SUBDIRS)
- CORE_FILES := arch/$(ARCH)/sn/sn.a \
- arch/$(ARCH)/sn/io/sgiio.o\
+ CORE_FILES := arch/$(ARCH)/sn/kernel/sn.o \
+ arch/$(ARCH)/sn/io/sgiio.o \
$(CORE_FILES)
endif

diff -urN linux-davidm/arch/ia64/config.in linux-2.4.10-lia/arch/ia64/config.in
--- linux-davidm/arch/ia64/config.in Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/config.in Mon Sep 24 21:43:20 2001
@@ -28,6 +28,7 @@

if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
define_bool CONFIG_ACPI y
+ define_bool CONFIG_ACPI_EFI y
define_bool CONFIG_ACPI_INTERPRETER y
define_bool CONFIG_ACPI_KERNEL_CONFIG y
fi
@@ -40,7 +41,8 @@
"generic CONFIG_IA64_GENERIC \
DIG-compliant CONFIG_IA64_DIG \
HP-simulator CONFIG_IA64_HP_SIM \
- SGI-SN1 CONFIG_IA64_SGI_SN1" generic
+ SGI-SN1 CONFIG_IA64_SGI_SN1 \
+ SGI-SN2 CONFIG_IA64_SGI_SN2" generic

choice 'Kernel page size' \
"4KB CONFIG_IA64_PAGE_SIZE_4KB \
@@ -71,18 +73,22 @@
define_bool CONFIG_PM y
fi

-if [ "$CONFIG_IA64_SGI_SN1" = "y" ]; then
- bool ' Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN1_SIM
- define_bool CONFIG_DEVFS_DEBUG y
+if [ "$CONFIG_IA64_SGI_SN1" = "y" ] || [ "$CONFIG_IA64_SGI_SN2" = "y" ]; then
+ define_bool CONFIG_IA64_SGI_SN y
+ bool ' Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG n
+ bool ' Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN_SIM
+ bool ' Enable autotest (llsc). Option to run cache test instead of booting' \
+ CONFIG_IA64_SGI_AUTOTEST n
define_bool CONFIG_DEVFS_FS y
- define_bool CONFIG_IA64_BRL_EMU y
+ if [ "$CONFIG_DEVFS_FS" = "y" ]; then
+ bool ' Enable DEVFS Debug Code' CONFIG_DEVFS_DEBUG n
+ fi
+ bool ' Enable protocol mode for the L1 console' CONFIG_SERIAL_SGI_L1_PROTOCOL y
+ define_bool CONFIG_DISCONTIGMEM y
define_bool CONFIG_IA64_MCA y
- define_bool CONFIG_ITANIUM y
- define_bool CONFIG_SGI_IOC3_ETH y
+ define_bool CONFIG_NUMA y
define_bool CONFIG_PERCPU_IRQ y
- define_int CONFIG_CACHE_LINE_SHIFT 7
- bool ' Enable DISCONTIGMEM support' CONFIG_DISCONTIGMEM
- bool ' Enable NUMA support' CONFIG_NUMA
+ tristate ' PCIBA support' CONFIG_PCIBA
fi

define_bool CONFIG_KCORE_ELF y # On IA-64, we always want an ELF /proc/kcore.
@@ -250,13 +256,19 @@
mainmenu_option next_comment
comment 'Kernel hacking'

-#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
-
-bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
-bool 'Early printk support (requires VGA!)' CONFIG_IA64_EARLY_PRINTK
-bool 'Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
-bool 'Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ
-bool 'Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS
-bool 'Disable VHPT' CONFIG_DISABLE_VHPT
+bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
+if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
+ bool ' Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS
+ bool ' Disable VHPT' CONFIG_DISABLE_VHPT
+ bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
+
+# early printk is currently broken for SMP: the secondary processors get stuck...
+# bool ' Early printk support (requires VGA!)' CONFIG_IA64_EARLY_PRINTK
+
+ bool ' Debug memory allocations' CONFIG_DEBUG_SLAB
+ bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+ bool ' Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
+ bool ' Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ
+fi

endmenu
diff -urN linux-davidm/arch/ia64/defconfig linux-2.4.10-lia/arch/ia64/defconfig
--- linux-davidm/arch/ia64/defconfig Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/defconfig Mon Sep 24 22:23:50 2001
@@ -25,6 +25,7 @@
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_ACPI=y
+CONFIG_ACPI_EFI=y
CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_KERNEL_CONFIG=y
CONFIG_ITANIUM=y
@@ -33,6 +34,7 @@
CONFIG_IA64_DIG=y
# CONFIG_IA64_HP_SIM is not set
# CONFIG_IA64_SGI_SN1 is not set
+# CONFIG_IA64_SGI_SN2 is not set
# CONFIG_IA64_PAGE_SIZE_4KB is not set
# CONFIG_IA64_PAGE_SIZE_8KB is not set
CONFIG_IA64_PAGE_SIZE_16KB=y
@@ -44,6 +46,7 @@
CONFIG_PM=y
CONFIG_KCORE_ELF=y
CONFIG_SMP=y
+CONFIG_IA32_SUPPORT=y
CONFIG_PERFMON=y
CONFIG_IA64_PALINFO=y
CONFIG_EFI_VARS=y
@@ -159,6 +162,7 @@
# CONFIG_MD_RAID0 is not set
# CONFIG_MD_RAID1 is not set
# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
# CONFIG_BLK_DEV_LVM is not set

#
@@ -203,6 +207,7 @@
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_BLK_DEV_ADMA=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_IDEDMA_PCI_AUTO is not set
CONFIG_BLK_DEV_IDEDMA=y
@@ -212,8 +217,8 @@
# CONFIG_AEC62XX_TUNING is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_WDC_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD7409 is not set
-# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_AMD74XX_OVERRIDE is not set
# CONFIG_BLK_DEV_CMD64X is not set
# CONFIG_BLK_DEV_CY82C693 is not set
# CONFIG_BLK_DEV_CS5530 is not set
@@ -226,7 +231,8 @@
# CONFIG_BLK_DEV_OPTI621 is not set
# CONFIG_BLK_DEV_PDC202XX is not set
# CONFIG_PDC202XX_BURST is not set
-# CONFIG_BLK_DEV_OSB4 is not set
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
@@ -236,6 +242,9 @@
# CONFIG_IDEDMA_IVB is not set
# CONFIG_DMA_NONPCI is not set
CONFIG_BLK_DEV_IDE_MODES=y
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set

#
# SCSI support
@@ -271,6 +280,7 @@
# CONFIG_SCSI_AHA1740 is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_AM53C974 is not set
@@ -288,6 +298,7 @@
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_NCR_D700 is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_NCR53C8XX is not set
# CONFIG_SCSI_SYM53C8XX is not set
@@ -325,7 +336,6 @@
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_ARM_AM79C961A is not set
# CONFIG_SUNLANCE is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNBMAC is not set
@@ -344,8 +354,6 @@
# CONFIG_APRICOT is not set
# CONFIG_CS89x0 is not set
# CONFIG_TULIP is not set
-# CONFIG_TULIP_MWI is not set
-# CONFIG_TULIP_MMIO is not set
# CONFIG_DE4X5 is not set
# CONFIG_DGRS is not set
# CONFIG_DM9102 is not set
@@ -366,15 +374,16 @@
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_WINBOND_840 is not set
+# CONFIG_LAN_SAA9730 is not set
# CONFIG_NET_POCKET is not set

#
# Ethernet (1000 Mbit)
#
# CONFIG_ACENIC is not set
-# CONFIG_ACENIC_OMIT_TIGON_I is not set
# CONFIG_DL2K is not set
# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_SK98LIN is not set
@@ -457,11 +466,37 @@
#
# Joysticks
#
-# CONFIG_JOYSTICK is not set
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+CONFIG_INPUT_SERIO=y
+CONFIG_INPUT_SERPORT=y

#
-# Input core support is needed for joysticks
+# Joysticks
#
+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set
+# CONFIG_INPUT_TURBOGRAFX is not set
# CONFIG_QIC02_TAPE is not set

#
@@ -484,21 +519,21 @@
CONFIG_AGP=y
# CONFIG_AGP_INTEL is not set
CONFIG_AGP_I460=y
-# CONFIG_AGP_I460_FULLRQ is not set
# CONFIG_AGP_I810 is not set
# CONFIG_AGP_VIA is not set
# CONFIG_AGP_AMD is not set
# CONFIG_AGP_SIS is not set
# CONFIG_AGP_ALI is not set
# CONFIG_AGP_SWORKS is not set
-CONFIG_AGP_PTE_FIXUPS=y
CONFIG_DRM=y
-CONFIG_DRM_TDFX=y
-# CONFIG_DRM_GAMMA is not set
-# CONFIG_DRM_R128 is not set
-# CONFIG_DRM_RADEON is not set
-# CONFIG_DRM_I810 is not set
-# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_NEW is not set
+CONFIG_DRM_OLD=y
+CONFIG_DRM40_TDFX=y
+# CONFIG_DRM40_GAMMA is not set
+# CONFIG_DRM40_R128 is not set
+# CONFIG_DRM40_RADEON is not set
+# CONFIG_DRM40_I810 is not set
+# CONFIG_DRM40_MGA is not set

#
# Multimedia devices
@@ -612,8 +647,23 @@
#
# Partition Types
#
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_DEVFS_GUID is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
# CONFIG_SMB_NLS is not set
CONFIG_NLS=y

@@ -672,8 +722,10 @@
# Sound
#
CONFIG_SOUND=y
+# CONFIG_SOUND_BT878 is not set
# CONFIG_SOUND_CMPCI is not set
# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_MIDI_EMU10K1 is not set
# CONFIG_SOUND_FUSION is not set
CONFIG_SOUND_CS4281=y
# CONFIG_SOUND_ES1370 is not set
@@ -682,6 +734,7 @@
# CONFIG_SOUND_MAESTRO is not set
# CONFIG_SOUND_MAESTRO3 is not set
# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_RME96XX is not set
# CONFIG_SOUND_SONICVIBES is not set
# CONFIG_SOUND_TRIDENT is not set
# CONFIG_SOUND_MSNDCLAS is not set
@@ -747,10 +800,11 @@
#
# USB Network adaptors
#
-# CONFIG_USB_PLUSB is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_CATC is not set
-# CONFIG_USB_NET1080 is not set
+# CONFIG_USB_CDCETHER is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_USBNET is not set

#
# USB port drivers
@@ -775,11 +829,11 @@
#
# Kernel hacking
#
-CONFIG_IA32_SUPPORT=y
-CONFIG_MATHEMU=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_IA64_PRINT_HAZARDS=y
+# CONFIG_DISABLE_VHPT is not set
CONFIG_MAGIC_SYSRQ=y
-CONFIG_IA64_EARLY_PRINTK=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_IA64_DEBUG_CMPXCHG is not set
# CONFIG_IA64_DEBUG_IRQ is not set
-CONFIG_IA64_PRINT_HAZARDS=y
-# CONFIG_DISABLE_VHPT is not set
diff -urN linux-davidm/arch/ia64/ia32/binfmt_elf32.c linux-2.4.10-lia/arch/ia64/ia32/binfmt_elf32.c
--- linux-davidm/arch/ia64/ia32/binfmt_elf32.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/ia32/binfmt_elf32.c Mon Sep 24 21:43:45 2001
@@ -3,10 +3,11 @@
*
* Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
* Copyright (C) 2001 Hewlett-Packard Co
- * Copyright (C) 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*
* 06/16/00 A. Mallick initialize csd/ssd/tssd/cflg for ia32_load_state
* 04/13/01 D. Mosberger dropped saving tssd in ar.k1---it's not needed
+ * 09/14/01 D. Mosberger fixed memory management for gdt/tss page
*/
#include <linux/config.h>

@@ -41,51 +42,32 @@
extern void ia64_elf32_init (struct pt_regs *regs);
extern void put_dirty_page (struct task_struct * tsk, struct page *page, unsigned long address);

+static void elf32_set_personality (void);
+
#define ELF_PLAT_INIT(_r) ia64_elf32_init(_r)
#define setup_arg_pages(bprm) ia32_setup_arg_pages(bprm)
-#define elf_map elf_map32
+#define elf_map elf32_map
+#define SET_PERSONALITY(ex, ibcs2) elf32_set_personality()

/* Ugly but avoids duplication */
#include "../../../fs/binfmt_elf.c"

-/* Global descriptor table */
-unsigned long *ia32_gdt_table, *ia32_tss;
+extern struct page *ia32_shared_page[];
+extern unsigned long *ia32_gdt;

struct page *
-put_shared_page (struct task_struct * tsk, struct page *page, unsigned long address)
+ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int no_share)
{
- pgd_t * pgd;
- pmd_t * pmd;
- pte_t * pte;
-
- if (page_count(page) != 1)
- printk("mem_map disagrees with %p at %08lx\n", (void *) page, address);
+ struct page *pg = ia32_shared_page[(address - vma->vm_start)/PAGE_SIZE];

- pgd = pgd_offset(tsk->mm, address);
-
- spin_lock(&tsk->mm->page_table_lock);
- {
- pmd = pmd_alloc(tsk->mm, pgd, address);
- if (!pmd)
- goto out;
- pte = pte_alloc(tsk->mm, pmd, address);
- if (!pte)
- goto out;
- if (!pte_none(*pte))
- goto out;
- flush_page_to_ram(page);
- set_pte(pte, pte_mkwrite(mk_pte(page, PAGE_SHARED)));
- }
- spin_unlock(&tsk->mm->page_table_lock);
- /* no need for flush_tlb */
- return page;
-
- out:
- spin_unlock(&tsk->mm->page_table_lock);
- __free_page(page);
- return 0;
+ get_page(pg);
+ return pg;
}

+static struct vm_operations_struct ia32_shared_page_vm_ops = {
+ nopage: ia32_install_shared_page
+};
+
void
ia64_elf32_init (struct pt_regs *regs)
{
@@ -97,9 +79,23 @@
* it with privilege level 3 because the IVE uses non-privileged accesses to these
* tables. IA-32 segmentation is used to protect against IA-32 accesses to them.
*/
- put_shared_page(current, virt_to_page(ia32_gdt_table), IA32_GDT_OFFSET);
- if (PAGE_SHIFT <= IA32_PAGE_SHIFT)
- put_shared_page(current, virt_to_page(ia32_tss), IA32_TSS_OFFSET);
+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (vma) {
+ vma->vm_mm = current->mm;
+ vma->vm_start = IA32_GDT_OFFSET;
+ vma->vm_end = vma->vm_start + max(PAGE_SIZE, 2*IA32_PAGE_SIZE);
+ vma->vm_page_prot = PAGE_SHARED;
+ vma->vm_flags = VM_READ|VM_MAYREAD;
+ vma->vm_ops = &ia32_shared_page_vm_ops;
+ vma->vm_pgoff = 0;
+ vma->vm_file = NULL;
+ vma->vm_private_data = NULL;
+ down_write(&current->mm->mmap_sem);
+ {
+ insert_vm_struct(current->mm, vma);
+ }
+ up_write(&current->mm->mmap_sem);
+ }

/*
* Install LDT as anonymous memory. This gives us all-zero segment descriptors
@@ -116,25 +112,25 @@
vma->vm_pgoff = 0;
vma->vm_file = NULL;
vma->vm_private_data = NULL;
- insert_vm_struct(current->mm, vma);
+ down_write(&current->mm->mmap_sem);
+ {
+ insert_vm_struct(current->mm, vma);
+ }
+ up_write(&current->mm->mmap_sem);
}

nr = smp_processor_id();

- current->thread.map_base = IA32_PAGE_OFFSET/3;
- current->thread.task_size = IA32_PAGE_OFFSET; /* use what Linux/x86 uses... */
- set_fs(USER_DS); /* set addr limit for new TASK_SIZE */
-
/* Setup the segment selectors */
regs->r16 = (__USER_DS << 16) | __USER_DS; /* ES = DS, GS, FS are zero */
regs->r17 = (__USER_DS << 16) | __USER_CS; /* SS, CS; ia32_load_state() sets TSS and LDT */

/* Setup the segment descriptors */
- regs->r24 = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_DS >> 3]); /* ESD */
- regs->r27 = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_DS >> 3]); /* DSD */
+ regs->r24 = IA32_SEG_UNSCRAMBLE(ia32_gdt[__USER_DS >> 3]); /* ESD */
+ regs->r27 = IA32_SEG_UNSCRAMBLE(ia32_gdt[__USER_DS >> 3]); /* DSD */
regs->r28 = 0; /* FSD (null) */
regs->r29 = 0; /* GSD (null) */
- regs->r30 = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[_LDT(nr)]); /* LDTD */
+ regs->r30 = IA32_SEG_UNSCRAMBLE(ia32_gdt[_LDT(nr)]); /* LDTD */

/*
* Setup GDTD. Note: GDTD is the descrambled version of the pseudo-descriptor
@@ -164,9 +160,9 @@
current->thread.fcr = IA32_FCR_DEFAULT;
current->thread.fir = 0;
current->thread.fdr = 0;
- current->thread.csd = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_CS >> 3]);
- current->thread.ssd = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[__USER_DS >> 3]);
- current->thread.tssd = IA32_SEG_UNSCRAMBLE(ia32_gdt_table[_TSS(nr)]);
+ current->thread.csd = IA32_SEG_UNSCRAMBLE(ia32_gdt[__USER_CS >> 3]);
+ current->thread.ssd = IA32_SEG_UNSCRAMBLE(ia32_gdt[__USER_DS >> 3]);
+ current->thread.tssd = IA32_SEG_UNSCRAMBLE(ia32_gdt[_TSS(nr)]);

ia32_load_state(current);
}
@@ -189,6 +185,7 @@
if (!mpnt)
return -ENOMEM;

+ down_write(&current->mm->mmap_sem);
{
mpnt->vm_mm = current->mm;
mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
@@ -204,54 +201,32 @@
}

for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
- if (bprm->page[i]) {
- put_dirty_page(current,bprm->page[i],stack_base);
+ struct page *page = bprm->page[i];
+ if (page) {
+ bprm->page[i] = NULL;
+ put_dirty_page(current, page, stack_base);
}
stack_base += PAGE_SIZE;
}
+ up_write(&current->mm->mmap_sem);

return 0;
}

-static unsigned long
-ia32_mm_addr (unsigned long addr)
+static void
+elf32_set_personality (void)
{
- struct vm_area_struct *vma;
-
- if ((vma = find_vma(current->mm, addr)) = NULL)
- return ELF_PAGESTART(addr);
- if (vma->vm_start > addr)
- return ELF_PAGESTART(addr);
- return ELF_PAGEALIGN(addr);
+ set_personality(PER_LINUX32);
+ current->thread.map_base = IA32_PAGE_OFFSET/3;
+ current->thread.task_size = IA32_PAGE_OFFSET; /* use what Linux/x86 uses... */
+ set_fs(USER_DS); /* set addr limit for new TASK_SIZE */
}

-/*
- * Normally we would do an `mmap' to map in the process's text section.
- * This doesn't work with IA32 processes as the ELF file might specify
- * a non page size aligned address. Instead we will just allocate
- * memory and read the data in from the file. Slightly less efficient
- * but it works.
- */
-extern long ia32_do_mmap (struct file *filep, unsigned int len, unsigned int prot,
- unsigned int flags, unsigned int fd, unsigned int offset);
-
static unsigned long
-elf_map32 (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
+elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
{
- unsigned long retval;
-
- if (eppnt->p_memsz >= (1UL<<32) || addr > (1UL<<32) - eppnt->p_memsz)
- return -EINVAL;
+ unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK;

- /*
- * 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;
- set_brk(ia32_mm_addr(addr), addr + eppnt->p_memsz);
- memset((char *) addr + eppnt->p_filesz, 0, eppnt->p_memsz - eppnt->p_filesz);
- kernel_read(filep, eppnt->p_offset, (char *) addr, eppnt->p_filesz);
- retval = (unsigned long) addr;
- return retval;
+ return ia32_do_mmap(filep, (addr & IA32_PAGE_MASK), eppnt->p_filesz + pgoff, prot, type,
+ eppnt->p_offset - pgoff);
}
diff -urN linux-davidm/arch/ia64/ia32/ia32_entry.S linux-2.4.10-lia/arch/ia64/ia32/ia32_entry.S
--- linux-davidm/arch/ia64/ia32/ia32_entry.S Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/ia32/ia32_entry.S Mon Sep 24 21:44:23 2001
@@ -2,7 +2,7 @@
#include <asm/offsets.h>
#include <asm/signal.h>

-#include "../kernel/entry.h"
+#include "../kernel/minstate.h"

/*
* execve() is special because in case of success, we need to
@@ -14,13 +14,13 @@
alloc loc1=ar.pfs,3,2,4,0
mov loc0=rp
.body
- mov out0=in0 // filename
+ zxt4 out0=in0 // filename
;; // stop bit between alloc and call
- mov out1=in1 // argv
- mov out2=in2 // envp
+ zxt4 out1=in1 // argv
+ zxt4 out2=in2 // envp
add out3\x16,sp // regs
br.call.sptk.few rp=sys32_execve
-1: cmp4.ge p6,p0=r8,r0
+1: cmp.ge p6,p0=r8,r0
mov ar.pfs=loc1 // restore ar.pfs
;;
(p6) mov ar.pfs=r0 // clear ar.pfs in case of success
@@ -29,6 +29,25 @@
br.ret.sptk.few rp
END(ia32_execve)

+ENTRY(ia32_clone)
+ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
+ alloc r16=ar.pfs,2,2,4,0
+ DO_SAVE_SWITCH_STACK
+ mov loc0=rp
+ mov loc1=r16 // save ar.pfs across do_fork
+ .body
+ zxt4 out1=in1 // newsp
+ mov out3=0 // stacksize
+ adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs
+ zxt4 out0=in0 // out0 = clone_flags
+ br.call.sptk.many rp=do_fork
+.ret0: .restore sp
+ adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
+ mov ar.pfs=loc1
+ mov rp=loc0
+ br.ret.sptk.many rp
+END(ia32_clone)
+
//
// Get possibly unaligned sigmask argument into an aligned
// kernel buffer
@@ -38,7 +57,8 @@
// r32 is still the first argument which is the signal mask.
// We copy this 4-byte aligned value to an 8-byte aligned buffer
// in the task structure and then jump to the IA64 code.
-
+ zxt4 r32=r32
+ ;;
EX(.Lfail, ld4 r2=[r32],4) // load low part of sigmask
;;
EX(.Lfail, ld4 r3=[r32]) // load high part of sigmask
@@ -54,6 +74,24 @@
.Lfail: br.ret.sptk.many rp // failed to read sigmask
END(ia32_rt_sigsuspend)

+GLOBAL_ENTRY(ia32_ret_from_clone)
+ PT_REGS_UNWIND_INFO(0)
+ /*
+ * We need to call schedule_tail() to complete the scheduling process.
+ * Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the
+ * address of the previously executing task.
+ */
+ br.call.sptk.many rp=ia64_invoke_schedule_tail
+.ret1: adds r2=IA64_TASK_PTRACE_OFFSET,r13
+ ;;
+ ld8 r2=[r2]
+ ;;
+ mov r8=0
+ tbit.nz p6,p0=r2,PT_TRACESYS_BIT
+(p6) br.cond.spnt .ia32_strace_check_retval
+ ;; // prevent RAW on r8
+END(ia32_ret_from_clone)
+ // fall thrugh
GLOBAL_ENTRY(ia32_ret_from_syscall)
PT_REGS_UNWIND_INFO(0)

@@ -77,15 +115,20 @@
//
GLOBAL_ENTRY(ia32_trace_syscall)
PT_REGS_UNWIND_INFO(0)
+ mov r3=-38
+ adds r2=IA64_PT_REGS_R8_OFFSET+16,sp
+ ;;
+ st8 [r2]=r3 // initialize return code to -ENOSYS
br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args
-.ret0: br.call.sptk.few rp¶ // do the syscall
-.ret1: cmp.lt p6,p0=r8,r0 // syscall failed?
+.ret2: br.call.sptk.few rp¶ // do the syscall
+.ia32_strace_check_retval:
+ cmp.lt p6,p0=r8,r0 // syscall failed?
adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8
;;
st8.spill [r2]=r8 // store return value in slot for r8
br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value
-.ret2: alloc r2=ar.pfs,0,0,0,0 // drop the syscall argument frame
- br.cond.sptk.many ia64_leave_kernel // rp MUST be != ia64_leave_kernel!
+.ret4: alloc r2=ar.pfs,0,0,0,0 // drop the syscall argument frame
+ br.cond.sptk.many ia64_leave_kernel
END(ia32_trace_syscall)

GLOBAL_ENTRY(sys32_vfork)
@@ -110,7 +153,7 @@
mov out3=0
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs
br.call.sptk.few rp=do_fork
-.ret3: mov ar.pfs=loc1
+.ret5: mov ar.pfs=loc1
.restore sp
adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
mov rp=loc0
@@ -137,21 +180,21 @@
data8 sys32_time
data8 sys_mknod
data8 sys_chmod /* 15 */
- data8 sys_lchown
+ data8 sys_lchown /* 16-bit version */
data8 sys32_ni_syscall /* old break syscall holder */
data8 sys32_ni_syscall
data8 sys32_lseek
data8 sys_getpid /* 20 */
data8 sys_mount
data8 sys_oldumount
- data8 sys_setuid
- data8 sys_getuid
+ data8 sys_setuid /* 16-bit version */
+ data8 sys_getuid /* 16-bit version */
data8 sys32_ni_syscall /* sys_stime is not supported on IA64 */ /* 25 */
data8 sys32_ptrace
data8 sys32_alarm
data8 sys32_ni_syscall
- data8 sys_pause
- data8 ia32_utime /* 30 */
+ data8 sys32_pause
+ data8 sys32_utime /* 30 */
data8 sys32_ni_syscall /* old stty syscall holder */
data8 sys32_ni_syscall /* old gtty syscall holder */
data8 sys_access
@@ -167,15 +210,15 @@
data8 sys32_times
data8 sys32_ni_syscall /* old prof syscall holder */
data8 sys_brk /* 45 */
- data8 sys_setgid
- data8 sys_getgid
+ data8 sys_setgid /* 16-bit version */
+ data8 sys_getgid /* 16-bit version */
data8 sys32_signal
- data8 sys_geteuid
- data8 sys_getegid /* 50 */
+ data8 sys_geteuid /* 16-bit version */
+ data8 sys_getegid /* 16-bit version */ /* 50 */
data8 sys_acct
data8 sys_umount /* recycled never used phys( */
data8 sys32_ni_syscall /* old lock syscall holder */
- data8 ia32_ioctl
+ data8 sys32_ioctl
data8 sys32_fcntl /* 55 */
data8 sys32_ni_syscall /* old mpx syscall holder */
data8 sys_setpgid
@@ -191,19 +234,19 @@
data8 sys32_sigaction
data8 sys32_ni_syscall
data8 sys32_ni_syscall
- data8 sys_setreuid /* 70 */
- data8 sys_setregid
+ data8 sys_setreuid /* 16-bit version */ /* 70 */
+ data8 sys_setregid /* 16-bit version */
data8 sys32_ni_syscall
- data8 sys_sigpending
+ data8 sys32_sigpending
data8 sys_sethostname
data8 sys32_setrlimit /* 75 */
- data8 sys32_getrlimit
+ data8 sys32_old_getrlimit
data8 sys32_getrusage
data8 sys32_gettimeofday
data8 sys32_settimeofday
- data8 sys_getgroups /* 80 */
- data8 sys_setgroups
- data8 old_select
+ data8 sys32_getgroups16 /* 80 */
+ data8 sys32_setgroups16
+ data8 sys32_old_select
data8 sys_symlink
data8 sys32_ni_syscall
data8 sys_readlink /* 85 */
@@ -212,17 +255,17 @@
data8 sys_reboot
data8 sys32_readdir
data8 sys32_mmap /* 90 */
- data8 sys_munmap
+ data8 sys32_munmap
data8 sys_truncate
data8 sys_ftruncate
data8 sys_fchmod
- data8 sys_fchown /* 95 */
+ data8 sys_fchown /* 16-bit version */ /* 95 */
data8 sys_getpriority
data8 sys_setpriority
data8 sys32_ni_syscall /* old profil syscall holder */
data8 sys32_statfs
data8 sys32_fstatfs /* 100 */
- data8 sys_ioperm
+ data8 sys32_ioperm
data8 sys32_socketcall
data8 sys_syslog
data8 sys32_setitimer
@@ -231,36 +274,36 @@
data8 sys32_newlstat
data8 sys32_newfstat
data8 sys32_ni_syscall
- data8 sys_iopl /* 110 */
+ data8 sys32_iopl /* 110 */
data8 sys_vhangup
data8 sys32_ni_syscall /* used to be sys_idle */
data8 sys32_ni_syscall
data8 sys32_wait4
data8 sys_swapoff /* 115 */
- data8 sys_sysinfo
+ data8 sys32_sysinfo
data8 sys32_ipc
data8 sys_fsync
data8 sys32_sigreturn
- data8 sys_clone /* 120 */
+ data8 ia32_clone /* 120 */
data8 sys_setdomainname
data8 sys32_newuname
data8 sys32_modify_ldt
- data8 sys_adjtimex
+ data8 sys32_ni_syscall /* adjtimex */
data8 sys32_mprotect /* 125 */
- data8 sys_sigprocmask
- data8 sys_create_module
- data8 sys_init_module
- data8 sys_delete_module
- data8 sys_get_kernel_syms /* 130 */
- data8 sys_quotactl
+ data8 sys32_sigprocmask
+ data8 sys32_ni_syscall /* create_module */
+ data8 sys32_ni_syscall /* init_module */
+ data8 sys32_ni_syscall /* delete_module */
+ data8 sys32_ni_syscall /* get_kernel_syms */ /* 130 */
+ data8 sys32_quotactl
data8 sys_getpgid
data8 sys_fchdir
- data8 sys_bdflush
- data8 sys_sysfs /* 135 */
- data8 sys_personality
+ data8 sys32_ni_syscall /* sys_bdflush */
+ data8 sys_sysfs /* 135 */
+ data8 sys32_personality
data8 sys32_ni_syscall /* for afs_syscall */
- data8 sys_setfsuid
- data8 sys_setfsgid
+ data8 sys_setfsuid /* 16-bit version */
+ data8 sys_setfsgid /* 16-bit version */
data8 sys_llseek /* 140 */
data8 sys32_getdents
data8 sys32_select
@@ -282,68 +325,68 @@
data8 sys_sched_yield
data8 sys_sched_get_priority_max
data8 sys_sched_get_priority_min /* 160 */
- data8 sys_sched_rr_get_interval
+ data8 sys32_sched_rr_get_interval
data8 sys32_nanosleep
data8 sys_mremap
- data8 sys_setresuid
- data8 sys32_getresuid /* 165 */
- data8 sys_vm86
- data8 sys_query_module
+ data8 sys_setresuid /* 16-bit version */
+ data8 sys32_getresuid16 /* 16-bit version */ /* 165 */
+ data8 sys32_ni_syscall /* vm86 */
+ data8 sys32_ni_syscall /* sys_query_module */
data8 sys_poll
- data8 sys_nfsservctl
+ data8 sys32_ni_syscall /* nfsservctl */
data8 sys_setresgid /* 170 */
- data8 sys32_getresgid
+ data8 sys32_getresgid16
data8 sys_prctl
data8 sys32_rt_sigreturn
data8 sys32_rt_sigaction
data8 sys32_rt_sigprocmask /* 175 */
data8 sys_rt_sigpending
- data8 sys_rt_sigtimedwait
- data8 sys_rt_sigqueueinfo
+ data8 sys32_rt_sigtimedwait
+ data8 sys32_rt_sigqueueinfo
data8 ia32_rt_sigsuspend
- data8 sys_pread /* 180 */
- data8 sys_pwrite
- data8 sys_chown
+ data8 sys32_pread /* 180 */
+ data8 sys32_pwrite
+ data8 sys_chown /* 16-bit version */
data8 sys_getcwd
data8 sys_capget
data8 sys_capset /* 185 */
data8 sys32_sigaltstack
- data8 sys_sendfile
+ data8 sys32_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
+ data8 sys32_getrlimit
+ data8 sys32_mmap2
+ data8 sys32_truncate64
+ data8 sys32_ftruncate64
+ data8 sys32_stat64 /* 195 */
+ data8 sys32_lstat64
+ data8 sys32_fstat64
+ data8 sys_lchown
+ data8 sys_getuid
+ data8 sys_getgid /* 200 */
+ data8 sys_geteuid
+ data8 sys_getegid
+ data8 sys_setreuid
+ data8 sys_setregid
+ data8 sys_getgroups /* 205 */
+ data8 sys_setgroups
+ data8 sys_fchown
+ data8 sys_setresuid
+ data8 sys_getresuid
+ data8 sys_setresgid /* 210 */
+ data8 sys_getresgid
+ data8 sys_chown
+ data8 sys_setuid
+ data8 sys_setgid
+ data8 sys_setfsuid /* 215 */
+ data8 sys_setfsgid
+ data8 sys_pivot_root
+ data8 sys_mincore
+ data8 sys_madvise
+ data8 sys_getdents64 /* 220 */
+ data8 sys32_fcntl64
+ data8 sys_ni_syscall /* reserved for TUX */
/*
* 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 linux-2.4.10-lia/arch/ia64/ia32/ia32_ioctl.c
--- linux-davidm/arch/ia64/ia32/ia32_ioctl.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/ia32/ia32_ioctl.c Mon Sep 24 21:44:39 2001
@@ -36,12 +36,13 @@
_ret; \
})

-#define P(i) ((void *)(long)(i))
+#define P(i) ((void *)(unsigned 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)
+asmlinkage long
+sys32_ioctl (unsigned int fd, unsigned int cmd, unsigned int arg)
{
long ret;

@@ -81,7 +82,7 @@
if (copy_to_user(P(arg), &ver32, sizeof(ver32)))
return -EFAULT;
}
- return(ret);
+ return ret;
}

case IOCTL_NR(DRM_IOCTL_GET_UNIQUE):
@@ -202,9 +203,9 @@
case IOCTL_NR(I2OHTML):
break;
default:
- return(sys_ioctl(fd, cmd, (unsigned long)arg));
+ return sys_ioctl(fd, cmd, (unsigned long)arg);

}
printk("%x:unimplemented IA32 ioctl system call\n", cmd);
- return(-EINVAL);
+ return -EINVAL;
}
diff -urN linux-davidm/arch/ia64/ia32/ia32_ldt.c linux-2.4.10-lia/arch/ia64/ia32/ia32_ldt.c
--- linux-davidm/arch/ia64/ia32/ia32_ldt.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/ia32/ia32_ldt.c Mon Sep 24 21:44:52 2001
@@ -16,6 +16,8 @@
#include <asm/uaccess.h>
#include <asm/ia32.h>

+#define P(p) ((void *) (unsigned long) (p))
+
/*
* read_ldt() is not really atomic - this is not a problem since synchronization of reads
* and writes done to the LDT has to be assured by user-space anyway. Writes are atomic,
@@ -101,19 +103,19 @@
}

asmlinkage int
-sys32_modify_ldt (int func, void *ptr, unsigned int bytecount)
+sys32_modify_ldt (int func, unsigned int ptr, unsigned int bytecount)
{
int ret = -ENOSYS;

switch (func) {
case 0:
- ret = read_ldt(ptr, bytecount);
+ ret = read_ldt(P(ptr), bytecount);
break;
case 1:
- ret = write_ldt(ptr, bytecount, 1);
+ ret = write_ldt(P(ptr), bytecount, 1);
break;
case 0x11:
- ret = write_ldt(ptr, bytecount, 0);
+ ret = write_ldt(P(ptr), bytecount, 0);
break;
}
return ret;
diff -urN linux-davidm/arch/ia64/ia32/ia32_signal.c linux-2.4.10-lia/arch/ia64/ia32/ia32_signal.c
--- linux-davidm/arch/ia64/ia32/ia32_signal.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/ia32/ia32_signal.c Mon Sep 24 21:45:00 2001
@@ -1,8 +1,8 @@
/*
* IA32 Architecture-specific signal handling support.
*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999, 2001 Hewlett-Packard Co
+ * David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
* Copyright (C) 2000 VA Linux Co
* Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
@@ -13,6 +13,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/mm.h>
+#include <linux/personality.h>
#include <linux/ptrace.h>
#include <linux/sched.h>
#include <linux/signal.h>
@@ -31,6 +32,8 @@
#define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))

+#define __IA32_NR_sigreturn 119
+#define __IA32_NR_rt_sigreturn 173

struct sigframe_ia32
{
@@ -54,12 +57,51 @@
char retcode[8];
};

-static int
+int
+copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from)
+{
+ unsigned long tmp;
+ int err;
+
+ if (!access_ok(VERIFY_READ, from, sizeof(siginfo_t32)))
+ return -EFAULT;
+
+ err = __get_user(to->si_signo, &from->si_signo);
+ err |= __get_user(to->si_errno, &from->si_errno);
+ err |= __get_user(to->si_code, &from->si_code);
+
+ if (from->si_code < 0)
+ err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
+ else {
+ switch (from->si_code >> 16) {
+ case __SI_CHLD >> 16:
+ err |= __get_user(to->si_utime, &from->si_utime);
+ err |= __get_user(to->si_stime, &from->si_stime);
+ err |= __get_user(to->si_status, &from->si_status);
+ default:
+ err |= __get_user(to->si_pid, &from->si_pid);
+ err |= __get_user(to->si_uid, &from->si_uid);
+ break;
+ case __SI_FAULT >> 16:
+ err |= __get_user(tmp, &from->si_addr);
+ to->si_addr = (void *) tmp;
+ break;
+ case __SI_POLL >> 16:
+ err |= __get_user(to->si_band, &from->si_band);
+ err |= __get_user(to->si_fd, &from->si_fd);
+ break;
+ /* case __SI_RT: This is not generated by the kernel as of now. */
+ }
+ }
+ return err;
+}
+
+int
copy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from)
{
int err;

- if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
+ if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32)))
return -EFAULT;

/* If you change siginfo_t structure, please be sure
@@ -100,80 +142,81 @@

static int
-setup_sigcontext_ia32(struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
- struct pt_regs *regs, unsigned long mask)
+setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
+ struct pt_regs *regs, unsigned long mask)
{
- int err = 0;
- unsigned long flag;
+ int err = 0;
+ unsigned long flag;

- err |= __put_user((regs->r16 >> 32) & 0xffff , (unsigned int *)&sc->fs);
- err |= __put_user((regs->r16 >> 48) & 0xffff , (unsigned int *)&sc->gs);
+ err |= __put_user((regs->r16 >> 32) & 0xffff , (unsigned int *)&sc->fs);
+ err |= __put_user((regs->r16 >> 48) & 0xffff , (unsigned int *)&sc->gs);

- err |= __put_user((regs->r16 >> 56) & 0xffff, (unsigned int *)&sc->es);
- err |= __put_user(regs->r16 & 0xffff, (unsigned int *)&sc->ds);
- err |= __put_user(regs->r15, &sc->edi);
- err |= __put_user(regs->r14, &sc->esi);
- err |= __put_user(regs->r13, &sc->ebp);
- err |= __put_user(regs->r12, &sc->esp);
- err |= __put_user(regs->r11, &sc->ebx);
- err |= __put_user(regs->r10, &sc->edx);
- err |= __put_user(regs->r9, &sc->ecx);
- err |= __put_user(regs->r8, &sc->eax);
+ err |= __put_user((regs->r16 >> 56) & 0xffff, (unsigned int *)&sc->es);
+ err |= __put_user(regs->r16 & 0xffff, (unsigned int *)&sc->ds);
+ err |= __put_user(regs->r15, &sc->edi);
+ err |= __put_user(regs->r14, &sc->esi);
+ err |= __put_user(regs->r13, &sc->ebp);
+ err |= __put_user(regs->r12, &sc->esp);
+ err |= __put_user(regs->r11, &sc->ebx);
+ err |= __put_user(regs->r10, &sc->edx);
+ err |= __put_user(regs->r9, &sc->ecx);
+ err |= __put_user(regs->r8, &sc->eax);
#if 0
- err |= __put_user(current->tss.trap_no, &sc->trapno);
- err |= __put_user(current->tss.error_code, &sc->err);
+ err |= __put_user(current->tss.trap_no, &sc->trapno);
+ err |= __put_user(current->tss.error_code, &sc->err);
#endif
- err |= __put_user(regs->cr_iip, &sc->eip);
- err |= __put_user(regs->r17 & 0xffff, (unsigned int *)&sc->cs);
- /*
- * `eflags' is in an ar register for this context
- */
- asm volatile ("mov %0=ar.eflag ;;" : "=r"(flag));
- err |= __put_user((unsigned int)flag, &sc->eflags);
-
- err |= __put_user(regs->r12, &sc->esp_at_signal);
- err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int *)&sc->ss);
+ err |= __put_user(regs->cr_iip, &sc->eip);
+ err |= __put_user(regs->r17 & 0xffff, (unsigned int *)&sc->cs);
+ /*
+ * `eflags' is in an ar register for this context
+ */
+ asm volatile ("mov %0=ar.eflag ;;" : "=r"(flag));
+ err |= __put_user((unsigned int)flag, &sc->eflags);
+ err |= __put_user(regs->r12, &sc->esp_at_signal);
+ err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int *)&sc->ss);

#if 0
- tmp = save_i387(fpstate);
- if (tmp < 0)
- err = 1;
- else
- err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);
+ tmp = save_i387(fpstate);
+ if (tmp < 0)
+ err = 1;
+ else
+ err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);

- /* non-iBCS2 extensions.. */
+ /* non-iBCS2 extensions.. */
#endif
- err |= __put_user(mask, &sc->oldmask);
+ err |= __put_user(mask, &sc->oldmask);
#if 0
- err |= __put_user(current->tss.cr2, &sc->cr2);
+ err |= __put_user(current->tss.cr2, &sc->cr2);
#endif
-
- return err;
+ return err;
}

static int
-restore_sigcontext_ia32(struct pt_regs *regs, struct sigcontext_ia32 *sc, int *peax)
+restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 *sc, int *peax)
{
unsigned int err = 0;

-#define COPY(ia64x, ia32x) err |= __get_user(regs->ia64x, &sc->ia32x)
+#define COPY(ia64x, ia32x) err |= __get_user(regs->ia64x, &sc->ia32x)

-#define copyseg_gs(tmp) (regs->r16 |= (unsigned long) tmp << 48)
-#define copyseg_fs(tmp) (regs->r16 |= (unsigned long) tmp << 32)
-#define copyseg_cs(tmp) (regs->r17 |= tmp)
-#define copyseg_ss(tmp) (regs->r17 |= (unsigned long) tmp << 16)
-#define copyseg_es(tmp) (regs->r16 |= (unsigned long) tmp << 16)
-#define copyseg_ds(tmp) (regs->r16 |= tmp)
-
-#define COPY_SEG(seg) \
- { unsigned short tmp; \
- err |= __get_user(tmp, &sc->seg); \
- copyseg_##seg(tmp); }
-
-#define COPY_SEG_STRICT(seg) \
- { unsigned short tmp; \
- err |= __get_user(tmp, &sc->seg); \
- copyseg_##seg(tmp|3); }
+#define copyseg_gs(tmp) (regs->r16 |= (unsigned long) tmp << 48)
+#define copyseg_fs(tmp) (regs->r16 |= (unsigned long) tmp << 32)
+#define copyseg_cs(tmp) (regs->r17 |= tmp)
+#define copyseg_ss(tmp) (regs->r17 |= (unsigned long) tmp << 16)
+#define copyseg_es(tmp) (regs->r16 |= (unsigned long) tmp << 16)
+#define copyseg_ds(tmp) (regs->r16 |= tmp)
+
+#define COPY_SEG(seg) \
+ { \
+ unsigned short tmp; \
+ err |= __get_user(tmp, &sc->seg); \
+ copyseg_##seg(tmp); \
+ }
+#define COPY_SEG_STRICT(seg) \
+ { \
+ unsigned short tmp; \
+ err |= __get_user(tmp, &sc->seg); \
+ copyseg_##seg(tmp|3); \
+ }

/* To make COPY_SEGs easier, we zero r16, r17 */
regs->r16 = 0;
@@ -198,9 +241,8 @@
unsigned long flag;

/*
- * IA32 `eflags' is not part of `pt_regs', it's
- * in an ar register which is part of the thread
- * context. Fortunately, we are executing in the
+ * IA32 `eflags' is not part of `pt_regs', it's in an ar register which
+ * is part of the thread context. Fortunately, we are executing in the
* IA32 process's context.
*/
err |= __get_user(tmpflags, &sc->eflags);
@@ -227,7 +269,7 @@
err |= __get_user(*peax, &sc->eax);
return err;

-#if 0
+#if 0
badframe:
return 1;
#endif
@@ -238,158 +280,164 @@
* Determine which stack to use..
*/
static inline void *
-get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
{
- unsigned long esp;
- unsigned int xss;
+ unsigned long esp;

- /* Default to using normal stack */
- esp = regs->r12;
- xss = regs->r16 >> 16;
-
- /* This is the X/Open sanctioned signal stack switching. */
- if (ka->sa.sa_flags & SA_ONSTACK) {
- if (! on_sig_stack(esp))
- esp = current->sas_ss_sp + current->sas_ss_size;
- }
- /* Legacy stack switching not supported */
-
- return (void *)((esp - frame_size) & -8ul);
+ /* Default to using normal stack (truncate off sign-extension of bit 31: */
+ esp = (unsigned int) regs->r12;
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (!on_sig_stack(esp))
+ esp = current->sas_ss_sp + current->sas_ss_size;
+ }
+ /* Legacy stack switching not supported */
+
+ return (void *)((esp - frame_size) & -8ul);
}

static int
-setup_frame_ia32(int sig, struct k_sigaction *ka, sigset_t *set,
- struct pt_regs * regs)
-{
- struct sigframe_ia32 *frame;
- int err = 0;
-
- frame = get_sigframe(ka, regs, sizeof(*frame));
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
-
- err |= __put_user((current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? (int)(current->exec_domain->signal_invmap[sig])
- : sig),
- &frame->sig);
-
- err |= setup_sigcontext_ia32(&frame->sc, &frame->fpstate, regs, set->sig[0]);
-
- if (_IA32_NSIG_WORDS > 1) {
- err |= __copy_to_user(frame->extramask, (char *) &set->sig[1] + 4,
- sizeof(frame->extramask));
- }
+setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
+{
+ struct sigframe_ia32 *frame;
+ int err = 0;

- /* Set up to return from userspace. If provided, use a stub
- already in userspace. */
- err |= __put_user((long)frame->retcode, &frame->pretcode);
- /* This is popl %eax ; movl $,%eax ; int $0x80 */
- err |= __put_user(0xb858, (short *)(frame->retcode+0));
-#define __IA32_NR_sigreturn 119
- err |= __put_user(__IA32_NR_sigreturn & 0xffff, (short *)(frame->retcode+2));
- err |= __put_user(__IA32_NR_sigreturn >> 16, (short *)(frame->retcode+4));
- err |= __put_user(0x80cd, (short *)(frame->retcode+6));
-
- if (err)
- goto give_sigsegv;
-
- /* Set up registers for signal handler */
- regs->r12 = (unsigned long) frame;
- regs->cr_iip = (unsigned long) ka->sa.sa_handler;
-
- set_fs(USER_DS);
- regs->r16 = (__USER_DS << 16) | (__USER_DS); /* ES = DS, GS, FS are zero */
- regs->r17 = (__USER_DS << 16) | __USER_CS;
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ err |= __put_user((current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32
+ ? (int)(current->exec_domain->signal_invmap[sig])
+ : sig),
+ &frame->sig);
+
+ err |= setup_sigcontext_ia32(&frame->sc, &frame->fpstate, regs, set->sig[0]);
+
+ if (_IA32_NSIG_WORDS > 1)
+ err |= __copy_to_user(frame->extramask, (char *) &set->sig + 4,
+ sizeof(frame->extramask));
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ unsigned int restorer = IA32_SA_RESTORER(ka);
+ err |= __put_user(restorer, &frame->pretcode);
+ } else {
+ err |= __put_user((long)frame->retcode, &frame->pretcode);
+ /* This is popl %eax ; movl $,%eax ; int $0x80 */
+ err |= __put_user(0xb858, (short *)(frame->retcode+0));
+ err |= __put_user(__IA32_NR_sigreturn & 0xffff, (short *)(frame->retcode+2));
+ err |= __put_user(__IA32_NR_sigreturn >> 16, (short *)(frame->retcode+4));
+ err |= __put_user(0x80cd, (short *)(frame->retcode+6));
+ }
+
+ if (err)
+ goto give_sigsegv;
+
+ /* Set up registers for signal handler */
+ regs->r12 = (unsigned long) frame;
+ regs->cr_iip = IA32_SA_HANDLER(ka);
+
+ set_fs(USER_DS);
+ regs->r16 = (__USER_DS << 16) | (__USER_DS); /* ES = DS, GS, FS are zero */
+ regs->r17 = (__USER_DS << 16) | __USER_CS;

#if 0
- regs->eflags &= ~TF_MASK;
+ regs->eflags &= ~TF_MASK;
#endif

#if 0
- printk("SIG deliver (%s:%d): sig=%d sp=%p pc=%lx ra=%x\n",
+ printk("SIG deliver (%s:%d): sig=%d sp=%p pc=%lx ra=%x\n",
current->comm, current->pid, sig, (void *) frame, regs->cr_iip, frame->pretcode);
#endif

- return 1;
+ return 1;

-give_sigsegv:
- if (sig = SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
- return 0;
+ give_sigsegv:
+ if (sig = SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+ return 0;
}

static int
-setup_rt_frame_ia32(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs * regs)
+setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs * regs)
{
- struct rt_sigframe_ia32 *frame;
- int err = 0;
+ struct rt_sigframe_ia32 *frame;
+ int err = 0;

- frame = get_sigframe(ka, regs, sizeof(*frame));
+ frame = get_sigframe(ka, regs, sizeof(*frame));

- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
-
- err |= __put_user((current->exec_domain
- && current->exec_domain->signal_invmap
- && sig < 32
- ? current->exec_domain->signal_invmap[sig]
- : sig),
- &frame->sig);
- err |= __put_user((long)&frame->info, &frame->pinfo);
- err |= __put_user((long)&frame->uc, &frame->puc);
- err |= copy_siginfo_to_user32(&frame->info, info);
-
- /* Create the ucontext. */
- err |= __put_user(0, &frame->uc.uc_flags);
- err |= __put_user(0, &frame->uc.uc_link);
- err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(regs->r12),
- &frame->uc.uc_stack.ss_flags);
- err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
- err |= setup_sigcontext_ia32(&frame->uc.uc_mcontext, &frame->fpstate,
- regs, set->sig[0]);
- err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-
- err |= __put_user((long)frame->retcode, &frame->pretcode);
- /* This is movl $,%eax ; int $0x80 */
- err |= __put_user(0xb8, (char *)(frame->retcode+0));
-#define __IA32_NR_rt_sigreturn 173
- err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
- err |= __put_user(0x80cd, (short *)(frame->retcode+5));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ err |= __put_user((current->exec_domain
+ && current->exec_domain->signal_invmap
+ && sig < 32
+ ? current->exec_domain->signal_invmap[sig]
+ : sig),
+ &frame->sig);
+ err |= __put_user((long)&frame->info, &frame->pinfo);
+ err |= __put_user((long)&frame->uc, &frame->puc);
+ err |= copy_siginfo_to_user32(&frame->info, info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->r12), &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext_ia32(&frame->uc.uc_mcontext, &frame->fpstate, regs, set->sig[0]);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ if (err)
+ goto give_sigsegv;
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ unsigned int restorer = IA32_SA_RESTORER(ka);
+ err |= __put_user(restorer, &frame->pretcode);
+ } else {
+ err |= __put_user((long)frame->retcode, &frame->pretcode);
+ /* This is movl $,%eax ; int $0x80 */
+ err |= __put_user(0xb8, (char *)(frame->retcode+0));
+ err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
+ err |= __put_user(0x80cd, (short *)(frame->retcode+5));
+ }

- if (err)
- goto give_sigsegv;
+ if (err)
+ goto give_sigsegv;

- /* Set up registers for signal handler */
- regs->r12 = (unsigned long) frame;
- regs->cr_iip = (unsigned long) ka->sa.sa_handler;
+ /* Set up registers for signal handler */
+ regs->r12 = (unsigned long) frame;
+ regs->cr_iip = IA32_SA_HANDLER(ka);

- set_fs(USER_DS);
+ set_fs(USER_DS);

- regs->r16 = (__USER_DS << 16) | (__USER_DS); /* ES = DS, GS, FS are zero */
- regs->r17 = (__USER_DS << 16) | __USER_CS;
+ regs->r16 = (__USER_DS << 16) | (__USER_DS); /* ES = DS, GS, FS are zero */
+ regs->r17 = (__USER_DS << 16) | __USER_CS;

#if 0
- regs->eflags &= ~TF_MASK;
+ regs->eflags &= ~TF_MASK;
#endif

#if 0
- printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n",
+ printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%x\n",
current->comm, current->pid, (void *) frame, regs->cr_iip, frame->pretcode);
#endif

- return 1;
+ return 1;

give_sigsegv:
- if (sig = SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
- return 0;
+ if (sig = SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+ return 0;
}

int
@@ -398,93 +446,79 @@
{
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
- return(setup_rt_frame_ia32(sig, ka, info, set, regs));
+ return setup_rt_frame_ia32(sig, ka, info, set, regs);
else
- return(setup_frame_ia32(sig, ka, set, regs));
+ return setup_frame_ia32(sig, ka, set, regs);
}

-asmlinkage int
-sys32_sigreturn(
-int arg0,
-int arg1,
-int arg2,
-int arg3,
-int arg4,
-int arg5,
-int arg6,
-int arg7,
-unsigned long stack)
-{
- struct pt_regs *regs = (struct pt_regs *) &stack;
- struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(regs->r12- 8);
- sigset_t set;
- int eax;
-
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
-
- if (__get_user(set.sig[0], &frame->sc.oldmask)
- || (_IA32_NSIG_WORDS > 1 && __copy_from_user((char *) &set.sig + 4, &frame->extramask,
- sizeof(frame->extramask))))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
- current->blocked = (sigset_t) set;
- recalc_sigpending(current);
- spin_unlock_irq(&current->sigmask_lock);
-
- if (restore_sigcontext_ia32(regs, &frame->sc, &eax))
- goto badframe;
- return eax;
-
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
-
-asmlinkage int
-sys32_rt_sigreturn(
-int arg0,
-int arg1,
-int arg2,
-int arg3,
-int arg4,
-int arg5,
-int arg6,
-int arg7,
-unsigned long stack)
-{
- struct pt_regs *regs = (struct pt_regs *) &stack;
- struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(regs->r12 - 4);
- sigset_t set;
- stack_t st;
- int eax;
-
- if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
- if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
- current->blocked = set;
- recalc_sigpending(current);
- spin_unlock_irq(&current->sigmask_lock);
-
- if (restore_sigcontext_ia32(regs, &frame->uc.uc_mcontext, &eax))
- goto badframe;
-
- if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
- goto badframe;
- /* It is more difficult to avoid calling this function than to
- call it and ignore errors. */
- do_sigaltstack(&st, NULL, regs->r12);
-
- return eax;
+asmlinkage long
+sys32_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7,
+ unsigned long stack)
+{
+ struct pt_regs *regs = (struct pt_regs *) &stack;
+ unsigned long esp = (unsigned int) regs->r12;
+ struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(esp - 8);
+ sigset_t set;
+ int eax;
+
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (__get_user(set.sig[0], &frame->sc.oldmask)
+ || (_IA32_NSIG_WORDS > 1 && __copy_from_user((char *) &set.sig + 4, &frame->extramask,
+ sizeof(frame->extramask))))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = (sigset_t) set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ if (restore_sigcontext_ia32(regs, &frame->sc, &eax))
+ goto badframe;
+ return eax;
+
+ badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}

-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
+asmlinkage long
+sys32_rt_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7,
+ unsigned long stack)
+{
+ struct pt_regs *regs = (struct pt_regs *) &stack;
+ unsigned long esp = (unsigned int) regs->r12;
+ struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(esp - 4);
+ sigset_t set;
+ stack_t st;
+ int eax;
+
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ if (restore_sigcontext_ia32(regs, &frame->uc.uc_mcontext, &eax))
+ goto badframe;
+
+ if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+ goto badframe;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, esp);
+
+ return eax;
+
+ badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}

diff -urN linux-davidm/arch/ia64/ia32/ia32_support.c linux-2.4.10-lia/arch/ia64/ia32/ia32_support.c
--- linux-davidm/arch/ia64/ia32/ia32_support.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/ia32/ia32_support.c Mon Sep 24 21:45:11 2001
@@ -4,15 +4,17 @@
* Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
* Copyright (C) 2000 Asit K. Mallick <asit.k.mallick@intel.com>
* Copyright (C) 2001 Hewlett-Packard Co
- * Copyright (C) 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*
* 06/16/00 A. Mallick added csd/ssd/tssd for ia32 thread context
* 02/19/01 D. Mosberger dropped tssd; it's not needed
+ * 09/14/01 D. Mosberger fixed memory management for gdt/tss page
*/

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
+#include <linux/personality.h>
#include <linux/sched.h>

#include <asm/page.h>
@@ -21,10 +23,12 @@
#include <asm/processor.h>
#include <asm/ia32.h>

-extern unsigned long *ia32_gdt_table, *ia32_tss;
-
extern void die_if_kernel (char *str, struct pt_regs *regs, long err);

+struct exec_domain ia32_exec_domain;
+struct page *ia32_shared_page[(2*IA32_PAGE_SIZE + PAGE_SIZE - 1)/PAGE_SIZE];
+unsigned long *ia32_gdt;
+
void
ia32_save_state (struct task_struct *t)
{
@@ -85,36 +89,34 @@
void
ia32_gdt_init (void)
{
- unsigned long gdt_and_tss_page, ldt_size;
+ unsigned long *tss;
+ unsigned long ldt_size;
int nr;

- /* allocate two IA-32 pages of memory: */
- gdt_and_tss_page = __get_free_pages(GFP_KERNEL,
- (IA32_PAGE_SHIFT < PAGE_SHIFT)
- ? 0 : (IA32_PAGE_SHIFT + 1) - PAGE_SHIFT);
- ia32_gdt_table = (unsigned long *) gdt_and_tss_page;
- ia32_tss = (unsigned long *) (gdt_and_tss_page + IA32_PAGE_SIZE);
-
- /* Zero the gdt and tss */
- memset((void *) gdt_and_tss_page, 0, 2*IA32_PAGE_SIZE);
+ ia32_shared_page[0] = alloc_page(GFP_KERNEL);
+ ia32_gdt = page_address(ia32_shared_page[0]);
+ tss = ia32_gdt + IA32_PAGE_SIZE/sizeof(ia32_gdt[0]);
+
+ if (IA32_PAGE_SIZE = PAGE_SIZE) {
+ ia32_shared_page[1] = alloc_page(GFP_KERNEL);
+ tss = page_address(ia32_shared_page[1]);
+ }

/* CS descriptor in IA-32 (scrambled) format */
- ia32_gdt_table[__USER_CS >> 3] - IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET - 1) >> IA32_PAGE_SHIFT,
- 0xb, 1, 3, 1, 1, 1, 1);
+ ia32_gdt[__USER_CS >> 3] = IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
+ 0xb, 1, 3, 1, 1, 1, 1);

/* DS descriptor in IA-32 (scrambled) format */
- ia32_gdt_table[__USER_DS >> 3] - IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET - 1) >> IA32_PAGE_SHIFT,
- 0x3, 1, 3, 1, 1, 1, 1);
+ ia32_gdt[__USER_DS >> 3] = IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
+ 0x3, 1, 3, 1, 1, 1, 1);

/* We never change the TSS and LDT descriptors, so we can share them across all CPUs. */
ldt_size = PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
for (nr = 0; nr < NR_CPUS; ++nr) {
- ia32_gdt_table[_TSS(nr)] = IA32_SEG_DESCRIPTOR(IA32_TSS_OFFSET, 235,
- 0xb, 0, 3, 1, 1, 1, 0);
- ia32_gdt_table[_LDT(nr)] = IA32_SEG_DESCRIPTOR(IA32_LDT_OFFSET, ldt_size - 1,
- 0x2, 0, 3, 1, 1, 1, 0);
+ ia32_gdt[_TSS(nr)] = IA32_SEG_DESCRIPTOR(IA32_TSS_OFFSET, 235,
+ 0xb, 0, 3, 1, 1, 1, 0);
+ ia32_gdt[_LDT(nr)] = IA32_SEG_DESCRIPTOR(IA32_LDT_OFFSET, ldt_size - 1,
+ 0x2, 0, 3, 1, 1, 1, 0);
}
}

@@ -133,3 +135,18 @@
siginfo.si_code = TRAP_BRKPT;
force_sig_info(SIGTRAP, &siginfo, current);
}
+
+static int __init
+ia32_init (void)
+{
+ ia32_exec_domain.name = "Linux/x86";
+ ia32_exec_domain.handler = NULL;
+ ia32_exec_domain.pers_low = PER_LINUX32;
+ ia32_exec_domain.pers_high = PER_LINUX32;
+ ia32_exec_domain.signal_map = default_exec_domain.signal_map;
+ ia32_exec_domain.signal_invmap = default_exec_domain.signal_invmap;
+ register_exec_domain(&ia32_exec_domain);
+ return 0;
+}
+
+__initcall(ia32_init);
diff -urN linux-davidm/arch/ia64/ia32/sys_ia32.c linux-2.4.10-lia/arch/ia64/ia32/sys_ia32.c
--- linux-davidm/arch/ia64/ia32/sys_ia32.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/ia32/sys_ia32.c Mon Sep 24 21:45:20 2001
@@ -1,14 +1,13 @@
/*
- * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on
- * sys_sparc32
+ * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Derived from sys_sparc32.c.
*
* Copyright (C) 2000 VA Linux Co
* Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
* Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com>
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 2000 Hewlett-Packard Co.
- * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2000-2001 Hewlett-Packard Co
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*
* These routines maintain argument size conversion between 32bit and 64bit
* environment.
@@ -53,7 +52,6 @@
#include <asm/types.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
-#include <asm/ipc.h>

#include <net/scm.h>
#include <net/sock.h>
@@ -66,18 +64,23 @@

extern asmlinkage long sys_execve (char *, char **, char **, struct pt_regs *);
extern asmlinkage long sys_mprotect (unsigned long, size_t, unsigned long);
+extern asmlinkage long sys_munmap (unsigned long, size_t);
+
+/* forward declaration: */
+asmlinkage long sys32_mprotect (unsigned int, unsigned int, int);

static int
nargs (unsigned int arg, char **ap)
{
- int n, err, addr;
+ unsigned int addr;
+ int n, err;

if (!arg)
return 0;

n = 0;
do {
- err = get_user(addr, (int *)A(arg));
+ err = get_user(addr, (unsigned int *)A(arg));
if (err)
return err;
if (ap)
@@ -144,30 +147,33 @@
}

static inline int
-putstat(struct stat32 *ubuf, struct stat *kbuf)
+putstat (struct stat32 *ubuf, struct stat *kbuf)
{
int err;

- err = put_user (kbuf->st_dev, &ubuf->st_dev);
- err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
- err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
- err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink);
- err |= __put_user (kbuf->st_uid, &ubuf->st_uid);
- err |= __put_user (kbuf->st_gid, &ubuf->st_gid);
- err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev);
- err |= __put_user (kbuf->st_size, &ubuf->st_size);
- err |= __put_user (kbuf->st_atime, &ubuf->st_atime);
- err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime);
- err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime);
- err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize);
- err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks);
+ if (clear_user(ubuf, sizeof(*ubuf)))
+ return 1;
+
+ err = __put_user(kbuf->st_dev, &ubuf->st_dev);
+ err |= __put_user(kbuf->st_ino, &ubuf->st_ino);
+ err |= __put_user(kbuf->st_mode, &ubuf->st_mode);
+ err |= __put_user(kbuf->st_nlink, &ubuf->st_nlink);
+ err |= __put_user(kbuf->st_uid, &ubuf->st_uid);
+ err |= __put_user(kbuf->st_gid, &ubuf->st_gid);
+ err |= __put_user(kbuf->st_rdev, &ubuf->st_rdev);
+ err |= __put_user(kbuf->st_size, &ubuf->st_size);
+ err |= __put_user(kbuf->st_atime, &ubuf->st_atime);
+ err |= __put_user(kbuf->st_mtime, &ubuf->st_mtime);
+ err |= __put_user(kbuf->st_ctime, &ubuf->st_ctime);
+ err |= __put_user(kbuf->st_blksize, &ubuf->st_blksize);
+ err |= __put_user(kbuf->st_blocks, &ubuf->st_blocks);
return err;
}

-extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
+extern asmlinkage long sys_newstat (char * filename, struct stat * statbuf);

asmlinkage long
-sys32_newstat(char * filename, struct stat32 *statbuf)
+sys32_newstat (char *filename, struct stat32 *statbuf)
{
int ret;
struct stat s;
@@ -175,8 +181,8 @@

set_fs(KERNEL_DS);
ret = sys_newstat(filename, &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s))
+ set_fs(old_fs);
+ if (putstat(statbuf, &s))
return -EFAULT;
return ret;
}
@@ -184,16 +190,16 @@
extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);

asmlinkage long
-sys32_newlstat(char * filename, struct stat32 *statbuf)
+sys32_newlstat (char *filename, struct stat32 *statbuf)
{
- int ret;
- struct stat s;
mm_segment_t old_fs = get_fs();
+ struct stat s;
+ int ret;

- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
ret = sys_newlstat(filename, &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s))
+ set_fs(old_fs);
+ if (putstat(statbuf, &s))
return -EFAULT;
return ret;
}
@@ -201,112 +207,171 @@
extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);

asmlinkage long
-sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
+sys32_newfstat (unsigned int fd, struct stat32 *statbuf)
{
- int ret;
- struct stat s;
mm_segment_t old_fs = get_fs();
+ struct stat s;
+ int ret;

- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
ret = sys_newfstat(fd, &s);
- set_fs (old_fs);
- if (putstat (statbuf, &s))
+ set_fs(old_fs);
+ if (putstat(statbuf, &s))
return -EFAULT;
return ret;
}

#define OFFSET4K(a) ((a) & 0xfff)

-unsigned long
-do_mmap_fake(struct file *file, unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags, loff_t off)
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
+
+/*
+ * Determine whether address ADDR is readable. This must be done *without* actually
+ * touching memory because otherwise the stack auto-expansion may *make* the address
+ * readable, which is not at all what we want. --davidm 01/09/20
+ */
+static inline long
+is_readable (unsigned long addr)
+{
+ struct vm_area_struct *vma = find_vma(current->mm, addr);
+ return vma && (vma->vm_start <= addr) && (vma->vm_flags & VM_READ);
+}
+
+static unsigned long
+do_mmap_fake (struct file *file, unsigned long addr, unsigned long len, int prot, int flags,
+ loff_t off)
{
+ unsigned long faddr = (addr & PAGE_MASK), end, front_len, back_len, retval;
+ void *front = 0, *back = 0;
struct inode *inode;
- void *front, *back;
- unsigned long baddr;
- int r;
- char c;

- if (OFFSET4K(addr) || OFFSET4K(off))
- return -EINVAL;
+ /*
+ * Allow any kind of access: this lets us avoid having to figure out what the
+ * protection of the partial front and back pages is...
+ */
prot |= PROT_WRITE;
- front = NULL;
- back = NULL;
- if ((baddr = (addr & PAGE_MASK)) != addr && get_user(c, (char *)baddr) = 0) {
- front = kmalloc(addr - baddr, GFP_KERNEL);
- if (!front)
- return -ENOMEM;
- __copy_user(front, (void *)baddr, addr - baddr);
+
+ if (OFFSET4K(addr))
+ return -EINVAL;
+
+ end = addr + len;
+ front_len = addr - faddr;
+ back_len = (end & ~PAGE_MASK);
+
+ if (front_len && is_readable(faddr)) {
+ front = kmalloc(front_len, GFP_KERNEL);
+ if (!front) {
+ addr = -ENOMEM;
+ goto fail;
+ }
+ copy_from_user(front, (void *)faddr, front_len);
}
- if (addr && ((addr + len) & ~PAGE_MASK) && get_user(c, (char *)(addr + len)) = 0) {
- back = kmalloc(PAGE_SIZE - ((addr + len) & ~PAGE_MASK), GFP_KERNEL);
+
+ if (addr && back_len && is_readable(end)) {
+ back = kmalloc(PAGE_SIZE - back_len, GFP_KERNEL);
if (!back) {
- if (front)
- kfree(front);
- return -ENOMEM;
+ addr = -ENOMEM;
+ goto fail;
}
- __copy_user(back, (char *)addr + len, PAGE_SIZE - ((addr + len) & ~PAGE_MASK));
+ copy_from_user(back, (char *)end, PAGE_SIZE - back_len);
}
+
down_write(&current->mm->mmap_sem);
- r = do_mmap(0, baddr, len + (addr - baddr), prot, flags | MAP_ANONYMOUS, 0);
+ {
+ retval = do_mmap(0, faddr, len + front_len, prot, flags | MAP_ANONYMOUS, 0);
+ }
up_write(&current->mm->mmap_sem);
- if (r < 0)
- return(r);
- if (addr = 0)
- addr = r;
+
+ if (IS_ERR((void *) retval)) {
+ addr = retval;
+ goto fail;
+ }
+
+ if (!addr)
+ addr = retval;
+
+ end = addr + len;
+
if (back) {
- __copy_user((char *)addr + len, back, PAGE_SIZE - ((addr + len) & ~PAGE_MASK));
+ if (copy_to_user((char *) end, back, PAGE_SIZE - back_len)) {
+ addr = -EINVAL;
+ goto fail;
+ }
kfree(back);
}
if (front) {
- __copy_user((void *)baddr, front, addr - baddr);
+ if (copy_to_user((void *) faddr, front, front_len)) {
+ addr = -EINVAL;
+ goto fail;
+ }
kfree(front);
}
- if (flags & MAP_ANONYMOUS) {
- clear_user((char *)addr, len);
- return(addr);
+
+ if (!(flags & MAP_ANONYMOUS)) {
+ inode = file->f_dentry->d_inode;
+ if (!inode->i_fop
+ || !file->f_op->read
+ || (*file->f_op->read)(file, (char *)addr, len, &off) < 0)
+ {
+ sys_munmap(addr, len + front_len);
+ return -EINVAL;
+ }
}
- if (!file)
- return -EINVAL;
- inode = file->f_dentry->d_inode;
- if (!inode->i_fop)
- return -EINVAL;
- if (!file->f_op->read)
- return -EINVAL;
- r = file->f_op->read(file, (char *)addr, len, &off);
- return (r < 0) ? -EINVAL : addr;
+ return addr;
+
+ fail: if (front)
+ kfree(front);
+ if (back)
+ kfree(back);
+ return addr;
}

-long
-ia32_do_mmap (struct file *file, unsigned int addr, unsigned int len, unsigned int prot,
- unsigned int flags, unsigned int fd, unsigned int offset)
+#endif /* PAGE_SHIFT > IA32_PAGE_SHIFT */
+
+unsigned long
+ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot, int flags,
+ loff_t offset)
{
- long error = -EFAULT;
- unsigned int poff;
+ if (file && (!file->f_op || !file->f_op->mmap))
+ return -ENODEV;

- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- prot |= PROT_EXEC;
+ len = IA32_PAGE_ALIGN(len);
+ if (len = 0)
+ return addr;
+
+ if (len > IA32_PAGE_OFFSET || addr > IA32_PAGE_OFFSET - len)
+ return -EINVAL;
+
+ if (OFFSET4K(offset))
+ return -EINVAL;
+
+ if (prot & (PROT_READ | PROT_WRITE))
+ prot |= PROT_EXEC; /* x86 has no "execute" permission bit... */

+#if PAGE_SHIFT > IA32_PAGE_SHIFT
if ((flags & MAP_FIXED) && ((addr & ~PAGE_MASK) || (offset & ~PAGE_MASK)))
- error = do_mmap_fake(file, addr, len, prot, flags, (loff_t)offset);
- else {
- poff = offset & PAGE_MASK;
- len += offset - poff;
+ addr = do_mmap_fake(file, addr, len, prot, flags, offset);
+ else
+#endif
+ {
+ loff_t pgoff = offset & PAGE_MASK;
+ len += offset - pgoff;

down_write(&current->mm->mmap_sem);
- error = do_mmap_pgoff(file, addr, len, prot, flags, poff >> PAGE_SHIFT);
+ {
+ addr = do_mmap(file, addr, len, prot, flags, pgoff);
+ }
up_write(&current->mm->mmap_sem);

- if (!IS_ERR((void *) error))
- error += offset - poff;
+ if (!IS_ERR((void *) addr))
+ addr += offset - pgoff;
}
- return error;
+ return addr;
}

/*
- * Linux/i386 didn't use to be able to handle more than
- * 4 system call parameters, so these system calls used a memory
- * block for parameter passing..
+ * Linux/i386 didn't use to be able to handle more than 4 system call parameters, so these
+ * system calls used a memory block for parameter passing..
*/

struct mmap_arg_struct {
@@ -319,56 +384,147 @@
};

asmlinkage long
-sys32_mmap(struct mmap_arg_struct *arg)
+sys32_mmap (struct mmap_arg_struct *arg)
{
struct mmap_arg_struct a;
struct file *file = NULL;
- long retval;
+ unsigned long addr;
+ int flags;

if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT;

- if (PAGE_ALIGN(a.len) = 0)
- return a.addr;
+ if (OFFSET4K(a.offset))
+ return -EINVAL;
+
+ flags = a.flags;

- if (!(a.flags & MAP_ANONYMOUS)) {
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
file = fget(a.fd);
if (!file)
return -EBADF;
}
-#ifdef CONFIG_IA64_PAGE_SIZE_4KB
- if ((a.offset & ~PAGE_MASK) != 0)
- return -EINVAL;

- down_write(&current->mm->mmap_sem);
- retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset >> PAGE_SHIFT);
- up_write(&current->mm->mmap_sem);
-#else
- retval = ia32_do_mmap(file, a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
-#endif
+ addr = ia32_do_mmap(file, a.addr, a.len, a.prot, flags, a.offset);
+
+ if (file)
+ fput(file);
+ return addr;
+}
+
+asmlinkage long
+sys32_mmap2 (unsigned int addr, unsigned int len, unsigned int prot, unsigned int flags,
+ unsigned int fd, unsigned int pgoff)
+{
+ struct file *file = NULL;
+ unsigned long retval;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ return -EBADF;
+ }
+
+ retval = ia32_do_mmap(file, addr, len, prot, flags,
+ (unsigned long) pgoff << IA32_PAGE_SHIFT);
+
if (file)
fput(file);
return retval;
}

asmlinkage long
-sys32_mprotect(unsigned long start, size_t len, unsigned long prot)
+sys32_munmap (unsigned int start, unsigned int len)
+{
+ unsigned int end = start + len;
+
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
+ if (start > end)
+ return -EINVAL;
+
+ start = PAGE_ALIGN(start);
+ end = end & PAGE_MASK;
+
+ if (start >= end)
+ return 0;
+#endif
+ return sys_munmap(start, end - start);
+}
+
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
+
+/*
+ * When mprotect()ing a partial page, we set the permission to the union of the old
+ * settings and the new settings. In other words, it's only possible to make access to a
+ * partial page less restrictive.
+ */
+static long
+mprotect_partial_page (unsigned long address, int new_prot)
+{
+ int old_prot;
+
+ if (new_prot = PROT_NONE)
+ return 0; /* optimize case where nothing changes... */
+
+ /*
+ * We cannot easily determine the existing protection on this page because we have
+ * to relinquish the mmap-semaphore before calling sys_mprotect(), which would
+ * create a window during which another task could change the protection settings
+ * underneath us. To avoid this, we conservatively assume that the page is
+ * RWXable.
+ */
+ old_prot = PROT_READ | PROT_WRITE | PROT_EXEC;
+ return sys_mprotect(address, PAGE_SIZE, new_prot | old_prot);
+}
+
+#endif /* PAGE_SHIFT > IA32_PAGE_SHIFT */
+
+asmlinkage long
+sys32_mprotect (unsigned int start, unsigned int len, int prot)
{
+ unsigned long end = start + len;
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
+ long retval;
+#endif

-#ifdef CONFIG_IA64_PAGE_SIZE_4KB
- return(sys_mprotect(start, len, prot));
-#else // CONFIG_IA64_PAGE_SIZE_4KB
- if (prot = 0)
- return(0);
- len += start & ~PAGE_MASK;
- if ((start & ~PAGE_MASK) && (prot & PROT_WRITE))
+ if (prot & (PROT_READ | PROT_WRITE))
+ /* on x86, PROT_WRITE implies PROT_READ and PROT_READ implies PROT_EXEC... */
prot |= PROT_EXEC;
- return(sys_mprotect(start & PAGE_MASK, len & PAGE_MASK, prot));
-#endif // CONFIG_IA64_PAGE_SIZE_4KB
+
+#if PAGE_SHIFT > IA32_PAGE_SHIFT
+ if (OFFSET4K(start))
+ return -EINVAL;
+
+ end = IA32_PAGE_ALIGN(end);
+ if (end < start)
+ return -EINVAL;
+
+ if (start & ~PAGE_MASK) {
+ /* start address is 4KB aligned but not page aligned. */
+ retval = mprotect_partial_page(start & PAGE_MASK, prot);
+ if (retval < 0)
+ return retval;
+
+ start = PAGE_ALIGN(start);
+ if (start >= end)
+ return 0;
+ }
+
+ if (end & ~PAGE_MASK) {
+ /* end address is 4KB aligned but not page aligned. */
+ retval = mprotect_partial_page(end & PAGE_MASK, prot);
+ if (retval < 0)
+ return retval;
+ end &= PAGE_MASK;
+ }
+#endif
+ return sys_mprotect(start, end - start, prot);
}

asmlinkage long
-sys32_pipe(int *fd)
+sys32_pipe (int *fd)
{
int retval;
int fds[2];
@@ -382,119 +538,154 @@
return retval;
}

+static inline void
+sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int restorer)
+{
+ if (handler + 1 <= 2)
+ /* SIG_DFL, SIG_IGN, or SIG_ERR: must sign-extend to 64-bits */
+ sa->sa.sa_handler = (__sighandler_t) A((int) handler);
+ else
+ sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);
+}
+
asmlinkage long
sys32_signal (int sig, unsigned int handler)
{
struct k_sigaction new_sa, old_sa;
int ret;

- new_sa.sa.sa_handler = (__sighandler_t) A(handler);
+ sigact_set_handler(&new_sa, handler, 0);
new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;

ret = do_sigaction(sig, &new_sa, &old_sa);

- return ret ? ret : (unsigned long)old_sa.sa.sa_handler;
+ return ret ? ret : IA32_SA_HANDLER(&old_sa);
}

asmlinkage long
-sys32_rt_sigaction(int sig, struct sigaction32 *act,
- struct sigaction32 *oact, unsigned int sigsetsize)
+sys32_rt_sigaction (int sig, struct sigaction32 *act,
+ struct sigaction32 *oact, unsigned int sigsetsize)
{
struct k_sigaction new_ka, old_ka;
+ unsigned int handler, restorer;
int ret;
- sigset32_t set32;

/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset32_t))
return -EINVAL;

if (act) {
- ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
- ret |= __copy_from_user(&set32, &act->sa_mask,
- sizeof(sigset32_t));
- switch (_NSIG_WORDS) {
- case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
- | (((long)set32.sig[7]) << 32);
- case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
- | (((long)set32.sig[5]) << 32);
- case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
- | (((long)set32.sig[3]) << 32);
- case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
- | (((long)set32.sig[1]) << 32);
- }
- ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
-
+ ret = get_user(handler, &act->sa_handler);
+ ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ ret |= get_user(restorer, &act->sa_restorer);
+ ret |= copy_from_user(&new_ka.sa.sa_mask, &act->sa_mask, sizeof(sigset32_t));
if (ret)
return -EFAULT;
+
+ sigact_set_handler(&new_ka, handler, restorer);
}

ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);

if (!ret && oact) {
- switch (_NSIG_WORDS) {
- case 4:
- set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
- set32.sig[6] = old_ka.sa.sa_mask.sig[3];
- case 3:
- set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
- set32.sig[4] = old_ka.sa.sa_mask.sig[2];
- case 2:
- set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
- set32.sig[2] = old_ka.sa.sa_mask.sig[1];
- case 1:
- set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
- set32.sig[0] = old_ka.sa.sa_mask.sig[0];
- }
- ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
- ret |= __copy_to_user(&oact->sa_mask, &set32,
- sizeof(sigset32_t));
- ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler);
+ ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer);
+ ret |= copy_to_user(&oact->sa_mask, &old_ka.sa.sa_mask, sizeof(sigset32_t));
}
-
return ret;
}

-extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,
- size_t sigsetsize);
+extern asmlinkage long sys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset,
+ size_t sigsetsize);

asmlinkage long
-sys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset,
- unsigned int sigsetsize)
+sys32_rt_sigprocmask (int how, sigset32_t *set, sigset32_t *oset, unsigned int sigsetsize)
{
- sigset_t s;
- sigset32_t s32;
- int ret;
mm_segment_t old_fs = get_fs();
+ sigset_t s;
+ long ret;
+
+ if (sigsetsize > sizeof(s))
+ return -EINVAL;

if (set) {
- if (copy_from_user (&s32, set, sizeof(sigset32_t)))
+ memset(&s, 0, sizeof(s));
+ if (copy_from_user(&s.sig, set, sigsetsize))
return -EFAULT;
- switch (_NSIG_WORDS) {
- case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
- case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
- case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
- case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
- }
}
- set_fs (KERNEL_DS);
- ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL,
- sigsetsize);
- set_fs (old_fs);
- if (ret) return ret;
+ set_fs(KERNEL_DS);
+ ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sizeof(s));
+ set_fs(old_fs);
+ if (ret)
+ return ret;
if (oset) {
- switch (_NSIG_WORDS) {
- case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
- case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
- case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
- case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
- }
- if (copy_to_user (oset, &s32, sizeof(sigset32_t)))
+ if (copy_to_user(oset, &s.sig, sigsetsize))
return -EFAULT;
}
return 0;
}

+asmlinkage long
+sys32_sigprocmask (int how, unsigned int *set, unsigned int *oset)
+{
+ return sys32_rt_sigprocmask(how, (sigset32_t *) set, (sigset32_t *) oset, sizeof(*set));
+}
+
+struct timespec32 {
+ int tv_sec;
+ int tv_nsec;
+};
+
+asmlinkage long
+sys32_rt_sigtimedwait (sigset32_t *uthese, siginfo_t32 *uinfo, struct timespec32 *uts,
+ unsigned int sigsetsize)
+{
+ extern asmlinkage long sys_rt_sigtimedwait (const sigset_t *, siginfo_t *,
+ const struct timespec *, size_t);
+ extern int copy_siginfo_to_user32 (siginfo_t32 *, siginfo_t *);
+ mm_segment_t old_fs = get_fs();
+ struct timespec t;
+ siginfo_t info;
+ sigset_t s;
+ int ret;
+
+ if (copy_from_user(&s.sig, uthese, sizeof(sigset32_t)))
+ return -EFAULT;
+ if (uts) {
+ ret = get_user(t.tv_sec, &uts->tv_sec);
+ ret |= get_user(t.tv_nsec, &uts->tv_nsec);
+ if (ret)
+ return -EFAULT;
+ }
+ set_fs(KERNEL_DS);
+ ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
+ set_fs(old_fs);
+ if (ret >= 0 && uinfo) {
+ if (copy_siginfo_to_user32(uinfo, &info))
+ return -EFAULT;
+ }
+ return ret;
+}
+
+asmlinkage long
+sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo)
+{
+ extern asmlinkage long sys_rt_sigqueueinfo (int, int, siginfo_t *);
+ extern int copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from);
+ mm_segment_t old_fs = get_fs();
+ siginfo_t info;
+ int ret;
+
+ if (copy_siginfo_from_user32(&info, uinfo))
+ return -EFAULT;
+ set_fs(KERNEL_DS);
+ ret = sys_rt_sigqueueinfo(pid, sig, &info);
+ set_fs(old_fs);
+ return ret;
+}
+
static inline int
put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
{
@@ -516,15 +707,15 @@
extern asmlinkage long sys_statfs(const char * path, struct statfs * buf);

asmlinkage long
-sys32_statfs(const char * path, struct statfs32 *buf)
+sys32_statfs (const char *path, struct statfs32 *buf)
{
int ret;
struct statfs s;
mm_segment_t old_fs = get_fs();

- set_fs (KERNEL_DS);
- ret = sys_statfs((const char *)path, &s);
- set_fs (old_fs);
+ set_fs(KERNEL_DS);
+ ret = sys_statfs(path, &s);
+ set_fs(old_fs);
if (put_statfs(buf, &s))
return -EFAULT;
return ret;
@@ -533,15 +724,15 @@
extern asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf);

asmlinkage long
-sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
+sys32_fstatfs (unsigned int fd, struct statfs32 *buf)
{
int ret;
struct statfs s;
mm_segment_t old_fs = get_fs();

- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
ret = sys_fstatfs(fd, &s);
- set_fs (old_fs);
+ set_fs(old_fs);
if (put_statfs(buf, &s))
return -EFAULT;
return ret;
@@ -559,7 +750,7 @@
};

static inline long
-get_tv32(struct timeval *o, struct timeval32 *i)
+get_tv32 (struct timeval *o, struct timeval32 *i)
{
return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
(__get_user(o->tv_sec, &i->tv_sec) |
@@ -567,7 +758,7 @@
}

static inline long
-put_tv32(struct timeval32 *o, struct timeval *i)
+put_tv32 (struct timeval32 *o, struct timeval *i)
{
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->tv_sec, &o->tv_sec) |
@@ -575,7 +766,7 @@
}

static inline long
-get_it32(struct itimerval *o, struct itimerval32 *i)
+get_it32 (struct itimerval *o, struct itimerval32 *i)
{
return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
(__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
@@ -585,7 +776,7 @@
}

static inline long
-put_it32(struct itimerval32 *o, struct itimerval *i)
+put_it32 (struct itimerval32 *o, struct itimerval *i)
{
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
@@ -594,10 +785,10 @@
__put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
}

-extern int do_getitimer(int which, struct itimerval *value);
+extern int do_getitimer (int which, struct itimerval *value);

asmlinkage long
-sys32_getitimer(int which, struct itimerval32 *it)
+sys32_getitimer (int which, struct itimerval32 *it)
{
struct itimerval kit;
int error;
@@ -609,10 +800,10 @@
return error;
}

-extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
+extern int do_setitimer (int which, struct itimerval *, struct itimerval *);

asmlinkage long
-sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
+sys32_setitimer (int which, struct itimerval32 *in, struct itimerval32 *out)
{
struct itimerval kin, kout;
int error;
@@ -632,8 +823,9 @@
return 0;

}
+
asmlinkage unsigned long
-sys32_alarm(unsigned int seconds)
+sys32_alarm (unsigned int seconds)
{
struct itimerval it_new, it_old;
unsigned int oldalarm;
@@ -662,7 +854,7 @@
extern asmlinkage long sys_gettimeofday (struct timeval *tv, struct timezone *tz);

asmlinkage long
-ia32_utime(char * filename, struct utimbuf_32 *times32)
+sys32_utime (char *filename, struct utimbuf_32 *times32)
{
mm_segment_t old_fs = get_fs();
struct timeval tv[2], *tvp;
@@ -675,20 +867,20 @@
if (get_user(tv[1].tv_sec, &times32->mtime))
return -EFAULT;
tv[1].tv_usec = 0;
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
tvp = tv;
} else
tvp = NULL;
ret = sys_utimes(filename, tvp);
- set_fs (old_fs);
+ set_fs(old_fs);
return ret;
}

extern struct timezone sys_tz;
-extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+extern int do_sys_settimeofday (struct timeval *tv, struct timezone *tz);

asmlinkage long
-sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
+sys32_gettimeofday (struct timeval32 *tv, struct timezone *tz)
{
if (tv) {
struct timeval ktv;
@@ -704,7 +896,7 @@
}

asmlinkage long
-sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
+sys32_settimeofday (struct timeval32 *tv, struct timezone *tz)
{
struct timeval ktv;
struct timezone ktz;
@@ -777,7 +969,7 @@
}

asmlinkage long
-sys32_getdents (unsigned int fd, void * dirent, unsigned int count)
+sys32_getdents (unsigned int fd, struct linux32_dirent *dirent, unsigned int count)
{
struct file * file;
struct linux32_dirent * lastdirent;
@@ -789,7 +981,7 @@
if (!file)
goto out;

- buf.current_dir = (struct linux32_dirent *) dirent;
+ buf.current_dir = dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
@@ -833,7 +1025,7 @@
}

asmlinkage long
-sys32_readdir (unsigned int fd, void * dirent, unsigned int count)
+sys32_readdir (unsigned int fd, void *dirent, unsigned int count)
{
int error;
struct file * file;
@@ -868,7 +1060,7 @@
#define ROUND_UP_TIME(x,y) (((x)+(y)-1)/(y))

asmlinkage long
-sys32_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval32 *tvp32)
+sys32_select (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval32 *tvp32)
{
fd_set_bits fds;
char *bits;
@@ -880,8 +1072,7 @@
time_t sec, usec;

ret = -EFAULT;
- if (get_user(sec, &tvp32->tv_sec)
- || get_user(usec, &tvp32->tv_usec))
+ if (get_user(sec, &tvp32->tv_sec) || get_user(usec, &tvp32->tv_usec))
goto out_nofds;

ret = -EINVAL;
@@ -935,9 +1126,7 @@
usec = timeout % HZ;
usec *= (1000000/HZ);
}
- if (put_user(sec, (int *)&tvp32->tv_sec)
- || put_user(usec, (int *)&tvp32->tv_usec))
- {
+ if (put_user(sec, &tvp32->tv_sec) || put_user(usec, &tvp32->tv_usec)) {
ret = -EFAULT;
goto out;
}
@@ -971,50 +1160,43 @@
};

asmlinkage long
-old_select(struct sel_arg_struct *arg)
+sys32_old_select (struct sel_arg_struct *arg)
{
struct sel_arg_struct a;

if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT;
- return sys32_select(a.n, (fd_set *)A(a.inp), (fd_set *)A(a.outp), (fd_set *)A(a.exp),
- (struct timeval32 *)A(a.tvp));
+ return sys32_select(a.n, (fd_set *) A(a.inp), (fd_set *) A(a.outp), (fd_set *) A(a.exp),
+ (struct timeval32 *) A(a.tvp));
}

-struct timespec32 {
- int tv_sec;
- int tv_nsec;
-};
-
-extern asmlinkage long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
+extern asmlinkage long sys_nanosleep (struct timespec *rqtp, struct timespec *rmtp);

asmlinkage long
-sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
+sys32_nanosleep (struct timespec32 *rqtp, struct timespec32 *rmtp)
{
struct timespec t;
int ret;
mm_segment_t old_fs = get_fs ();

- if (get_user (t.tv_sec, &rqtp->tv_sec) ||
- __get_user (t.tv_nsec, &rqtp->tv_nsec))
+ if (get_user (t.tv_sec, &rqtp->tv_sec) || get_user (t.tv_nsec, &rqtp->tv_nsec))
return -EFAULT;
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
ret = sys_nanosleep(&t, rmtp ? &t : NULL);
- set_fs (old_fs);
+ set_fs(old_fs);
if (rmtp && ret = -EINTR) {
- if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
- __put_user (t.tv_nsec, &rmtp->tv_nsec))
+ if (put_user(t.tv_sec, &rmtp->tv_sec) || put_user(t.tv_nsec, &rmtp->tv_nsec))
return -EFAULT;
}
return ret;
}

struct iovec32 { unsigned int iov_base; int iov_len; };
-asmlinkage ssize_t sys_readv(unsigned long,const struct iovec *,unsigned long);
-asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long);
+asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long);
+asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long);

static struct iovec *
-get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type)
+get_iovec32 (struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type)
{
int i;
u32 buf, len;
@@ -1024,24 +1206,23 @@

if (!count)
return 0;
- if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
- return(struct iovec *)0;
+ if (verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
+ return NULL;
if (count > UIO_MAXIOV)
- return(struct iovec *)0;
+ return NULL;
if (count > UIO_FASTIOV) {
iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
if (!iov)
- return((struct iovec *)0);
+ return NULL;
} else
iov = iov_buf;

ivp = iov;
for (i = 0; i < count; i++) {
- if (__get_user(len, &iov32->iov_len) ||
- __get_user(buf, &iov32->iov_base)) {
+ if (__get_user(len, &iov32->iov_len) || __get_user(buf, &iov32->iov_base)) {
if (iov != iov_buf)
kfree(iov);
- return((struct iovec *)0);
+ return NULL;
}
if (verify_area(type, (void *)A(buf), len)) {
if (iov != iov_buf)
@@ -1049,22 +1230,23 @@
return((struct iovec *)0);
}
ivp->iov_base = (void *)A(buf);
- ivp->iov_len = (__kernel_size_t)len;
+ ivp->iov_len = (__kernel_size_t) len;
iov32++;
ivp++;
}
- return(iov);
+ return iov;
}

asmlinkage long
-sys32_readv(int fd, struct iovec32 *vector, u32 count)
+sys32_readv (int fd, struct iovec32 *vector, u32 count)
{
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov;
- int ret;
+ long ret;
mm_segment_t old_fs = get_fs();

- if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE)) = (struct iovec *)0)
+ iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE);
+ if (!iov)
return -EFAULT;
set_fs(KERNEL_DS);
ret = sys_readv(fd, iov, count);
@@ -1075,14 +1257,15 @@
}

asmlinkage long
-sys32_writev(int fd, struct iovec32 *vector, u32 count)
+sys32_writev (int fd, struct iovec32 *vector, u32 count)
{
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov;
- int ret;
+ long ret;
mm_segment_t old_fs = get_fs();

- if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ)) = (struct iovec *)0)
+ iov = get_iovec32(vector, iovstack, count, VERIFY_READ);
+ if (!iov)
return -EFAULT;
set_fs(KERNEL_DS);
ret = sys_writev(fd, iov, count);
@@ -1100,45 +1283,66 @@
int rlim_max;
};

-extern asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim);
+extern asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim);

asmlinkage long
-sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
+sys32_old_getrlimit (unsigned int resource, struct rlimit32 *rlim)
{
+ mm_segment_t old_fs = get_fs();
struct rlimit r;
int ret;
- mm_segment_t old_fs = get_fs ();

- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
+ ret = sys_getrlimit(resource, &r);
+ set_fs(old_fs);
+ if (!ret) {
+ ret = put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
+ ret |= put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max);
+ }
+ return ret;
+}
+
+asmlinkage long
+sys32_getrlimit (unsigned int resource, struct rlimit32 *rlim)
+{
+ mm_segment_t old_fs = get_fs();
+ struct rlimit r;
+ int ret;
+
+ set_fs(KERNEL_DS);
ret = sys_getrlimit(resource, &r);
- set_fs (old_fs);
+ set_fs(old_fs);
if (!ret) {
- ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
- ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
+ if (r.rlim_cur >= 0xffffffff)
+ r.rlim_cur = 0xffffffff;
+ if (r.rlim_max >= 0xffffffff)
+ r.rlim_max = 0xffffffff;
+ ret = put_user(r.rlim_cur, &rlim->rlim_cur);
+ ret |= put_user(r.rlim_max, &rlim->rlim_max);
}
return ret;
}

-extern asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim);
+extern asmlinkage long sys_setrlimit (unsigned int resource, struct rlimit *rlim);

asmlinkage long
-sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
+sys32_setrlimit (unsigned int resource, struct rlimit32 *rlim)
{
struct rlimit r;
int ret;
- mm_segment_t old_fs = get_fs ();
+ mm_segment_t old_fs = get_fs();

- if (resource >= RLIM_NLIMITS) return -EINVAL;
- if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
- __get_user (r.rlim_max, &rlim->rlim_max))
+ if (resource >= RLIM_NLIMITS)
+ return -EINVAL;
+ if (get_user(r.rlim_cur, &rlim->rlim_cur) || get_user(r.rlim_max, &rlim->rlim_max))
return -EFAULT;
if (r.rlim_cur = RLIM_INFINITY32)
r.rlim_cur = RLIM_INFINITY;
if (r.rlim_max = RLIM_INFINITY32)
r.rlim_max = RLIM_INFINITY;
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
ret = sys_setrlimit(resource, &r);
- set_fs (old_fs);
+ set_fs(old_fs);
return ret;
}

@@ -1157,7 +1361,7 @@
};

static inline int
-shape_msg(struct msghdr *mp, struct msghdr32 *mp32)
+shape_msg (struct msghdr *mp, struct msghdr32 *mp32)
{
int ret;
unsigned int i;
@@ -1189,7 +1393,7 @@
*/

static inline int
-verify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode)
+verify_iovec32 (struct msghdr *m, struct iovec *iov, char *address, int mode)
{
int size, err, ct;
struct iovec32 *iov32;
@@ -1224,8 +1428,8 @@
return err;
}

-extern __inline__ void
-sockfd_put(struct socket *sock)
+static inline void
+sockfd_put (struct socket *sock)
{
fput(sock->file);
}
@@ -1236,13 +1440,14 @@
24 for IPv6,
about 80 for AX.25 */

-extern struct socket *sockfd_lookup(int fd, int *err);
+extern struct socket *sockfd_lookup (int fd, int *err);

/*
* BSD sendmsg interface
*/

-int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags)
+int
+sys32_sendmsg (int fd, struct msghdr32 *msg, unsigned flags)
{
struct socket *sock;
char address[MAX_SOCK_ADDR];
@@ -1406,9 +1611,9 @@

/* Argument list sizes for sys_socketcall */
#define AL(x) ((x) * sizeof(u32))
-static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
- AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
- AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+static const unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+ AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
+ AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
#undef AL

extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
@@ -1437,7 +1642,8 @@
extern asmlinkage long sys_shutdown(int fd, int how);
extern asmlinkage long sys_listen(int fd, int backlog);

-asmlinkage long sys32_socketcall(int call, u32 *args)
+asmlinkage long
+sys32_socketcall (int call, u32 *args)
{
int ret;
u32 a[6];
@@ -1465,16 +1671,13 @@
ret = sys_listen(a0, a1);
break;
case SYS_ACCEPT:
- ret = sys_accept(a0, (struct sockaddr *)A(a1),
- (int *)A(a[2]));
+ ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
break;
case SYS_GETSOCKNAME:
- ret = sys_getsockname(a0, (struct sockaddr *)A(a1),
- (int *)A(a[2]));
+ ret = sys_getsockname(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
break;
case SYS_GETPEERNAME:
- ret = sys_getpeername(a0, (struct sockaddr *)A(a1),
- (int *)A(a[2]));
+ ret = sys_getpeername(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
break;
case SYS_SOCKETPAIR:
ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
@@ -1502,12 +1705,10 @@
ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]);
break;
case SYS_SENDMSG:
- ret = sys32_sendmsg(a0, (struct msghdr32 *)A(a1),
- a[2]);
+ ret = sys32_sendmsg(a0, (struct msghdr32 *) A(a1), a[2]);
break;
case SYS_RECVMSG:
- ret = sys32_recvmsg(a0, (struct msghdr32 *)A(a1),
- a[2]);
+ ret = sys32_recvmsg(a0, (struct msghdr32 *) A(a1), a[2]);
break;
default:
ret = EINVAL;
@@ -1574,10 +1775,27 @@
unsigned short shm_nattch;
};

+struct ipc_kludge {
+ struct msgbuf *msgp;
+ long msgtyp;
+};
+
+#define SEMOP 1
+#define SEMGET 2
+#define SEMCTL 3
+#define MSGSND 11
+#define MSGRCV 12
+#define MSGGET 13
+#define MSGCTL 14
+#define SHMAT 21
+#define SHMDT 22
+#define SHMGET 23
+#define SHMCTL 24
+
#define IPCOP_MASK(__x) (1UL << (__x))

static int
-do_sys32_semctl(int first, int second, int third, void *uptr)
+do_sys32_semctl (int first, int second, int third, void *uptr)
{
union semun fourth;
u32 pad;
@@ -1590,7 +1808,7 @@
return -EINVAL;
if (get_user(pad, (u32 *)uptr))
return -EFAULT;
- if(third = SETVAL)
+ if (third = SETVAL)
fourth.val = (int)pad;
else
fourth.__pad = (void *)A(pad);
@@ -1607,44 +1825,38 @@
case GETALL:
case SETVAL:
case SETALL:
- err = sys_semctl (first, second, third, fourth);
+ err = sys_semctl(first, second, third, fourth);
break;

case IPC_STAT:
case SEM_STAT:
usp = (struct semid_ds32 *)A(pad);
fourth.__pad = &s;
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_semctl (first, second, third, fourth);
- set_fs (old_fs);
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_semctl(first, second, third, fourth);
+ set_fs(old_fs);
err2 = put_user(s.sem_perm.key, &usp->sem_perm.key);
- err2 |= __put_user(s.sem_perm.uid, &usp->sem_perm.uid);
- err2 |= __put_user(s.sem_perm.gid, &usp->sem_perm.gid);
- err2 |= __put_user(s.sem_perm.cuid,
- &usp->sem_perm.cuid);
- err2 |= __put_user (s.sem_perm.cgid,
- &usp->sem_perm.cgid);
- err2 |= __put_user (s.sem_perm.mode,
- &usp->sem_perm.mode);
- err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
- err2 |= __put_user (s.sem_otime, &usp->sem_otime);
- err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
- err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
+ err2 |= put_user(s.sem_perm.uid, &usp->sem_perm.uid);
+ err2 |= put_user(s.sem_perm.gid, &usp->sem_perm.gid);
+ err2 |= put_user(s.sem_perm.cuid, &usp->sem_perm.cuid);
+ err2 |= put_user(s.sem_perm.cgid, &usp->sem_perm.cgid);
+ err2 |= put_user(s.sem_perm.mode, &usp->sem_perm.mode);
+ err2 |= put_user(s.sem_perm.seq, &usp->sem_perm.seq);
+ err2 |= put_user(s.sem_otime, &usp->sem_otime);
+ err2 |= put_user(s.sem_ctime, &usp->sem_ctime);
+ err2 |= put_user(s.sem_nsems, &usp->sem_nsems);
if (err2)
err = -EFAULT;
break;
-
}
-
return err;
}

static int
do_sys32_msgsnd (int first, int second, int third, void *uptr)
{
- struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf)
- + 4, GFP_USER);
+ struct msgbuf *p = kmalloc (second + sizeof(struct msgbuf) + 4, GFP_USER);
struct msgbuf32 *up = (struct msgbuf32 *)uptr;
mm_segment_t old_fs;
int err;
@@ -1656,17 +1868,16 @@
if (err)
goto out;
old_fs = get_fs ();
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
err = sys_msgsnd (first, p, second, third);
- set_fs (old_fs);
+ set_fs(old_fs);
out:
kfree (p);
return err;
}

static int
-do_sys32_msgrcv (int first, int second, int msgtyp, int third,
- int version, void *uptr)
+do_sys32_msgrcv (int first, int second, int msgtyp, int third, int version, void *uptr)
{
struct msgbuf32 *up;
struct msgbuf *p;
@@ -1691,9 +1902,9 @@
if (!p)
goto out;
old_fs = get_fs ();
- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
err = sys_msgrcv (first, p, second + 4, msgtyp, third);
- set_fs (old_fs);
+ set_fs(old_fs);
if (err < 0)
goto free_then_out;
up = (struct msgbuf32 *)uptr;
@@ -1720,49 +1931,47 @@
case IPC_INFO:
case IPC_RMID:
case MSG_INFO:
- err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
+ err = sys_msgctl(first, second, (struct msqid_ds *)uptr);
break;

case IPC_SET:
- err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
- err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
- err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
- err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
+ err = get_user(m.msg_perm.uid, &up->msg_perm.uid);
+ err |= get_user(m.msg_perm.gid, &up->msg_perm.gid);
+ err |= get_user(m.msg_perm.mode, &up->msg_perm.mode);
+ err |= get_user(m.msg_qbytes, &up->msg_qbytes);
if (err)
break;
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_msgctl (first, second, &m);
- set_fs (old_fs);
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_msgctl(first, second, &m);
+ set_fs(old_fs);
break;

case IPC_STAT:
case MSG_STAT:
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_msgctl (first, second, (void *) &m64);
- set_fs (old_fs);
- err2 = put_user (m64.msg_perm.key, &up->msg_perm.key);
- err2 |= __put_user(m64.msg_perm.uid, &up->msg_perm.uid);
- err2 |= __put_user(m64.msg_perm.gid, &up->msg_perm.gid);
- err2 |= __put_user(m64.msg_perm.cuid, &up->msg_perm.cuid);
- err2 |= __put_user(m64.msg_perm.cgid, &up->msg_perm.cgid);
- err2 |= __put_user(m64.msg_perm.mode, &up->msg_perm.mode);
- err2 |= __put_user(m64.msg_perm.seq, &up->msg_perm.seq);
- err2 |= __put_user(m64.msg_stime, &up->msg_stime);
- err2 |= __put_user(m64.msg_rtime, &up->msg_rtime);
- err2 |= __put_user(m64.msg_ctime, &up->msg_ctime);
- err2 |= __put_user(m64.msg_cbytes, &up->msg_cbytes);
- err2 |= __put_user(m64.msg_qnum, &up->msg_qnum);
- err2 |= __put_user(m64.msg_qbytes, &up->msg_qbytes);
- err2 |= __put_user(m64.msg_lspid, &up->msg_lspid);
- err2 |= __put_user(m64.msg_lrpid, &up->msg_lrpid);
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_msgctl(first, second, (void *) &m64);
+ set_fs(old_fs);
+ err2 = put_user(m64.msg_perm.key, &up->msg_perm.key);
+ err2 |= put_user(m64.msg_perm.uid, &up->msg_perm.uid);
+ err2 |= put_user(m64.msg_perm.gid, &up->msg_perm.gid);
+ err2 |= put_user(m64.msg_perm.cuid, &up->msg_perm.cuid);
+ err2 |= put_user(m64.msg_perm.cgid, &up->msg_perm.cgid);
+ err2 |= put_user(m64.msg_perm.mode, &up->msg_perm.mode);
+ err2 |= put_user(m64.msg_perm.seq, &up->msg_perm.seq);
+ err2 |= put_user(m64.msg_stime, &up->msg_stime);
+ err2 |= put_user(m64.msg_rtime, &up->msg_rtime);
+ err2 |= put_user(m64.msg_ctime, &up->msg_ctime);
+ err2 |= put_user(m64.msg_cbytes, &up->msg_cbytes);
+ err2 |= put_user(m64.msg_qnum, &up->msg_qnum);
+ err2 |= put_user(m64.msg_qbytes, &up->msg_qbytes);
+ err2 |= put_user(m64.msg_lspid, &up->msg_lspid);
+ err2 |= put_user(m64.msg_lrpid, &up->msg_lrpid);
if (err2)
err = -EFAULT;
break;
-
}
-
return err;
}

@@ -1774,8 +1983,8 @@
int err;

if (version = 1)
- return -EINVAL;
- err = sys_shmat (first, uptr, second, &raddr);
+ return -EINVAL; /* iBCS2 emulator entry point: unsupported */
+ err = sys_shmat(first, uptr, second, &raddr);
if (err)
return err;
return put_user(raddr, uaddr);
@@ -1806,60 +2015,55 @@
break;
case IPC_SET:
err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
- err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
- err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
+ err |= get_user(s.shm_perm.gid, &up->shm_perm.gid);
+ err |= get_user(s.shm_perm.mode, &up->shm_perm.mode);
if (err)
break;
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_shmctl (first, second, &s);
- set_fs (old_fs);
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_shmctl(first, second, &s);
+ set_fs(old_fs);
break;

case IPC_STAT:
case SHM_STAT:
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
err = sys_shmctl (first, second, (void *) &s64);
- set_fs (old_fs);
+ set_fs(old_fs);
if (err < 0)
break;
- err2 = put_user (s64.shm_perm.key, &up->shm_perm.key);
- err2 |= __put_user (s64.shm_perm.uid, &up->shm_perm.uid);
- err2 |= __put_user (s64.shm_perm.gid, &up->shm_perm.gid);
- err2 |= __put_user (s64.shm_perm.cuid,
- &up->shm_perm.cuid);
- err2 |= __put_user (s64.shm_perm.cgid,
- &up->shm_perm.cgid);
- err2 |= __put_user (s64.shm_perm.mode,
- &up->shm_perm.mode);
- err2 |= __put_user (s64.shm_perm.seq, &up->shm_perm.seq);
- err2 |= __put_user (s64.shm_atime, &up->shm_atime);
- err2 |= __put_user (s64.shm_dtime, &up->shm_dtime);
- err2 |= __put_user (s64.shm_ctime, &up->shm_ctime);
- err2 |= __put_user (s64.shm_segsz, &up->shm_segsz);
- err2 |= __put_user (s64.shm_nattch, &up->shm_nattch);
- err2 |= __put_user (s64.shm_cpid, &up->shm_cpid);
- err2 |= __put_user (s64.shm_lpid, &up->shm_lpid);
+ err2 = put_user(s64.shm_perm.key, &up->shm_perm.key);
+ err2 |= put_user(s64.shm_perm.uid, &up->shm_perm.uid);
+ err2 |= put_user(s64.shm_perm.gid, &up->shm_perm.gid);
+ err2 |= put_user(s64.shm_perm.cuid, &up->shm_perm.cuid);
+ err2 |= put_user(s64.shm_perm.cgid, &up->shm_perm.cgid);
+ err2 |= put_user(s64.shm_perm.mode, &up->shm_perm.mode);
+ err2 |= put_user(s64.shm_perm.seq, &up->shm_perm.seq);
+ err2 |= put_user(s64.shm_atime, &up->shm_atime);
+ err2 |= put_user(s64.shm_dtime, &up->shm_dtime);
+ err2 |= put_user(s64.shm_ctime, &up->shm_ctime);
+ err2 |= put_user(s64.shm_segsz, &up->shm_segsz);
+ err2 |= put_user(s64.shm_nattch, &up->shm_nattch);
+ err2 |= put_user(s64.shm_cpid, &up->shm_cpid);
+ err2 |= put_user(s64.shm_lpid, &up->shm_lpid);
if (err2)
err = -EFAULT;
break;

case SHM_INFO:
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_shmctl (first, second, (void *)&si);
- set_fs (old_fs);
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = sys_shmctl(first, second, (void *)&si);
+ set_fs(old_fs);
if (err < 0)
break;
- err2 = put_user (si.used_ids, &uip->used_ids);
- err2 |= __put_user (si.shm_tot, &uip->shm_tot);
- err2 |= __put_user (si.shm_rss, &uip->shm_rss);
- err2 |= __put_user (si.shm_swp, &uip->shm_swp);
- err2 |= __put_user (si.swap_attempts,
- &uip->swap_attempts);
- err2 |= __put_user (si.swap_successes,
- &uip->swap_successes);
+ err2 = put_user(si.used_ids, &uip->used_ids);
+ err2 |= put_user(si.shm_tot, &uip->shm_tot);
+ err2 |= put_user(si.shm_rss, &uip->shm_rss);
+ err2 |= put_user(si.shm_swp, &uip->shm_swp);
+ err2 |= put_user(si.swap_attempts, &uip->swap_attempts);
+ err2 |= put_user(si.swap_successes, &uip->swap_successes);
if (err2)
err = -EFAULT;
break;
@@ -1877,53 +2081,48 @@
call &= 0xffff;

switch (call) {
-
- case SEMOP:
+ case SEMOP:
/* struct sembuf is the same on 32 and 64bit :)) */
- err = sys_semop (first, (struct sembuf *)AA(ptr),
- second);
- break;
- case SEMGET:
- err = sys_semget (first, second, third);
- break;
- case SEMCTL:
- err = do_sys32_semctl (first, second, third,
- (void *)AA(ptr));
- break;
+ return sys_semop(first, (struct sembuf *)AA(ptr), second);
+ case SEMGET:
+ return sys_semget(first, second, third);
+ case SEMCTL:
+ if (third & IPC_64) {
+ printk("sys32_ipc(SEMCTL): no IPC_64 version; please fix me.");
+ return -ENOSYS;
+ }
+ return do_sys32_semctl(first, second, third, (void *)AA(ptr));

- case MSGSND:
- err = do_sys32_msgsnd (first, second, third,
- (void *)AA(ptr));
- break;
- case MSGRCV:
- err = do_sys32_msgrcv (first, second, fifth, third,
- version, (void *)AA(ptr));
- break;
- case MSGGET:
- err = sys_msgget ((key_t) first, second);
- break;
- case MSGCTL:
- err = do_sys32_msgctl (first, second, (void *)AA(ptr));
- break;
+ case MSGSND:
+ return do_sys32_msgsnd(first, second, third, (void *)AA(ptr));
+ case MSGRCV:
+ return do_sys32_msgrcv(first, second, fifth, third, version, (void *)AA(ptr));
+ case MSGGET:
+ return sys_msgget((key_t) first, second);
+ case MSGCTL:
+ if (second & IPC_64) {
+ printk("sys32_ipc(MSGCTL): no IPC_64 version; please fix me.");
+ return -ENOSYS;
+ }
+ return do_sys32_msgctl(first, second, (void *)AA(ptr));

- case SHMAT:
- err = do_sys32_shmat (first, second, third, version, (void *)AA(ptr));
+ case SHMAT:
+ err = do_sys32_shmat(first, second, third, version, (void *)AA(ptr));
break;
- case SHMDT:
- err = sys_shmdt ((char *)AA(ptr));
- break;
- case SHMGET:
- err = sys_shmget (first, second, third);
- break;
- case SHMCTL:
- err = do_sys32_shmctl (first, second, (void *)AA(ptr));
- break;
- default:
- err = -EINVAL;
- break;
- }
+ case SHMDT:
+ return sys_shmdt((char *)AA(ptr));
+ case SHMGET:
+ return sys_shmget(first, second, third);
+ case SHMCTL:
+ if (second & IPC_64) {
+ printk("sys32_ipc(SHMCTL): no IPC_64 version; please fix me.");
+ return -ENOSYS;
+ }
+ return do_sys32_shmctl(first, second, (void *)AA(ptr));

- return err;
+ default:
+ return -EINVAL;
+ }
}

/*
@@ -1931,7 +2130,8 @@
* sys_gettimeofday(). IA64 did this but i386 Linux did not
* so we have to implement this system call here.
*/
-asmlinkage long sys32_time(int * tloc)
+asmlinkage long
+sys32_time (int *tloc)
{
int i;

@@ -1939,7 +2139,7 @@
stuff it to user space. No side effects */
i = CURRENT_TIME;
if (tloc) {
- if (put_user(i,tloc))
+ if (put_user(i, tloc))
i = -EFAULT;
}
return i;
@@ -1991,8 +2191,7 @@
}

asmlinkage long
-sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options,
- struct rusage32 *ru)
+sys32_wait4 (int pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
{
if (!ru)
return sys_wait4(pid, stat_addr, options, NULL);
@@ -2002,37 +2201,38 @@
unsigned int status;
mm_segment_t old_fs = get_fs();

- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
- set_fs (old_fs);
- if (put_rusage (ru, &r)) return -EFAULT;
- if (stat_addr && put_user (status, stat_addr))
+ set_fs(old_fs);
+ if (put_rusage(ru, &r))
+ return -EFAULT;
+ if (stat_addr && put_user(status, stat_addr))
return -EFAULT;
return ret;
}
}

asmlinkage long
-sys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options)
+sys32_waitpid (int pid, unsigned int *stat_addr, int options)
{
return sys32_wait4(pid, stat_addr, options, NULL);
}

-extern asmlinkage long
-sys_getrusage(int who, struct rusage *ru);
+extern asmlinkage long sys_getrusage (int who, struct rusage *ru);

asmlinkage long
-sys32_getrusage(int who, struct rusage32 *ru)
+sys32_getrusage (int who, struct rusage32 *ru)
{
struct rusage r;
int ret;
mm_segment_t old_fs = get_fs();

- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
ret = sys_getrusage(who, &r);
- set_fs (old_fs);
- if (put_rusage (ru, &r)) return -EFAULT;
+ set_fs(old_fs);
+ if (put_rusage (ru, &r))
+ return -EFAULT;
return ret;
}

@@ -2043,41 +2243,41 @@
__kernel_clock_t32 tms_cstime;
};

-extern asmlinkage long sys_times(struct tms * tbuf);
+extern asmlinkage long sys_times (struct tms * tbuf);

asmlinkage long
-sys32_times(struct tms32 *tbuf)
+sys32_times (struct tms32 *tbuf)
{
+ mm_segment_t old_fs = get_fs();
struct tms t;
long ret;
- mm_segment_t old_fs = get_fs ();
int err;

- set_fs (KERNEL_DS);
+ set_fs(KERNEL_DS);
ret = sys_times(tbuf ? &t : NULL);
- set_fs (old_fs);
+ set_fs(old_fs);
if (tbuf) {
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);
+ 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 IA32_TICK(ret);
}

-unsigned int
+static unsigned int
ia32_peek (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int *val)
{
size_t copied;
unsigned int ret;

copied = access_process_vm(child, addr, val, sizeof(*val), 0);
- return(copied != sizeof(ret) ? -EIO : 0);
+ return (copied != sizeof(ret)) ? -EIO : 0;
}

-unsigned int
+static unsigned int
ia32_poke (struct pt_regs *regs, struct task_struct *child, unsigned long addr, unsigned int val)
{

@@ -2107,113 +2307,70 @@
#define PT_UESP 15
#define PT_SS 16

-unsigned int
-getreg(struct task_struct *child, int regno)
+static unsigned int
+getreg (struct task_struct *child, int regno)
{
struct pt_regs *child_regs;

child_regs = ia64_task_regs(child);
switch (regno / sizeof(int)) {
-
- case PT_EBX:
- return(child_regs->r11);
- case PT_ECX:
- return(child_regs->r9);
- case PT_EDX:
- return(child_regs->r10);
- case PT_ESI:
- return(child_regs->r14);
- case PT_EDI:
- return(child_regs->r15);
- case PT_EBP:
- return(child_regs->r13);
- case PT_EAX:
- case PT_ORIG_EAX:
- return(child_regs->r8);
- case PT_EIP:
- return(child_regs->cr_iip);
- case PT_UESP:
- return(child_regs->r12);
- case PT_EFL:
- return(child->thread.eflag);
- case PT_DS:
- case PT_ES:
- case PT_FS:
- case PT_GS:
- case PT_SS:
- return((unsigned int)__USER_DS);
- case PT_CS:
- return((unsigned int)__USER_CS);
- default:
- printk(KERN_ERR "getregs:unknown register %d\n", regno);
+ case PT_EBX: return child_regs->r11;
+ case PT_ECX: return child_regs->r9;
+ case PT_EDX: return child_regs->r10;
+ case PT_ESI: return child_regs->r14;
+ case PT_EDI: return child_regs->r15;
+ case PT_EBP: return child_regs->r13;
+ case PT_EAX: return child_regs->r8;
+ case PT_ORIG_EAX: return child_regs->r1; /* see dispatch_to_ia32_handler() */
+ case PT_EIP: return child_regs->cr_iip;
+ case PT_UESP: return child_regs->r12;
+ case PT_EFL: return child->thread.eflag;
+ case PT_DS: case PT_ES: case PT_FS: case PT_GS: case PT_SS:
+ return __USER_DS;
+ case PT_CS: return __USER_CS;
+ default:
+ printk(KERN_ERR "getreg:unknown register %d\n", regno);
break;
-
}
- return(0);
+ return 0;
}

-void
-putreg(struct task_struct *child, int regno, unsigned int value)
+static void
+putreg (struct task_struct *child, int regno, unsigned int value)
{
struct pt_regs *child_regs;

child_regs = ia64_task_regs(child);
switch (regno / sizeof(int)) {
-
- case PT_EBX:
- child_regs->r11 = value;
- break;
- case PT_ECX:
- child_regs->r9 = value;
- break;
- case PT_EDX:
- child_regs->r10 = value;
- break;
- case PT_ESI:
- child_regs->r14 = value;
- break;
- case PT_EDI:
- child_regs->r15 = value;
- break;
- case PT_EBP:
- child_regs->r13 = value;
- break;
- case PT_EAX:
- case PT_ORIG_EAX:
- child_regs->r8 = value;
- break;
- case PT_EIP:
- child_regs->cr_iip = value;
- break;
- case PT_UESP:
- child_regs->r12 = value;
- break;
- case PT_EFL:
- child->thread.eflag = value;
- break;
- case PT_DS:
- case PT_ES:
- case PT_FS:
- case PT_GS:
- case PT_SS:
+ case PT_EBX: child_regs->r11 = value; break;
+ case PT_ECX: child_regs->r9 = value; break;
+ case PT_EDX: child_regs->r10 = value; break;
+ case PT_ESI: child_regs->r14 = value; break;
+ case PT_EDI: child_regs->r15 = value; break;
+ case PT_EBP: child_regs->r13 = value; break;
+ case PT_EAX: child_regs->r8 = value; break;
+ case PT_ORIG_EAX: child_regs->r1 = value; break;
+ case PT_EIP: child_regs->cr_iip = value; break;
+ case PT_UESP: child_regs->r12 = value; break;
+ case PT_EFL: child->thread.eflag = value; break;
+ case PT_DS: case PT_ES: case PT_FS: case PT_GS: case PT_SS:
if (value != __USER_DS)
printk(KERN_ERR "setregs:try to set invalid segment register %d = %x\n",
regno, value);
break;
- case PT_CS:
+ case PT_CS:
if (value != __USER_CS)
printk(KERN_ERR "setregs:try to set invalid segment register %d = %x\n",
regno, value);
break;
- default:
- printk(KERN_ERR "getregs:unknown register %d\n", regno);
+ default:
+ printk(KERN_ERR "putreg:unknown register %d\n", regno);
break;
-
}
}

static inline void
-ia32f2ia64f(void *dst, void *src)
+ia32f2ia64f (void *dst, void *src)
{

__asm__ ("ldfe f6=[%1] ;;\n\t"
@@ -2224,7 +2381,7 @@
}

static inline void
-ia64f2ia32f(void *dst, void *src)
+ia64f2ia32f (void *dst, void *src)
{

__asm__ ("ldf.fill f6=[%1] ;;\n\t"
@@ -2234,8 +2391,9 @@
return;
}

-void
-put_fpreg(int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, int tos)
+static void
+put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
+ int tos)
{
struct _fpreg_ia32 *f;
char buf[32];
@@ -2264,8 +2422,9 @@
__copy_to_user(reg, f, sizeof(*reg));
}

-void
-get_fpreg(int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp, int tos)
+static void
+get_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
+ int tos)
{

if ((regno += tos) >= 8)
@@ -2291,8 +2450,8 @@
return;
}

-int
-save_ia32_fpstate(struct task_struct *tsk, struct _fpstate_ia32 *save)
+static int
+save_ia32_fpstate (struct task_struct *tsk, struct _fpstate_ia32 *save)
{
struct switch_stack *swp;
struct pt_regs *ptp;
@@ -2315,11 +2474,11 @@
tos = (tsk->thread.fsr >> 11) & 3;
for (i = 0; i < 8; i++)
put_fpreg(i, &save->_st[i], ptp, swp, tos);
- return(0);
+ return 0;
}

-int
-restore_ia32_fpstate(struct task_struct *tsk, struct _fpstate_ia32 *save)
+static int
+restore_ia32_fpstate (struct task_struct *tsk, struct _fpstate_ia32 *save)
{
struct switch_stack *swp;
struct pt_regs *ptp;
@@ -2342,10 +2501,11 @@
tos = (tsk->thread.fsr >> 11) & 3;
for (i = 0; i < 8; i++)
get_fpreg(i, &save->_st[i], ptp, swp, tos);
- return(ret ? -EFAULT : 0);
+ return ret ? -EFAULT : 0;
}

-asmlinkage long sys_ptrace(long, pid_t, unsigned long, unsigned long, long, long, long, long, long);
+extern asmlinkage long sys_ptrace (long, pid_t, unsigned long, unsigned long, long, long, long,
+ long, long);

/*
* Note that the IA32 version of `ptrace' calls the IA64 routine for
@@ -2360,13 +2520,12 @@
{
struct pt_regs *regs = (struct pt_regs *) &stack;
struct task_struct *child;
+ unsigned int value, tmp;
long i, ret;
- unsigned int value;

lock_kernel();
if (request = PTRACE_TRACEME) {
- ret = sys_ptrace(request, pid, addr, data,
- arg4, arg5, arg6, arg7, stack);
+ ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack);
goto out;
}

@@ -2381,8 +2540,7 @@
goto out;

if (request = PTRACE_ATTACH) {
- ret = sys_ptrace(request, pid, addr, data,
- arg4, arg5, arg6, arg7, stack);
+ ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack);
goto out;
}
ret = -ESRCH;
@@ -2400,21 +2558,32 @@
case PTRACE_PEEKDATA: /* read word at location addr */
ret = ia32_peek(regs, child, addr, &value);
if (ret = 0)
- ret = put_user(value, (unsigned int *)A(data));
+ ret = put_user(value, (unsigned int *) A(data));
else
ret = -EIO;
goto out;

case PTRACE_POKETEXT:
case PTRACE_POKEDATA: /* write the word at location addr */
- ret = ia32_poke(regs, child, addr, (unsigned int)data);
+ ret = ia32_poke(regs, child, addr, data);
goto out;

case PTRACE_PEEKUSR: /* read word at addr in USER area */
- ret = 0;
+ ret = -EIO;
+ if ((addr & 3) || addr > 17*sizeof(int))
+ break;
+
+ tmp = getreg(child, addr);
+ if (!put_user(tmp, (unsigned int *) A(data)))
+ ret = 0;
break;

case PTRACE_POKEUSR: /* write word at addr in USER area */
+ ret = -EIO;
+ if ((addr & 3) || addr > 17*sizeof(int))
+ break;
+
+ putreg(child, addr, data);
ret = 0;
break;

@@ -2423,28 +2592,25 @@
ret = -EIO;
break;
}
- for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
- __put_user(getreg(child, i), (unsigned int *) A(data));
+ for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
+ put_user(getreg(child, i), (unsigned int *) A(data));
data += sizeof(int);
}
ret = 0;
break;

case IA32_PTRACE_SETREGS:
- {
- unsigned int tmp;
if (!access_ok(VERIFY_READ, (int *) A(data), 17*sizeof(int))) {
ret = -EIO;
break;
}
- for ( i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
- __get_user(tmp, (unsigned int *) A(data));
+ for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) {
+ get_user(tmp, (unsigned int *) A(data));
putreg(child, i, tmp);
data += sizeof(int);
}
ret = 0;
break;
- }

case IA32_PTRACE_GETFPREGS:
ret = save_ia32_fpstate(child, (struct _fpstate_ia32 *) A(data));
@@ -2459,10 +2625,8 @@
case PTRACE_KILL:
case PTRACE_SINGLESTEP: /* execute chile for one instruction */
case PTRACE_DETACH: /* detach a process */
- unlock_kernel();
- ret = sys_ptrace(request, pid, addr, data,
- arg4, arg5, arg6, arg7, stack);
- return(ret);
+ ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack);
+ break;

default:
ret = -EIO;
@@ -2500,35 +2664,35 @@
return err;
}

-extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd,
- unsigned long arg);
+extern asmlinkage long sys_fcntl (unsigned int fd, unsigned int cmd, unsigned long arg);

asmlinkage long
-sys32_fcntl(unsigned int fd, unsigned int cmd, int arg)
+sys32_fcntl (unsigned int fd, unsigned int cmd, unsigned int arg)
{
- struct flock f;
mm_segment_t old_fs;
+ struct flock f;
long ret;

switch (cmd) {
- case F_GETLK:
- case F_SETLK:
- case F_SETLKW:
- if(get_flock32(&f, (struct flock32 *)((long)arg)))
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ if (get_flock32(&f, (struct flock32 *) A(arg)))
return -EFAULT;
old_fs = get_fs();
set_fs(KERNEL_DS);
- ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+ ret = sys_fcntl(fd, cmd, (unsigned long) &f);
set_fs(old_fs);
- if(cmd = F_GETLK && put_flock32(&f, (struct flock32 *)((long)arg)))
+ if (cmd = F_GETLK && put_flock32(&f, (struct flock32 *) A(arg)))
return -EFAULT;
return ret;
- default:
+
+ default:
/*
* `sys_fcntl' lies about arg, for the F_SETOWN
* sub-function arg can have a negative value.
*/
- return sys_fcntl(fd, cmd, (unsigned long)((long)arg));
+ return sys_fcntl(fd, cmd, arg);
}
}

@@ -2536,25 +2700,30 @@
sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
{
struct k_sigaction new_ka, old_ka;
+ unsigned int handler, restorer;
int ret;

if (act) {
old_sigset32_t mask;

- ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
- ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
- ret |= __get_user(mask, &act->sa_mask);
+ ret = get_user(handler, &act->sa_handler);
+ ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ ret |= get_user(restorer, &act->sa_restorer);
+ ret |= get_user(mask, &act->sa_mask);
if (ret)
return ret;
+
+ sigact_set_handler(&new_ka, handler, restorer);
siginitset(&new_ka.sa.sa_mask, mask);
}

ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);

if (!ret && oact) {
- ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
- ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+ ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler);
+ ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer);
+ ret |= put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
}

return ret;
@@ -2563,8 +2732,8 @@
asmlinkage long sys_ni_syscall(void);

asmlinkage long
-sys32_ni_syscall(int dummy0, int dummy1, int dummy2, int dummy3,
- int dummy4, int dummy5, int dummy6, int dummy7, int stack)
+sys32_ni_syscall (int dummy0, int dummy1, int dummy2, int dummy3, int dummy4, int dummy5,
+ int dummy6, int dummy7, int stack)
{
struct pt_regs *regs = (struct pt_regs *)&stack;

@@ -2579,7 +2748,7 @@
#define IOLEN ((65536 / 4) * 4096)

asmlinkage long
-sys_iopl (int level)
+sys32_iopl (int level)
{
extern unsigned long ia64_iobase;
int fd;
@@ -2624,7 +2793,7 @@
}

asmlinkage long
-sys_ioperm (unsigned int from, unsigned int num, int on)
+sys32_ioperm (unsigned int from, unsigned int num, int on)
{

/*
@@ -2637,7 +2806,7 @@
* XXX proper ioperm() support should be emulated by
* manipulating the page protections...
*/
- return sys_iopl(3);
+ return sys32_iopl(3);
}

typedef struct {
@@ -2647,10 +2816,8 @@
} 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)
+sys32_sigaltstack (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;
@@ -2659,8 +2826,8 @@
mm_segment_t old_fs = get_fs();

if (uss32)
- if (copy_from_user(&buf32, (void *)A(uss32), sizeof(ia32_stack_t)))
- return(-EFAULT);
+ if (copy_from_user(&buf32, uss32, sizeof(ia32_stack_t)))
+ return -EFAULT;
uss.ss_sp = (void *) (long) buf32.ss_sp;
uss.ss_flags = buf32.ss_flags;
uss.ss_size = buf32.ss_size;
@@ -2673,34 +2840,34 @@
buf32.ss_sp = (long) 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);
+ if (copy_to_user(uoss32, &buf32, sizeof(ia32_stack_t)))
+ return -EFAULT;
}
- return(ret);
+ return ret;
}

asmlinkage int
-sys_pause (void)
+sys32_pause (void)
{
current->state = TASK_INTERRUPTIBLE;
schedule();
return -ERESTARTNOHAND;
}

-asmlinkage long sys_msync(unsigned long start, size_t len, int flags);
+asmlinkage long sys_msync (unsigned long start, size_t len, int flags);

asmlinkage int
-sys32_msync(unsigned int start, unsigned int len, int flags)
+sys32_msync (unsigned int start, unsigned int len, int flags)
{
unsigned int addr;

if (OFFSET4K(start))
return -EINVAL;
addr = start & PAGE_MASK;
- return(sys_msync(addr, len + (start - addr), flags));
+ return sys_msync(addr, len + (start - addr), flags);
}

-struct sysctl_ia32 {
+struct sysctl32 {
unsigned int name;
int nlen;
unsigned int oldval;
@@ -2713,16 +2880,16 @@
extern asmlinkage long sys_sysctl(struct __sysctl_args *args);

asmlinkage long
-sys32_sysctl(struct sysctl_ia32 *args32)
+sys32_sysctl (struct sysctl32 *args)
{
- struct sysctl_ia32 a32;
+ struct sysctl32 a32;
mm_segment_t old_fs = get_fs ();
void *oldvalp, *newvalp;
size_t oldlen;
int *namep;
long ret;

- if (copy_from_user(&a32, args32, sizeof (a32)))
+ if (copy_from_user(&a32, args, sizeof(a32)))
return -EFAULT;

/*
@@ -2755,7 +2922,7 @@
}

asmlinkage long
-sys32_newuname(struct new_utsname * name)
+sys32_newuname (struct new_utsname *name)
{
extern asmlinkage long sys_newuname(struct new_utsname * name);
int ret = sys_newuname(name);
@@ -2766,10 +2933,10 @@
return ret;
}

-extern asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
+extern asmlinkage long sys_getresuid (uid_t *ruid, uid_t *euid, uid_t *suid);

asmlinkage long
-sys32_getresuid (u16 *ruid, u16 *euid, u16 *suid)
+sys32_getresuid16 (u16 *ruid, u16 *euid, u16 *suid)
{
uid_t a, b, c;
int ret;
@@ -2787,7 +2954,7 @@
extern asmlinkage long sys_getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid);

asmlinkage long
-sys32_getresgid(u16 *rgid, u16 *egid, u16 *sgid)
+sys32_getresgid16 (u16 *rgid, u16 *egid, u16 *sgid)
{
gid_t a, b, c;
int ret;
@@ -2797,15 +2964,13 @@
ret = sys_getresgid(&a, &b, &c);
set_fs(old_fs);

- if (!ret) {
- ret = put_user(a, rgid);
- ret |= put_user(b, egid);
- ret |= put_user(c, sgid);
- }
- return ret;
+ if (ret)
+ return ret;
+
+ return put_user(a, rgid) | put_user(b, egid) | put_user(c, sgid);
}

-int
+asmlinkage long
sys32_lseek (unsigned int fd, int offset, unsigned int whence)
{
extern off_t sys_lseek (unsigned int fd, off_t offset, unsigned int origin);
@@ -2814,190 +2979,448 @@
return sys_lseek(fd, offset, whence);
}

-#ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */
+extern asmlinkage long sys_getgroups (int gidsetsize, gid_t *grouplist);

-/* In order to reduce some races, while at the same time doing additional
- * checking and hopefully speeding things up, we copy filenames to the
- * kernel data space before using them..
- *
- * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
- */
-static inline int
-do_getname32(const char *filename, char *page)
+asmlinkage long
+sys32_getgroups16 (int gidsetsize, short *grouplist)
{
- int retval;
+ mm_segment_t old_fs = get_fs();
+ gid_t gl[NGROUPS];
+ int ret, i;

- /* 32bit pointer will be always far below TASK_SIZE :)) */
- retval = strncpy_from_user((char *)page, (char *)filename, PAGE_SIZE);
- if (retval > 0) {
- if (retval < PAGE_SIZE)
- return 0;
- return -ENAMETOOLONG;
- } else if (!retval)
- retval = -ENOENT;
- return retval;
+ set_fs(KERNEL_DS);
+ ret = sys_getgroups(gidsetsize, gl);
+ set_fs(old_fs);
+
+ if (gidsetsize && ret > 0 && ret <= NGROUPS)
+ for (i = 0; i < ret; i++, grouplist++)
+ if (put_user(gl[i], grouplist))
+ return -EFAULT;
+ return ret;
}

-char *
-getname32(const char *filename)
-{
- char *tmp, *result;
+extern asmlinkage long sys_setgroups (int gidsetsize, gid_t *grouplist);

- result = ERR_PTR(-ENOMEM);
- tmp = (char *)__get_free_page(GFP_KERNEL);
- if (tmp) {
- int retval = do_getname32(filename, tmp);
+asmlinkage long
+sys32_setgroups16 (int gidsetsize, short *grouplist)
+{
+ mm_segment_t old_fs = get_fs();
+ gid_t gl[NGROUPS];
+ int ret, i;

- result = tmp;
- if (retval < 0) {
- putname(tmp);
- result = ERR_PTR(retval);
- }
- }
- return result;
+ if ((unsigned) gidsetsize > NGROUPS)
+ return -EINVAL;
+ for (i = 0; i < gidsetsize; i++, grouplist++)
+ if (get_user(gl[i], grouplist))
+ return -EFAULT;
+ set_fs(KERNEL_DS);
+ ret = sys_setgroups(gidsetsize, gl);
+ set_fs(old_fs);
+ return ret;
}

-/* 32-bit timeval and related flotsam. */
-
-extern asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
+/*
+ * Unfortunately, the x86 compiler aligns variables of type "long long" to a 4 byte boundary
+ * only, which means that the x86 version of "struct flock64" doesn't match the ia64 version
+ * of struct flock.
+ */

-asmlinkage long
-sys32_ioperm(u32 from, u32 num, int on)
+static inline long
+ia32_put_flock (struct flock *l, unsigned long addr)
{
- return sys_ioperm((unsigned long)from, (unsigned long)num, on);
+ return (put_user(l->l_type, (short *) addr)
+ | put_user(l->l_whence, (short *) (addr + 2))
+ | put_user(l->l_start, (long *) (addr + 4))
+ | put_user(l->l_len, (long *) (addr + 12))
+ | put_user(l->l_pid, (int *) (addr + 20)));
}

-struct dqblk32 {
- __u32 dqb_bhardlimit;
- __u32 dqb_bsoftlimit;
- __u32 dqb_curblocks;
- __u32 dqb_ihardlimit;
- __u32 dqb_isoftlimit;
- __u32 dqb_curinodes;
- __kernel_time_t32 dqb_btime;
- __kernel_time_t32 dqb_itime;
-};
-
-extern asmlinkage long sys_quotactl(int cmd, const char *special, int id,
- caddr_t addr);
+static inline long
+ia32_get_flock (struct flock *l, unsigned long addr)
+{
+ unsigned int start_lo, start_hi, len_lo, len_hi;
+ int err = (get_user(l->l_type, (short *) addr)
+ | get_user(l->l_whence, (short *) (addr + 2))
+ | get_user(start_lo, (int *) (addr + 4))
+ | get_user(start_hi, (int *) (addr + 8))
+ | get_user(len_lo, (int *) (addr + 12))
+ | get_user(len_hi, (int *) (addr + 16))
+ | get_user(l->l_pid, (int *) (addr + 20)));
+ l->l_start = ((unsigned long) start_hi << 32) | start_lo;
+ l->l_len = ((unsigned long) len_hi << 32) | len_lo;
+ return err;
+}

asmlinkage long
-sys32_quotactl(int cmd, const char *special, int id, unsigned long addr)
+sys32_fcntl64 (unsigned int fd, unsigned int cmd, unsigned int arg)
{
- int cmds = cmd >> SUBCMDSHIFT;
- int err;
- struct dqblk d;
mm_segment_t old_fs;
- char *spec;
+ struct flock f;
+ long ret;

- switch (cmds) {
- case Q_GETQUOTA:
- break;
- case Q_SETQUOTA:
- case Q_SETUSE:
- case Q_SETQLIM:
- if (copy_from_user (&d, (struct dqblk32 *)addr,
- sizeof (struct dqblk32)))
+ switch (cmd) {
+ case F_GETLK64:
+ case F_SETLK64:
+ case F_SETLKW64:
+ if (ia32_get_flock(&f, arg))
return -EFAULT;
- d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
- d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
- break;
- default:
- return sys_quotactl(cmd, special,
- id, (caddr_t)addr);
- }
- spec = getname32 (special);
- err = PTR_ERR(spec);
- if (IS_ERR(spec)) return err;
- old_fs = get_fs ();
- set_fs (KERNEL_DS);
- err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
- set_fs (old_fs);
- putname (spec);
- if (cmds = Q_GETQUOTA) {
- __kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
- ((struct dqblk32 *)&d)->dqb_itime = i;
- ((struct dqblk32 *)&d)->dqb_btime = b;
- if (copy_to_user ((struct dqblk32 *)addr, &d,
- sizeof (struct dqblk32)))
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_fcntl(fd, cmd, (unsigned long) &f);
+ set_fs(old_fs);
+ if (cmd = F_GETLK && ia32_put_flock(&f, arg))
return -EFAULT;
+ break;
+
+ default:
+ ret = sys32_fcntl(fd, cmd, arg);
+ break;
}
- return err;
+ return ret;
}

-extern asmlinkage long sys_utime(char * filename, struct utimbuf * times);
+asmlinkage long
+sys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi)
+{
+ extern asmlinkage long sys_truncate (const char *path, unsigned long length);

-struct utimbuf32 {
- __kernel_time_t32 actime, modtime;
-};
+ return sys_truncate((const char *) A(path), ((unsigned long) len_hi << 32) | len_lo);
+}

asmlinkage long
-sys32_utime(char * filename, struct utimbuf32 *times)
+sys32_ftruncate64 (int fd, unsigned int len_lo, unsigned int len_hi)
{
- struct utimbuf t;
- mm_segment_t old_fs;
- int ret;
- char *filenam;
+ extern asmlinkage long sys_ftruncate (int fd, unsigned long length);

- if (!times)
- return sys_utime(filename, NULL);
- if (get_user (t.actime, &times->actime) ||
- __get_user (t.modtime, &times->modtime))
- return -EFAULT;
- filenam = getname32 (filename);
- ret = PTR_ERR(filenam);
- if (!IS_ERR(filenam)) {
- old_fs = get_fs();
- set_fs (KERNEL_DS);
- ret = sys_utime(filenam, &t);
- set_fs (old_fs);
- putname (filenam);
- }
- return ret;
+ return sys_ftruncate(fd, ((unsigned long) len_hi << 32) | len_lo);
}

-/*
- * Ooo, nasty. We need here to frob 32-bit unsigned longs to
- * 64-bit unsigned longs.
- */
-
-static inline int
-get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
+static int
+putstat64 (struct stat64 *ubuf, struct stat *kbuf)
{
- if (ufdset) {
- unsigned long odd;
+ int err;

- if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
- return -EFAULT;
+ if (clear_user(ubuf, sizeof(*ubuf)))
+ return 1;

- odd = n & 1UL;
- n &= ~1UL;
- while (n) {
- unsigned long h, l;
- __get_user(l, ufdset);
- __get_user(h, ufdset+1);
- ufdset += 2;
- *fdset++ = h << 32 | l;
- n -= 2;
- }
- if (odd)
- __get_user(*fdset, ufdset);
- } else {
- /* Tricky, must clear full unsigned long in the
- * kernel fdset at the end, this makes sure that
- * actually happens.
- */
- memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
- }
- return 0;
+ err = __put_user(kbuf->st_dev, &ubuf->st_dev);
+ err |= __put_user(kbuf->st_ino, &ubuf->__st_ino);
+ err |= __put_user(kbuf->st_ino, &ubuf->st_ino_lo);
+ err |= __put_user(kbuf->st_ino >> 32, &ubuf->st_ino_hi);
+ err |= __put_user(kbuf->st_mode, &ubuf->st_mode);
+ err |= __put_user(kbuf->st_nlink, &ubuf->st_nlink);
+ err |= __put_user(kbuf->st_uid, &ubuf->st_uid);
+ err |= __put_user(kbuf->st_gid, &ubuf->st_gid);
+ err |= __put_user(kbuf->st_rdev, &ubuf->st_rdev);
+ err |= __put_user(kbuf->st_size, &ubuf->st_size_lo);
+ err |= __put_user((kbuf->st_size >> 32), &ubuf->st_size_hi);
+ err |= __put_user(kbuf->st_atime, &ubuf->st_atime);
+ err |= __put_user(kbuf->st_mtime, &ubuf->st_mtime);
+ err |= __put_user(kbuf->st_ctime, &ubuf->st_ctime);
+ err |= __put_user(kbuf->st_blksize, &ubuf->st_blksize);
+ err |= __put_user(kbuf->st_blocks, &ubuf->st_blocks);
+ return err;
}

-static inline void
-set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
+asmlinkage long
+sys32_stat64 (char *filename, struct stat64 *statbuf)
{
- unsigned long odd;
-
- if (!ufdset)
+ mm_segment_t old_fs = get_fs();
+ struct stat s;
+ long ret;
+
+ set_fs(KERNEL_DS);
+ ret = sys_newstat(filename, &s);
+ set_fs(old_fs);
+ if (putstat64(statbuf, &s))
+ return -EFAULT;
+ return ret;
+}
+
+asmlinkage long
+sys32_lstat64 (char *filename, struct stat64 *statbuf)
+{
+ mm_segment_t old_fs = get_fs();
+ struct stat s;
+ long ret;
+
+ set_fs(KERNEL_DS);
+ ret = sys_newlstat(filename, &s);
+ set_fs(old_fs);
+ if (putstat64(statbuf, &s))
+ return -EFAULT;
+ return ret;
+}
+
+asmlinkage long
+sys32_fstat64 (unsigned int fd, struct stat64 *statbuf)
+{
+ mm_segment_t old_fs = get_fs();
+ struct stat s;
+ long ret;
+
+ set_fs(KERNEL_DS);
+ ret = sys_newfstat(fd, &s);
+ set_fs(old_fs);
+ if (putstat64(statbuf, &s))
+ return -EFAULT;
+ return ret;
+}
+
+asmlinkage long
+sys32_sigpending (unsigned int *set)
+{
+ return do_sigpending(set, sizeof(*set));
+}
+
+struct sysinfo32 {
+ s32 uptime;
+ u32 loads[3];
+ u32 totalram;
+ u32 freeram;
+ u32 sharedram;
+ u32 bufferram;
+ u32 totalswap;
+ u32 freeswap;
+ unsigned short procs;
+ char _f[22];
+};
+
+asmlinkage long
+sys32_sysinfo (struct sysinfo32 *info)
+{
+ extern asmlinkage long sys_sysinfo (struct sysinfo *);
+ mm_segment_t old_fs = get_fs();
+ struct sysinfo s;
+ long ret, err;
+
+ set_fs(KERNEL_DS);
+ ret = sys_sysinfo(&s);
+ set_fs(old_fs);
+
+ if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
+ return -EFAULT;
+
+ err = __put_user(s.uptime, &info->uptime);
+ err |= __put_user(s.loads[0], &info->loads[0]);
+ err |= __put_user(s.loads[1], &info->loads[1]);
+ err |= __put_user(s.loads[2], &info->loads[2]);
+ err |= __put_user(s.totalram, &info->totalram);
+ err |= __put_user(s.freeram, &info->freeram);
+ err |= __put_user(s.sharedram, &info->sharedram);
+ err |= __put_user(s.bufferram, &info->bufferram);
+ err |= __put_user(s.totalswap, &info->totalswap);
+ err |= __put_user(s.freeswap, &info->freeswap);
+ err |= __put_user(s.procs, &info->procs);
+ if (err)
+ return -EFAULT;
+ return ret;
+}
+
+/* In order to reduce some races, while at the same time doing additional
+ * checking and hopefully speeding things up, we copy filenames to the
+ * kernel data space before using them..
+ *
+ * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
+ */
+static inline int
+do_getname32 (const char *filename, char *page)
+{
+ int retval;
+
+ /* 32bit pointer will be always far below TASK_SIZE :)) */
+ retval = strncpy_from_user((char *)page, (char *)filename, PAGE_SIZE);
+ if (retval > 0) {
+ if (retval < PAGE_SIZE)
+ return 0;
+ return -ENAMETOOLONG;
+ } else if (!retval)
+ retval = -ENOENT;
+ return retval;
+}
+
+static char *
+getname32 (const char *filename)
+{
+ char *tmp, *result;
+
+ result = ERR_PTR(-ENOMEM);
+ tmp = (char *)__get_free_page(GFP_KERNEL);
+ if (tmp) {
+ int retval = do_getname32(filename, tmp);
+
+ result = tmp;
+ if (retval < 0) {
+ putname(tmp);
+ result = ERR_PTR(retval);
+ }
+ }
+ return result;
+}
+
+struct dqblk32 {
+ __u32 dqb_bhardlimit;
+ __u32 dqb_bsoftlimit;
+ __u32 dqb_curblocks;
+ __u32 dqb_ihardlimit;
+ __u32 dqb_isoftlimit;
+ __u32 dqb_curinodes;
+ __kernel_time_t32 dqb_btime;
+ __kernel_time_t32 dqb_itime;
+};
+
+asmlinkage long
+sys32_quotactl (int cmd, unsigned int special, int id, struct dqblk32 *addr)
+{
+ extern asmlinkage long sys_quotactl (int, const char *, int, caddr_t);
+ int cmds = cmd >> SUBCMDSHIFT;
+ mm_segment_t old_fs;
+ struct dqblk d;
+ char *spec;
+ long err;
+
+ switch (cmds) {
+ case Q_GETQUOTA:
+ break;
+ case Q_SETQUOTA:
+ case Q_SETUSE:
+ case Q_SETQLIM:
+ if (copy_from_user (&d, addr, sizeof(struct dqblk32)))
+ return -EFAULT;
+ d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
+ d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
+ break;
+ default:
+ return sys_quotactl(cmd, (void *) A(special), id, (caddr_t) addr);
+ }
+ spec = getname32((void *) A(special));
+ err = PTR_ERR(spec);
+ if (IS_ERR(spec))
+ return err;
+ old_fs = get_fs ();
+ set_fs(KERNEL_DS);
+ err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
+ set_fs(old_fs);
+ putname(spec);
+ if (cmds = Q_GETQUOTA) {
+ __kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
+ ((struct dqblk32 *)&d)->dqb_itime = i;
+ ((struct dqblk32 *)&d)->dqb_btime = b;
+ if (copy_to_user(addr, &d, sizeof(struct dqblk32)))
+ return -EFAULT;
+ }
+ return err;
+}
+
+asmlinkage long
+sys32_sched_rr_get_interval (pid_t pid, struct timespec32 *interval)
+{
+ extern asmlinkage long sys_sched_rr_get_interval (pid_t, struct timespec *);
+ mm_segment_t old_fs = get_fs();
+ struct timespec t;
+ long ret;
+
+ set_fs(KERNEL_DS);
+ ret = sys_sched_rr_get_interval(pid, &t);
+ set_fs(old_fs);
+ if (put_user (t.tv_sec, &interval->tv_sec) || put_user (t.tv_nsec, &interval->tv_nsec))
+ return -EFAULT;
+ return ret;
+}
+
+asmlinkage long
+sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
+{
+ extern asmlinkage long sys_pread (unsigned int, char *, size_t, loff_t);
+ return sys_pread(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
+}
+
+asmlinkage long
+sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
+{
+ extern asmlinkage long sys_pwrite (unsigned int, const char *, size_t, loff_t);
+ return sys_pwrite(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
+}
+
+asmlinkage long
+sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count)
+{
+ extern asmlinkage long sys_sendfile (int, int, off_t *, size_t);
+ mm_segment_t old_fs = get_fs();
+ long ret;
+ off_t of;
+
+ if (offset && get_user(of, offset))
+ return -EFAULT;
+
+ set_fs(KERNEL_DS);
+ ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+ set_fs(old_fs);
+
+ if (!ret && offset && put_user(of, offset))
+ return -EFAULT;
+
+ return ret;
+}
+
+asmlinkage long
+sys32_personality (unsigned int personality)
+{
+ extern asmlinkage long sys_personality (unsigned long);
+ long ret;
+
+ if (current->personality = PER_LINUX32 && personality = PER_LINUX)
+ personality = PER_LINUX32;
+ ret = sys_personality(personality);
+ if (ret = PER_LINUX32)
+ ret = PER_LINUX;
+ return ret;
+}
+
+#ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */
+
+/*
+ * Ooo, nasty. We need here to frob 32-bit unsigned longs to
+ * 64-bit unsigned longs.
+ */
+
+static inline int
+get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
+{
+ if (ufdset) {
+ unsigned long odd;
+
+ if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
+ return -EFAULT;
+
+ odd = n & 1UL;
+ n &= ~1UL;
+ while (n) {
+ unsigned long h, l;
+ __get_user(l, ufdset);
+ __get_user(h, ufdset+1);
+ ufdset += 2;
+ *fdset++ = h << 32 | l;
+ n -= 2;
+ }
+ if (odd)
+ __get_user(*fdset, ufdset);
+ } else {
+ /* Tricky, must clear full unsigned long in the
+ * kernel fdset at the end, this makes sure that
+ * actually happens.
+ */
+ memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
+ }
+ return 0;
+}
+
+static inline void
+set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
+{
+ unsigned long odd;
+
+ if (!ufdset)
return;

odd = n & 1UL;
@@ -3015,20 +3438,11 @@
__put_user(*fdset, ufdset);
}

-extern asmlinkage long sys_sysfs(int option, unsigned long arg1,
- unsigned long arg2);
-
-asmlinkage long
-sys32_sysfs(int option, u32 arg1, u32 arg2)
-{
- return sys_sysfs(option, arg1, arg2);
-}
-
struct ncp_mount_data32 {
int version;
unsigned int ncp_fd;
__kernel_uid_t32 mounted_uid;
- __kernel_pid_t32 wdog_pid;
+ int wdog_pid;
unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
unsigned int time_out;
unsigned int retry_count;
@@ -3175,269 +3589,7 @@
}
}

-struct sysinfo32 {
- s32 uptime;
- u32 loads[3];
- u32 totalram;
- u32 freeram;
- u32 sharedram;
- u32 bufferram;
- u32 totalswap;
- u32 freeswap;
- unsigned short procs;
- char _f[22];
-};
-
-extern asmlinkage long sys_sysinfo(struct sysinfo *info);
-
-asmlinkage long
-sys32_sysinfo(struct sysinfo32 *info)
-{
- struct sysinfo s;
- int ret, err;
- mm_segment_t old_fs = get_fs ();
-
- set_fs (KERNEL_DS);
- ret = sys_sysinfo(&s);
- set_fs (old_fs);
- err = put_user (s.uptime, &info->uptime);
- err |= __put_user (s.loads[0], &info->loads[0]);
- err |= __put_user (s.loads[1], &info->loads[1]);
- err |= __put_user (s.loads[2], &info->loads[2]);
- err |= __put_user (s.totalram, &info->totalram);
- err |= __put_user (s.freeram, &info->freeram);
- err |= __put_user (s.sharedram, &info->sharedram);
- err |= __put_user (s.bufferram, &info->bufferram);
- err |= __put_user (s.totalswap, &info->totalswap);
- err |= __put_user (s.freeswap, &info->freeswap);
- err |= __put_user (s.procs, &info->procs);
- if (err)
- return -EFAULT;
- return ret;
-}
-
-extern asmlinkage long sys_sched_rr_get_interval(pid_t pid,
- struct timespec *interval);
-
-asmlinkage long
-sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
-{
- struct timespec t;
- int ret;
- mm_segment_t old_fs = get_fs ();
-
- set_fs (KERNEL_DS);
- ret = sys_sched_rr_get_interval(pid, &t);
- set_fs (old_fs);
- if (put_user (t.tv_sec, &interval->tv_sec) ||
- __put_user (t.tv_nsec, &interval->tv_nsec))
- return -EFAULT;
- return ret;
-}
-
-extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set,
- old_sigset_t *oset);
-
-asmlinkage long
-sys32_sigprocmask(int how, old_sigset_t32 *set, old_sigset_t32 *oset)
-{
- old_sigset_t s;
- int ret;
- mm_segment_t old_fs = get_fs();
-
- if (set && get_user (s, set)) return -EFAULT;
- set_fs (KERNEL_DS);
- ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
- set_fs (old_fs);
- if (ret) return ret;
- if (oset && put_user (s, oset)) return -EFAULT;
- return 0;
-}
-
-extern asmlinkage long sys_sigpending(old_sigset_t *set);
-
-asmlinkage long
-sys32_sigpending(old_sigset_t32 *set)
-{
- old_sigset_t s;
- int ret;
- mm_segment_t old_fs = get_fs();
-
- set_fs (KERNEL_DS);
- ret = sys_sigpending(&s);
- set_fs (old_fs);
- if (put_user (s, set)) return -EFAULT;
- return ret;
-}
-
-extern asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
-
-asmlinkage long
-sys32_rt_sigpending(sigset_t32 *set, __kernel_size_t32 sigsetsize)
-{
- sigset_t s;
- sigset_t32 s32;
- int ret;
- mm_segment_t old_fs = get_fs();
-
- set_fs (KERNEL_DS);
- ret = sys_rt_sigpending(&s, sigsetsize);
- set_fs (old_fs);
- if (!ret) {
- switch (_NSIG_WORDS) {
- case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
- case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
- case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
- case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
- }
- if (copy_to_user (set, &s32, sizeof(sigset_t32)))
- return -EFAULT;
- }
- return ret;
-}
-
-siginfo_t32 *
-siginfo64to32(siginfo_t32 *d, siginfo_t *s)
-{
- memset(d, 0, sizeof(siginfo_t32));
- d->si_signo = s->si_signo;
- d->si_errno = s->si_errno;
- d->si_code = s->si_code;
- if (s->si_signo >= SIGRTMIN) {
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- /* XXX: Ouch, how to find this out??? */
- d->si_int = s->si_int;
- } else switch (s->si_signo) {
- /* XXX: What about POSIX1.b timers */
- case SIGCHLD:
- d->si_pid = s->si_pid;
- d->si_status = s->si_status;
- d->si_utime = s->si_utime;
- d->si_stime = s->si_stime;
- break;
- case SIGSEGV:
- case SIGBUS:
- case SIGFPE:
- case SIGILL:
- d->si_addr = (long)(s->si_addr);
- /* XXX: Do we need to translate this from ia64 to ia32 traps? */
- d->si_trapno = s->si_trapno;
- break;
- case SIGPOLL:
- d->si_band = s->si_band;
- d->si_fd = s->si_fd;
- break;
- default:
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- break;
- }
- return d;
-}
-
-siginfo_t *
-siginfo32to64(siginfo_t *d, siginfo_t32 *s)
-{
- d->si_signo = s->si_signo;
- d->si_errno = s->si_errno;
- d->si_code = s->si_code;
- if (s->si_signo >= SIGRTMIN) {
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- /* XXX: Ouch, how to find this out??? */
- d->si_int = s->si_int;
- } else switch (s->si_signo) {
- /* XXX: What about POSIX1.b timers */
- case SIGCHLD:
- d->si_pid = s->si_pid;
- d->si_status = s->si_status;
- d->si_utime = s->si_utime;
- d->si_stime = s->si_stime;
- break;
- case SIGSEGV:
- case SIGBUS:
- case SIGFPE:
- case SIGILL:
- d->si_addr = (void *)A(s->si_addr);
- /* XXX: Do we need to translate this from ia32 to ia64 traps? */
- d->si_trapno = s->si_trapno;
- break;
- case SIGPOLL:
- d->si_band = s->si_band;
- d->si_fd = s->si_fd;
- break;
- default:
- d->si_pid = s->si_pid;
- d->si_uid = s->si_uid;
- break;
- }
- return d;
-}
-
-extern asmlinkage long
-sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
- const struct timespec *uts, size_t sigsetsize);
-
-asmlinkage long
-sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
- struct timespec32 *uts, __kernel_size_t32 sigsetsize)
-{
- sigset_t s;
- sigset_t32 s32;
- struct timespec t;
- int ret;
- mm_segment_t old_fs = get_fs();
- siginfo_t info;
- siginfo_t32 info32;
-
- if (copy_from_user (&s32, uthese, sizeof(sigset_t32)))
- return -EFAULT;
- switch (_NSIG_WORDS) {
- case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
- case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
- case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
- case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
- }
- if (uts) {
- ret = get_user (t.tv_sec, &uts->tv_sec);
- ret |= __get_user (t.tv_nsec, &uts->tv_nsec);
- if (ret)
- return -EFAULT;
- }
- set_fs (KERNEL_DS);
- ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
- set_fs (old_fs);
- if (ret >= 0 && uinfo) {
- if (copy_to_user (uinfo, siginfo64to32(&info32, &info),
- sizeof(siginfo_t32)))
- return -EFAULT;
- }
- return ret;
-}
-
-extern asmlinkage long
-sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
-
-asmlinkage long
-sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
-{
- siginfo_t info;
- siginfo_t32 info32;
- int ret;
- mm_segment_t old_fs = get_fs();
-
- if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32)))
- return -EFAULT;
- /* XXX: Is this correct? */
- siginfo32to64(&info, &info32);
- set_fs (KERNEL_DS);
- ret = sys_rt_sigqueueinfo(pid, sig, &info);
- set_fs (old_fs);
- return ret;
-}
-
-extern asmlinkage long sys_setreuid(uid_t ruid, uid_t euid);
+extern asmlinkage long sys_setreuid(uid_t ruid, uid_t euid);

asmlinkage long sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid)
{
@@ -3462,24 +3614,6 @@
return sys_setresuid(sruid, seuid, ssuid);
}

-extern asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
-
-asmlinkage long
-sys32_getresuid(__kernel_uid_t32 *ruid, __kernel_uid_t32 *euid,
- __kernel_uid_t32 *suid)
-{
- uid_t a, b, c;
- int ret;
- mm_segment_t old_fs = get_fs();
-
- set_fs (KERNEL_DS);
- ret = sys_getresuid(&a, &b, &c);
- set_fs (old_fs);
- if (put_user (a, ruid) || put_user (b, euid) || put_user (c, suid))
- return -EFAULT;
- return ret;
-}
-
extern asmlinkage long sys_setregid(gid_t rgid, gid_t egid);

asmlinkage long
@@ -3506,46 +3640,6 @@
return sys_setresgid(srgid, segid, ssgid);
}

-extern asmlinkage long sys_getgroups(int gidsetsize, gid_t *grouplist);
-
-asmlinkage long
-sys32_getgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
-{
- gid_t gl[NGROUPS];
- int ret, i;
- mm_segment_t old_fs = get_fs ();
-
- set_fs (KERNEL_DS);
- ret = sys_getgroups(gidsetsize, gl);
- set_fs (old_fs);
- if (gidsetsize && ret > 0 && ret <= NGROUPS)
- for (i = 0; i < ret; i++, grouplist++)
- if (__put_user (gl[i], grouplist))
- return -EFAULT;
- return ret;
-}
-
-extern asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist);
-
-asmlinkage long
-sys32_setgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
-{
- gid_t gl[NGROUPS];
- int ret, i;
- mm_segment_t old_fs = get_fs ();
-
- if ((unsigned) gidsetsize > NGROUPS)
- return -EINVAL;
- for (i = 0; i < gidsetsize; i++, grouplist++)
- if (__get_user (gl[i], grouplist))
- return -EFAULT;
- set_fs (KERNEL_DS);
- ret = sys_setgroups(gidsetsize, gl);
- set_fs (old_fs);
- return ret;
-}
-
-
/* XXX These as well... */
extern __inline__ struct socket *
socki_lookup(struct inode *inode)
@@ -3947,601 +4041,165 @@
kcmsg32->cmsg_len = clen32;

ucmsg = (struct cmsghdr *) (((char *)ucmsg) +
- CMSG_ALIGN(clen64));
- wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
- }
-
- /* Copy back fixed up data, and adjust pointers. */
- bufsz = (wp - workbuf);
- copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
-
- kmsg->msg_control = (struct cmsghdr *)
- (((char *)orig_cmsg_uptr) + bufsz);
- kmsg->msg_controllen = space_avail - bufsz;
-
- kfree(workbuf);
- return;
-
-fail:
- /* If we leave the 64-bit format CMSG chunks in there,
- * the application could get confused and crash. So to
- * ensure greater recovery, we report no CMSGs.
- */
- kmsg->msg_controllen += bufsz;
- kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-asmlinkage long
-sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
-{
- struct socket *sock;
- char address[MAX_SOCK_ADDR];
- struct iovec iov[UIO_FASTIOV];
- unsigned char ctl[sizeof(struct cmsghdr) + 20];
- unsigned char *ctl_buf = ctl;
- struct msghdr kern_msg;
- int err, total_len;
-
- if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
- return -EFAULT;
- if(kern_msg.msg_iovlen > UIO_MAXIOV)
- return -EINVAL;
- err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
- if (err < 0)
- goto out;
- total_len = err;
-
- if(kern_msg.msg_controllen) {
- err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
- if(err)
- goto out_freeiov;
- ctl_buf = kern_msg.msg_control;
- }
- kern_msg.msg_flags = user_flags;
-
- sock = sockfd_lookup(fd, &err);
- if (sock != NULL) {
- if (sock->file->f_flags & O_NONBLOCK)
- kern_msg.msg_flags |= MSG_DONTWAIT;
- err = sock_sendmsg(sock, &kern_msg, total_len);
- sockfd_put(sock);
- }
-
- /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
- if(ctl_buf != ctl)
- kfree(ctl_buf);
-out_freeiov:
- if(kern_msg.msg_iov != iov)
- kfree(kern_msg.msg_iov);
-out:
- return err;
-}
-
-asmlinkage long
-sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
-{
- struct iovec iovstack[UIO_FASTIOV];
- struct msghdr kern_msg;
- char addr[MAX_SOCK_ADDR];
- struct socket *sock;
- struct iovec *iov = iovstack;
- struct sockaddr *uaddr;
- int *uaddr_len;
- unsigned long cmsg_ptr;
- int err, total_len, len = 0;
-
- if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
- return -EFAULT;
- if(kern_msg.msg_iovlen > UIO_MAXIOV)
- return -EINVAL;
-
- uaddr = kern_msg.msg_name;
- uaddr_len = &user_msg->msg_namelen;
- err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
- if (err < 0)
- goto out;
- total_len = err;
-
- cmsg_ptr = (unsigned long) kern_msg.msg_control;
- kern_msg.msg_flags = 0;
-
- sock = sockfd_lookup(fd, &err);
- if (sock != NULL) {
- struct scm_cookie scm;
-
- if (sock->file->f_flags & O_NONBLOCK)
- user_flags |= MSG_DONTWAIT;
- memset(&scm, 0, sizeof(scm));
- lock_kernel();
- err = sock->ops->recvmsg(sock, &kern_msg, total_len,
- user_flags, &scm);
- if(err >= 0) {
- len = err;
- if(!kern_msg.msg_control) {
- if(sock->passcred || scm.fp)
- kern_msg.msg_flags |= MSG_CTRUNC;
- if(scm.fp)
- __scm_destroy(&scm);
- } else {
- /* If recvmsg processing itself placed some
- * control messages into user space, it's is
- * using 64-bit CMSG processing, so we need
- * to fix it up before we tack on more stuff.
- */
- if((unsigned long) kern_msg.msg_control
- != cmsg_ptr)
- cmsg32_recvmsg_fixup(&kern_msg,
- cmsg_ptr);
-
- /* Wheee... */
- if(sock->passcred)
- put_cmsg32(&kern_msg,
- SOL_SOCKET, SCM_CREDENTIALS,
- sizeof(scm.creds),
- &scm.creds);
- if(scm.fp != NULL)
- scm_detach_fds32(&kern_msg, &scm);
- }
- }
- unlock_kernel();
- sockfd_put(sock);
- }
-
- if(uaddr != NULL && err >= 0)
- err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr,
- uaddr_len);
- if(cmsg_ptr != 0 && err >= 0) {
- unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
- __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr
- - cmsg_ptr);
- err |= __put_user(uclen, &user_msg->msg_controllen);
- }
- if(err >= 0)
- err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
- if(kern_msg.msg_iov != iov)
- kfree(kern_msg.msg_iov);
-out:
- if(err < 0)
- return err;
- return len;
-}
-
-extern void check_pending(int signum);
-
-#ifdef CONFIG_MODULES
-
-extern asmlinkage unsigned long sys_create_module(const char *name_user,
- size_t size);
-
-asmlinkage unsigned long
-sys32_create_module(const char *name_user, __kernel_size_t32 size)
-{
- return sys_create_module(name_user, (size_t)size);
-}
-
-extern asmlinkage long sys_init_module(const char *name_user,
- struct module *mod_user);
-
-/* Hey, when you're trying to init module, take time and prepare us a nice 64bit
- * module structure, even if from 32bit modutils... Why to pollute kernel... :))
- */
-asmlinkage long
-sys32_init_module(const char *name_user, struct module *mod_user)
-{
- return sys_init_module(name_user, mod_user);
-}
-
-extern asmlinkage long sys_delete_module(const char *name_user);
-
-asmlinkage long
-sys32_delete_module(const char *name_user)
-{
- return sys_delete_module(name_user);
-}
-
-struct module_info32 {
- u32 addr;
- u32 size;
- u32 flags;
- s32 usecount;
-};
-
-/* Query various bits about modules. */
-
-static inline long
-get_mod_name(const char *user_name, char **buf)
-{
- unsigned long page;
- long retval;
-
- if ((unsigned long)user_name >= TASK_SIZE
- && !segment_eq(get_fs (), KERNEL_DS))
- return -EFAULT;
-
- page = __get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
- if (retval > 0) {
- if (retval < PAGE_SIZE) {
- *buf = (char *)page;
- return retval;
- }
- retval = -ENAMETOOLONG;
- } else if (!retval)
- retval = -EINVAL;
-
- free_page(page);
- return retval;
-}
-
-static inline void
-put_mod_name(char *buf)
-{
- free_page((unsigned long)buf);
-}
-
-static __inline__ struct module *
-find_module(const char *name)
-{
- struct module *mod;
-
- for (mod = module_list; mod ; mod = mod->next) {
- if (mod->flags & MOD_DELETED)
- continue;
- if (!strcmp(mod->name, name))
- break;
- }
-
- return mod;
-}
-
-static int
-qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
-{
- struct module *mod;
- size_t nmod, space, len;
-
- nmod = space = 0;
-
- for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
- len = strlen(mod->name)+1;
- if (len > bufsize)
- goto calc_space_needed;
- if (copy_to_user(buf, mod->name, len))
- return -EFAULT;
- buf += len;
- bufsize -= len;
- space += len;
- }
-
- if (put_user(nmod, ret))
- return -EFAULT;
- else
- return 0;
-
-calc_space_needed:
- space += len;
- while ((mod = mod->next)->next != NULL)
- space += strlen(mod->name)+1;
-
- if (put_user(space, ret))
- return -EFAULT;
- else
- return -ENOSPC;
-}
-
-static int
-qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
-{
- size_t i, space, len;
-
- if (mod->next = NULL)
- return -EINVAL;
- if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
- if (put_user(0, ret))
- return -EFAULT;
- else
- return 0;
-
- space = 0;
- for (i = 0; i < mod->ndeps; ++i) {
- const char *dep_name = mod->deps[i].dep->name;
-
- len = strlen(dep_name)+1;
- if (len > bufsize)
- goto calc_space_needed;
- if (copy_to_user(buf, dep_name, len))
- return -EFAULT;
- buf += len;
- bufsize -= len;
- space += len;
- }
-
- if (put_user(i, ret))
- return -EFAULT;
- else
- return 0;
-
-calc_space_needed:
- space += len;
- while (++i < mod->ndeps)
- space += strlen(mod->deps[i].dep->name)+1;
-
- if (put_user(space, ret))
- return -EFAULT;
- else
- return -ENOSPC;
-}
-
-static int
-qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
-{
- size_t nrefs, space, len;
- struct module_ref *ref;
-
- if (mod->next = NULL)
- return -EINVAL;
- if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
- if (put_user(0, ret))
- return -EFAULT;
- else
- return 0;
-
- space = 0;
- for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
- const char *ref_name = ref->ref->name;
-
- len = strlen(ref_name)+1;
- if (len > bufsize)
- goto calc_space_needed;
- if (copy_to_user(buf, ref_name, len))
- return -EFAULT;
- buf += len;
- bufsize -= len;
- space += len;
- }
-
- if (put_user(nrefs, ret))
- return -EFAULT;
- else
- return 0;
-
-calc_space_needed:
- space += len;
- while ((ref = ref->next_ref) != NULL)
- space += strlen(ref->ref->name)+1;
-
- if (put_user(space, ret))
- return -EFAULT;
- else
- return -ENOSPC;
-}
-
-static inline int
-qm_symbols(struct module *mod, char *buf, size_t bufsize,
- __kernel_size_t32 *ret)
-{
- size_t i, space, len;
- struct module_symbol *s;
- char *strings;
- unsigned *vals;
-
- if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
- if (put_user(0, ret))
- return -EFAULT;
- else
- return 0;
-
- space = mod->nsyms * 2*sizeof(u32);
-
- i = len = 0;
- s = mod->syms;
-
- if (space > bufsize)
- goto calc_space_needed;
-
- if (!access_ok(VERIFY_WRITE, buf, space))
- return -EFAULT;
-
- bufsize -= space;
- vals = (unsigned *)buf;
- strings = buf+space;
-
- for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
- len = strlen(s->name)+1;
- if (len > bufsize)
- goto calc_space_needed;
-
- if (copy_to_user(strings, s->name, len)
- || __put_user(s->value, vals+0)
- || __put_user(space, vals+1))
- return -EFAULT;
-
- strings += len;
- bufsize -= len;
- space += len;
- }
-
- if (put_user(i, ret))
- return -EFAULT;
- else
- return 0;
-
-calc_space_needed:
- for (; i < mod->nsyms; ++i, ++s)
- space += strlen(s->name)+1;
-
- if (put_user(space, ret))
- return -EFAULT;
- else
- return -ENOSPC;
-}
-
-static inline int
-qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
-{
- int error = 0;
-
- if (mod->next = NULL)
- return -EINVAL;
+ CMSG_ALIGN(clen64));
+ wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
+ }

- if (sizeof(struct module_info32) <= bufsize) {
- struct module_info32 info;
- info.addr = (unsigned long)mod;
- info.size = mod->size;
- info.flags = mod->flags;
- info.usecount - ((mod_member_present(mod, can_unload)
- && mod->can_unload)
- ? -1 : atomic_read(&mod->uc.usecount));
+ /* Copy back fixed up data, and adjust pointers. */
+ bufsz = (wp - workbuf);
+ copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);

- if (copy_to_user(buf, &info, sizeof(struct module_info32)))
- return -EFAULT;
- } else
- error = -ENOSPC;
+ kmsg->msg_control = (struct cmsghdr *)
+ (((char *)orig_cmsg_uptr) + bufsz);
+ kmsg->msg_controllen = space_avail - bufsz;

- if (put_user(sizeof(struct module_info32), ret))
- return -EFAULT;
+ kfree(workbuf);
+ return;

- return error;
+fail:
+ /* If we leave the 64-bit format CMSG chunks in there,
+ * the application could get confused and crash. So to
+ * ensure greater recovery, we report no CMSGs.
+ */
+ kmsg->msg_controllen += bufsz;
+ kmsg->msg_control = (void *) orig_cmsg_uptr;
}

asmlinkage long
-sys32_query_module(char *name_user, int which, char *buf,
- __kernel_size_t32 bufsize, u32 ret)
+sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
{
- struct module *mod;
- int err;
+ struct socket *sock;
+ char address[MAX_SOCK_ADDR];
+ struct iovec iov[UIO_FASTIOV];
+ unsigned char ctl[sizeof(struct cmsghdr) + 20];
+ unsigned char *ctl_buf = ctl;
+ struct msghdr kern_msg;
+ int err, total_len;

- lock_kernel();
- if (name_user = 0) {
- /* This finds "kernel_module" which is not exported. */
- for(mod = module_list; mod->next != NULL; mod = mod->next)
- ;
- } else {
- long namelen;
- char *name;
+ if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+ return -EFAULT;
+ if(kern_msg.msg_iovlen > UIO_MAXIOV)
+ return -EINVAL;
+ err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
+ if (err < 0)
+ goto out;
+ total_len = err;

- if ((namelen = get_mod_name(name_user, &name)) < 0) {
- err = namelen;
- goto out;
- }
- err = -ENOENT;
- if (namelen = 0) {
- /* This finds "kernel_module" which is not exported. */
- for(mod = module_list;
- mod->next != NULL;
- mod = mod->next) ;
- } else if ((mod = find_module(name)) = NULL) {
- put_mod_name(name);
- goto out;
- }
- put_mod_name(name);
+ if(kern_msg.msg_controllen) {
+ err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
+ if(err)
+ goto out_freeiov;
+ ctl_buf = kern_msg.msg_control;
}
+ kern_msg.msg_flags = user_flags;

- switch (which)
- {
- case 0:
- err = 0;
- break;
- case QM_MODULES:
- err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
- break;
- case QM_DEPS:
- err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
- break;
- case QM_REFS:
- err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
- break;
- case QM_SYMBOLS:
- err = qm_symbols(mod, buf, bufsize,
- (__kernel_size_t32 *)AA(ret));
- break;
- case QM_INFO:
- err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
- break;
- default:
- err = -EINVAL;
- break;
+ sock = sockfd_lookup(fd, &err);
+ if (sock != NULL) {
+ if (sock->file->f_flags & O_NONBLOCK)
+ kern_msg.msg_flags |= MSG_DONTWAIT;
+ err = sock_sendmsg(sock, &kern_msg, total_len);
+ sockfd_put(sock);
}
+
+ /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
+ if(ctl_buf != ctl)
+ kfree(ctl_buf);
+out_freeiov:
+ if(kern_msg.msg_iov != iov)
+ kfree(kern_msg.msg_iov);
out:
- unlock_kernel();
return err;
}

-struct kernel_sym32 {
- u32 value;
- char name[60];
-};
-
-extern asmlinkage long sys_get_kernel_syms(struct kernel_sym *table);
-
asmlinkage long
-sys32_get_kernel_syms(struct kernel_sym32 *table)
+sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
{
- int len, i;
- struct kernel_sym *tbl;
- mm_segment_t old_fs;
-
- len = sys_get_kernel_syms(NULL);
- if (!table) return len;
- tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
- if (!tbl) return -ENOMEM;
- old_fs = get_fs();
- set_fs (KERNEL_DS);
- sys_get_kernel_syms(tbl);
- set_fs (old_fs);
- for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) {
- if (put_user (tbl[i].value, &table->value) ||
- copy_to_user (table->name, tbl[i].name, 60))
- break;
- }
- kfree (tbl);
- return i;
-}
+ struct iovec iovstack[UIO_FASTIOV];
+ struct msghdr kern_msg;
+ char addr[MAX_SOCK_ADDR];
+ struct socket *sock;
+ struct iovec *iov = iovstack;
+ struct sockaddr *uaddr;
+ int *uaddr_len;
+ unsigned long cmsg_ptr;
+ int err, total_len, len = 0;

-#else /* CONFIG_MODULES */
+ if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+ return -EFAULT;
+ if(kern_msg.msg_iovlen > UIO_MAXIOV)
+ return -EINVAL;

-asmlinkage unsigned long
-sys32_create_module(const char *name_user, size_t size)
-{
- return -ENOSYS;
-}
+ uaddr = kern_msg.msg_name;
+ uaddr_len = &user_msg->msg_namelen;
+ err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
+ if (err < 0)
+ goto out;
+ total_len = err;

-asmlinkage long
-sys32_init_module(const char *name_user, struct module *mod_user)
-{
- return -ENOSYS;
-}
+ cmsg_ptr = (unsigned long) kern_msg.msg_control;
+ kern_msg.msg_flags = 0;

-asmlinkage long
-sys32_delete_module(const char *name_user)
-{
- return -ENOSYS;
-}
+ sock = sockfd_lookup(fd, &err);
+ if (sock != NULL) {
+ struct scm_cookie scm;

-asmlinkage long
-sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
- size_t *ret)
-{
- /* Let the program know about the new interface. Not that
- it'll do them much good. */
- if (which = 0)
- return 0;
+ if (sock->file->f_flags & O_NONBLOCK)
+ user_flags |= MSG_DONTWAIT;
+ memset(&scm, 0, sizeof(scm));
+ lock_kernel();
+ err = sock->ops->recvmsg(sock, &kern_msg, total_len,
+ user_flags, &scm);
+ if(err >= 0) {
+ len = err;
+ if(!kern_msg.msg_control) {
+ if(sock->passcred || scm.fp)
+ kern_msg.msg_flags |= MSG_CTRUNC;
+ if(scm.fp)
+ __scm_destroy(&scm);
+ } else {
+ /* If recvmsg processing itself placed some
+ * control messages into user space, it's is
+ * using 64-bit CMSG processing, so we need
+ * to fix it up before we tack on more stuff.
+ */
+ if((unsigned long) kern_msg.msg_control
+ != cmsg_ptr)
+ cmsg32_recvmsg_fixup(&kern_msg,
+ cmsg_ptr);

- return -ENOSYS;
-}
+ /* Wheee... */
+ if(sock->passcred)
+ put_cmsg32(&kern_msg,
+ SOL_SOCKET, SCM_CREDENTIALS,
+ sizeof(scm.creds),
+ &scm.creds);
+ if(scm.fp != NULL)
+ scm_detach_fds32(&kern_msg, &scm);
+ }
+ }
+ unlock_kernel();
+ sockfd_put(sock);
+ }

-asmlinkage long
-sys32_get_kernel_syms(struct kernel_sym *table)
-{
- return -ENOSYS;
+ if(uaddr != NULL && err >= 0)
+ err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr,
+ uaddr_len);
+ if(cmsg_ptr != 0 && err >= 0) {
+ unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
+ __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr
+ - cmsg_ptr);
+ err |= __put_user(uclen, &user_msg->msg_controllen);
+ }
+ if(err >= 0)
+ err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
+ if(kern_msg.msg_iov != iov)
+ kfree(kern_msg.msg_iov);
+out:
+ if(err < 0)
+ return err;
+ return len;
}

-#endif /* CONFIG_MODULES */
-
/* Stuff for NFS server syscalls... */
struct nfsctl_svc32 {
u16 svc32_port;
@@ -4821,152 +4479,12 @@
return err;
}

-asmlinkage long sys_utimes(char *, struct timeval *);
-
-asmlinkage long
-sys32_utimes(char *filename, struct timeval32 *tvs)
-{
- char *kfilename;
- struct timeval ktvs[2];
- mm_segment_t old_fs;
- int ret;
-
- kfilename = getname32(filename);
- ret = PTR_ERR(kfilename);
- if (!IS_ERR(kfilename)) {
- if (tvs) {
- if (get_tv32(&ktvs[0], tvs) ||
- get_tv32(&ktvs[1], 1+tvs))
- return -EFAULT;
- }
-
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = sys_utimes(kfilename, &ktvs[0]);
- set_fs(old_fs);
-
- putname(kfilename);
- }
- return ret;
-}
-
-/* These are here just in case some old ia32 binary calls it. */
-asmlinkage long
-sys32_pause(void)
-{
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- return -ERESTARTNOHAND;
-}
-
-/* PCI config space poking. */
-extern asmlinkage long sys_pciconfig_read(unsigned long bus,
- unsigned long dfn,
- unsigned long off,
- unsigned long len,
- unsigned char *buf);
-
-extern asmlinkage long sys_pciconfig_write(unsigned long bus,
- unsigned long dfn,
- unsigned long off,
- unsigned long len,
- unsigned char *buf);
-
-asmlinkage long
-sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
-{
- return sys_pciconfig_read((unsigned long) bus,
- (unsigned long) dfn,
- (unsigned long) off,
- (unsigned long) len,
- (unsigned char *)AA(ubuf));
-}
-
-asmlinkage long
-sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
-{
- return sys_pciconfig_write((unsigned long) bus,
- (unsigned long) dfn,
- (unsigned long) off,
- (unsigned long) len,
- (unsigned char *)AA(ubuf));
-}
-
-extern asmlinkage long sys_prctl(int option, unsigned long arg2,
- unsigned long arg3, unsigned long arg4,
- unsigned long arg5);
-
-asmlinkage long
-sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
-{
- return sys_prctl(option,
- (unsigned long) arg2,
- (unsigned long) arg3,
- (unsigned long) arg4,
- (unsigned long) arg5);
-}
-
-
-extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
- size_t count, loff_t pos);
-
-extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
- size_t count, loff_t pos);
-
-typedef __kernel_ssize_t32 ssize_t32;
-
-asmlinkage ssize_t32
-sys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count,
- u32 poshi, u32 poslo)
-{
- return sys_pread(fd, ubuf, count,
- ((loff_t)AA(poshi) << 32) | AA(poslo));
-}
-
-asmlinkage ssize_t32
-sys32_pwrite(unsigned int fd, char *ubuf, __kernel_size_t32 count,
- u32 poshi, u32 poslo)
-{
- return sys_pwrite(fd, ubuf, count,
- ((loff_t)AA(poshi) << 32) | AA(poslo));
-}
-
-
-extern asmlinkage long sys_personality(unsigned long);
-
-asmlinkage long
-sys32_personality(unsigned long personality)
-{
- int ret;
- if (current->personality = PER_LINUX32 && personality = PER_LINUX)
- personality = PER_LINUX32;
- ret = sys_personality(personality);
- if (ret = PER_LINUX32)
- ret = PER_LINUX;
- return ret;
-}
-
extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset,
size_t count);

asmlinkage long
sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
{
- mm_segment_t old_fs = get_fs();
- int ret;
- off_t of;
-
- if (offset && get_user(of, offset))
- return -EFAULT;
-
- set_fs(KERNEL_DS);
- ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
- set_fs(old_fs);
-
- if (!ret && offset && put_user(of, offset))
- return -EFAULT;
-
- return ret;
}

/* Handle adjtimex compatability. */
diff -urN linux-davidm/arch/ia64/kernel/acpi.c linux-2.4.10-lia/arch/ia64/kernel/acpi.c
--- linux-davidm/arch/ia64/kernel/acpi.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/acpi.c Mon Sep 24 21:45:43 2001
@@ -60,6 +60,8 @@
return "hpsim";
# elif defined (CONFIG_IA64_SGI_SN1)
return "sn1";
+# elif defined (CONFIG_IA64_SGI_SN2)
+ return "sn2";
# elif defined (CONFIG_IA64_DIG)
return "dig";
# else
diff -urN linux-davidm/arch/ia64/kernel/efi_stub.S linux-2.4.10-lia/arch/ia64/kernel/efi_stub.S
--- linux-davidm/arch/ia64/kernel/efi_stub.S Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/efi_stub.S Mon Sep 24 21:45:52 2001
@@ -1,8 +1,8 @@
/*
* EFI call stub.
*
- * Copyright (C) 1999-2000 Hewlett-Packard Co
- * Copyright (C) 1999-2000 David Mosberger <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
+ * David Mosberger <davidm@hpl.hp.com>
*
* This stub allows us to make EFI calls in physical mode with interrupts
* turned off. We need this because we can't call SetVirtualMap() until
@@ -68,17 +68,17 @@
;;
andcm r16=loc3,r16 // get psr with IT, DT, and RT bits cleared
mov out3=in4
- br.call.sptk.few rp=ia64_switch_mode
+ br.call.sptk.many rp=ia64_switch_mode
.ret0: mov out4=in5
mov out5=in6
mov out6=in7
- br.call.sptk.few rp¶ // call the EFI function
+ br.call.sptk.many rp¶ // call the EFI function
.ret1: mov ar.rsc=0 // put RSE in enforced lazy, LE mode
mov r16=loc3
- br.call.sptk.few rp=ia64_switch_mode // return to virtual mode
+ br.call.sptk.many rp=ia64_switch_mode // return to virtual mode
.ret2: mov ar.rsc=loc4 // restore RSE configuration
mov ar.pfs=loc1
mov rp=loc0
mov gp=loc2
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(efi_call_phys)
diff -urN linux-davidm/arch/ia64/kernel/efivars.c linux-2.4.10-lia/arch/ia64/kernel/efivars.c
--- linux-davidm/arch/ia64/kernel/efivars.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/efivars.c Mon Sep 24 21:46:04 2001
@@ -276,21 +276,20 @@
if (!capable(CAP_SYS_ADMIN))
return -EACCES;

- spin_lock(&efivars_lock);
MOD_INC_USE_COUNT;

var_data = kmalloc(size, GFP_KERNEL);
if (!var_data) {
MOD_DEC_USE_COUNT;
- spin_unlock(&efivars_lock);
return -ENOMEM;
}
if (copy_from_user(var_data, buffer, size)) {
MOD_DEC_USE_COUNT;
- spin_unlock(&efivars_lock);
+ kfree(var_data);
return -EFAULT;
}

+ spin_lock(&efivars_lock);

/* Since the data ptr we've currently got is probably for
a different variable find the right variable.
diff -urN linux-davidm/arch/ia64/kernel/entry.S linux-2.4.10-lia/arch/ia64/kernel/entry.S
--- linux-davidm/arch/ia64/kernel/entry.S Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/entry.S Mon Sep 24 21:46:12 2001
@@ -55,7 +55,7 @@
mov out1=in1 // argv
mov out2=in2 // envp
add out3\x16,sp // regs
- br.call.sptk.few rp=sys_execve
+ br.call.sptk.many rp=sys_execve
.ret0: cmp4.ge p6,p7=r8,r0
mov ar.pfs=loc1 // restore ar.pfs
sxt4 r8=r8 // return 64-bit result
@@ -64,7 +64,7 @@
(p6) cmp.ne pKern,pUser=r0,r0 // a successful execve() lands us in user-mode...
mov rp=loc0
(p6) mov ar.pfs=r0 // clear ar.pfs on success
-(p7) br.ret.sptk.few rp
+(p7) br.ret.sptk.many rp

/*
* In theory, we'd have to zap this state only to prevent leaking of
@@ -85,7 +85,7 @@
ldf.fill f26=[sp]; ldf.fill f27=[sp]; mov f28ð
ldf.fill f29=[sp]; ldf.fill f30=[sp]; mov f31ð
mov ar.lc=0
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(ia64_execve)

GLOBAL_ENTRY(sys_clone2)
@@ -99,7 +99,7 @@
mov out3=in2
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs
mov out0=in0 // out0 = clone_flags
- br.call.sptk.few rp=do_fork
+ br.call.sptk.many rp=do_fork
.ret1: .restore sp
adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
mov ar.pfs=loc1
@@ -118,7 +118,7 @@
mov out3=0
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs
mov out0=in0 // out0 = clone_flags
- br.call.sptk.few rp=do_fork
+ br.call.sptk.many rp=do_fork
.ret2: .restore sp
adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
mov ar.pfs=loc1
@@ -151,12 +151,13 @@
* again.
*/
(p6) cmp.eq p7,p6=r26,r27
-(p6) br.cond.dpnt.few .map
+(p6) br.cond.dpnt .map
;;
-.done: ld8 sp=[r21] // load kernel stack pointer of new task
+.done:
(p6) ssm psr.ic // if we we had to map, renable the psr.ic bit FIRST!!!
;;
(p6) srlz.d
+ ld8 sp=[r21] // load kernel stack pointer of new task
mov IA64_KR(CURRENT)=r20 // update "current" application register
mov r8=r13 // return pointer to previously running task
mov r13=in0 // set "current" pointer
@@ -167,7 +168,7 @@
#ifdef CONFIG_SMP
sync.i // ensure "fc"s done by this CPU are visible on other CPUs
#endif
- br.ret.sptk.few rp // boogie on out in new context
+ br.ret.sptk.many rp // boogie on out in new context

.map:
rsm psr.i | psr.ic
@@ -184,7 +185,7 @@
mov IA64_KR(CURRENT_STACK)=r26 // remember last page we mapped...
;;
itr.d dtr[r25]=r23 // wire in new mapping...
- br.cond.sptk.many .done
+ br.cond.sptk .done
END(ia64_switch_to)

/*
@@ -303,7 +304,7 @@
st8 [r2]=r20 // save ar.bspstore
st8 [r3]=r21 // save predicate registers
mov ar.rsc=3 // put RSE back into eager mode, pl 0
- br.cond.sptk.few b7
+ br.cond.sptk.many b7
END(save_switch_stack)

/*
@@ -418,7 +419,7 @@
;;
(p6) st4 [r2]=r8
(p6) mov r8=-1
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(__ia64_syscall)

/*
@@ -433,11 +434,11 @@
.body
mov loc2¶
;;
- br.call.sptk.few rp=syscall_trace
+ br.call.sptk.many rp=syscall_trace
.ret3: mov rp=loc0
mov ar.pfs=loc1
mov b6=loc2
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(invoke_syscall_trace)

/*
@@ -454,21 +455,21 @@

GLOBAL_ENTRY(ia64_trace_syscall)
PT_REGS_UNWIND_INFO(0)
- br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args
-.ret6: br.call.sptk.few rp¶ // do the syscall
+ br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch syscall args
+.ret6: br.call.sptk.many rp¶ // do the syscall
strace_check_retval:
cmp.lt p6,p0=r8,r0 // syscall failed?
adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8
adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10
mov r10=0
-(p6) br.cond.sptk.few strace_error // syscall failed ->
+(p6) br.cond.sptk strace_error // syscall failed ->
;; // avoid RAW on r10
strace_save_retval:
.mem.offset 0,0; st8.spill [r2]=r8 // store return value in slot for r8
.mem.offset 8,0; st8.spill [r3]=r10 // clear error indication in slot for r10
ia64_strace_leave_kernel:
- br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value
-.rety: br.cond.sptk.many ia64_leave_kernel
+ br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch return value
+.rety: br.cond.sptk ia64_leave_kernel

strace_error:
ld8 r3=[r2] // load pt_regs.r8
@@ -479,7 +480,7 @@
;;
(p6) mov r10=-1
(p6) mov r8=r9
- br.cond.sptk.few strace_save_retval
+ br.cond.sptk strace_save_retval
END(ia64_trace_syscall)

GLOBAL_ENTRY(ia64_ret_from_clone)
@@ -489,7 +490,7 @@
* Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the
* address of the previously executing task.
*/
- br.call.sptk.few rp=invoke_schedule_tail
+ br.call.sptk.many rp=ia64_invoke_schedule_tail
.ret8:
adds r2=IA64_TASK_PTRACE_OFFSET,r13
;;
@@ -497,7 +498,7 @@
;;
mov r8=0
tbit.nz p6,p0=r2,PT_TRACESYS_BIT
-(p6) br strace_check_retval
+(p6) br.cond.spnt strace_check_retval
;; // added stop bits to prevent r8 dependency
END(ia64_ret_from_clone)
// fall through
@@ -511,7 +512,7 @@
(p6) st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit
.mem.offset 8,0
(p6) st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit
-(p7) br.cond.spnt.few handle_syscall_error // handle potential syscall failure
+(p7) br.cond.spnt handle_syscall_error // handle potential syscall failure
END(ia64_ret_from_syscall)
// fall through
GLOBAL_ENTRY(ia64_leave_kernel)
@@ -524,17 +525,17 @@
adds r17=IA64_TASK_NEED_RESCHED_OFFSET,r13
adds r18=IA64_TASK_SIGPENDING_OFFSET,r13
#ifdef CONFIG_PERFMON
- adds r19=IA64_TASK_PFM_NOTIFY_OFFSET,r13
+ adds r19=IA64_TASK_PFM_MUST_BLOCK_OFFSET,r13
#endif
;;
#ifdef CONFIG_PERFMON
-(pUser) ld8 r19=[r19] // load current->task.pfm_notify
+(pUser) ld8 r19=[r19] // load current->thread.pfm_must_block
#endif
(pUser) ld8 r17=[r17] // load current->need_resched
(pUser) ld4 r18=[r18] // load current->sigpending
;;
#ifdef CONFIG_PERFMON
-(pUser) cmp.ne.unc p9,p0=r19,r0 // current->task.pfm_notify != 0?
+(pUser) cmp.ne.unc p9,p0=r19,r0 // current->thread.pfm_must_block != 0?
#endif
(pUser) cmp.ne.unc p7,p0=r17,r0 // current->need_resched != 0?
(pUser) cmp.ne.unc p8,p0=r18,r0 // current->sigpending != 0?
@@ -542,7 +543,7 @@
adds r2=PT(R8)+16,r12
adds r3=PT(R9)+16,r12
#ifdef CONFIG_PERFMON
-(p9) br.call.spnt.many b7=pfm_overflow_notify
+(p9) br.call.spnt.many b7=pfm_block_on_overflow
#endif
#if __GNUC__ < 3
(p7) br.call.spnt.many b7=invoke_schedule
@@ -642,13 +643,13 @@
movl r17=PERCPU_ADDR+IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET
;;
ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8
-(pKern) br.cond.dpnt.few skip_rbs_switch
+(pKern) br.cond.dpnt skip_rbs_switch
/*
* Restore user backing store.
*
* NOTE: alloc, loadrs, and cover can't be predicated.
*/
-(pNonSys) br.cond.dpnt.few dont_preserve_current_frame
+(pNonSys) br.cond.dpnt dont_preserve_current_frame
cover // add current frame into dirty partition
;;
mov r19=ar.bsp // get new backing store pointer
@@ -698,7 +699,7 @@
}{ .mib
mov loc3=0
mov loc4=0
-(pRecurse) br.call.sptk.few b6=rse_clear_invalid
+(pRecurse) br.call.sptk.many b6=rse_clear_invalid

}{ .mfi // cycle 2
mov loc5=0
@@ -707,7 +708,7 @@
}{ .mib
mov loc6=0
mov loc7=0
-(pReturn) br.ret.sptk.few b6
+(pReturn) br.ret.sptk.many b6
}
# undef pRecurse
# undef pReturn
@@ -753,24 +754,24 @@
;;
.mem.offset 0,0; st8.spill [r2]=r9 // store errno in pt_regs.r8 and set unat bit
.mem.offset 8,0; st8.spill [r3]=r10 // store error indication in pt_regs.r10 and set unat bit
- br.cond.sptk.many ia64_leave_kernel
+ br.cond.sptk ia64_leave_kernel
END(handle_syscall_error)

/*
* Invoke schedule_tail(task) while preserving in0-in7, which may be needed
* in case a system call gets restarted.
*/
-ENTRY(invoke_schedule_tail)
+GLOBAL_ENTRY(ia64_invoke_schedule_tail)
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
alloc loc1=ar.pfs,8,2,1,0
mov loc0=rp
mov out0=r8 // Address of previous task
;;
- br.call.sptk.few rp=schedule_tail
+ br.call.sptk.many rp=schedule_tail
.ret11: mov ar.pfs=loc1
mov rp=loc0
br.ret.sptk.many rp
-END(invoke_schedule_tail)
+END(ia64_invoke_schedule_tail)

#if __GNUC__ < 3

@@ -789,7 +790,7 @@
mov loc0=rp
;;
.body
- br.call.sptk.few rp=schedule
+ br.call.sptk.many rp=schedule
.ret14: mov ar.pfs=loc1
mov rp=loc0
br.ret.sptk.many rp
@@ -816,7 +817,7 @@
.spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
.body
- br.call.sptk.few rp=ia64_do_signal
+ br.call.sptk.many rp=ia64_do_signal
.ret15: .restore sp
adds sp\x16,sp // pop scratch stack space
;;
@@ -841,7 +842,7 @@
.spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
.body
- br.call.sptk.few rp=ia64_rt_sigsuspend
+ br.call.sptk.many rp=ia64_rt_sigsuspend
.ret17: .restore sp
adds sp\x16,sp // pop scratch stack space
;;
@@ -863,7 +864,7 @@
cmp.eq pNonSys,pSys=r0,r0 // sigreturn isn't a normal syscall...
;;
adds out0\x16,sp // out0 = &sigscratch
- br.call.sptk.few rp=ia64_rt_sigreturn
+ br.call.sptk.many rp=ia64_rt_sigreturn
.ret19: .restore sp 0
adds sp\x16,sp
;;
@@ -871,7 +872,7 @@
mov.sptk b7=r8,ia64_leave_kernel
;;
mov ar.unat=r9
- br b7
+ br.many b7
END(sys_rt_sigreturn)

GLOBAL_ENTRY(ia64_prepare_handle_unaligned)
@@ -882,7 +883,7 @@
mov r16=r0
.prologue
DO_SAVE_SWITCH_STACK
- br.call.sptk.few rp=ia64_handle_unaligned // stack frame setup in ivt
+ br.call.sptk.many rp=ia64_handle_unaligned // stack frame setup in ivt
.ret21: .body
DO_LOAD_SWITCH_STACK
br.cond.sptk.many rp // goes to ia64_leave_kernel
@@ -912,14 +913,14 @@
adds out0\x16,sp // &info
mov out1=r13 // current
adds out2\x16+EXTRA_FRAME_SIZE,sp // &switch_stack
- br.call.sptk.few rp=unw_init_frame_info
+ br.call.sptk.many rp=unw_init_frame_info
1: adds out0\x16,sp // &info
mov b6=loc2
mov loc2=gp // save gp across indirect function call
;;
ld8 gp=[in0]
mov out1=in1 // arg
- br.call.sptk.few rp¶ // invoke the callback function
+ br.call.sptk.many rp¶ // invoke the callback function
1: mov gp=loc2 // restore gp

// For now, we don't allow changing registers from within
diff -urN linux-davidm/arch/ia64/kernel/fw-emu.c linux-2.4.10-lia/arch/ia64/kernel/fw-emu.c
--- linux-davidm/arch/ia64/kernel/fw-emu.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/fw-emu.c Mon Sep 24 21:46:40 2001
@@ -416,11 +416,6 @@
strcpy(sal_systab->product_id, "SDV");
#endif

-#ifdef CONFIG_IA64_SGI_SN1_SIM
- strcpy(sal_systab->oem_id, "SGI");
- strcpy(sal_systab->product_id, "SN1");
-#endif
-
/* fill in an entry point: */
sal_ed->type = SAL_DESC_ENTRY_POINT;
sal_ed->pal_proc = __pa(pal_desc[0]);
diff -urN linux-davidm/arch/ia64/kernel/gate.S linux-2.4.10-lia/arch/ia64/kernel/gate.S
--- linux-davidm/arch/ia64/kernel/gate.S Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/gate.S Mon Sep 24 21:46:49 2001
@@ -3,7 +3,7 @@
* region. For now, it contains the signal trampoline code only.
*
* Copyright (C) 1999-2001 Hewlett-Packard Co
- * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*/

#include <asm/asmmacro.h>
@@ -18,7 +18,6 @@
# define ARG0_OFF (16 + IA64_SIGFRAME_ARG0_OFFSET)
# define ARG1_OFF (16 + IA64_SIGFRAME_ARG1_OFFSET)
# define ARG2_OFF (16 + IA64_SIGFRAME_ARG2_OFFSET)
-# define RBS_BASE_OFF (16 + IA64_SIGFRAME_RBS_BASE_OFFSET)
# define SIGHANDLER_OFF (16 + IA64_SIGFRAME_HANDLER_OFFSET)
# define SIGCONTEXT_OFF (16 + IA64_SIGFRAME_SIGCONTEXT_OFFSET)

@@ -32,6 +31,8 @@
# define PR_OFF IA64_SIGCONTEXT_PR_OFFSET
# define RP_OFF IA64_SIGCONTEXT_B0_OFFSET
# define SP_OFF IA64_SIGCONTEXT_R12_OFFSET
+# define RBS_BASE_OFF IA64_SIGCONTEXT_RBS_BASE_OFFSET
+# define LOADRS_OFF IA64_SIGCONTEXT_LOADRS_OFFSET
# define base0 r2
# define base1 r3
/*
@@ -73,34 +74,37 @@
.vframesp SP_OFF+SIGCONTEXT_OFF
.body

- .prologue
+ .label_state 1
+
adds base0=SIGHANDLER_OFF,sp
- adds base1=RBS_BASE_OFF,sp
+ adds base1=RBS_BASE_OFF+SIGCONTEXT_OFF,sp
br.call.sptk.many rp\x1f
1:
ld8 r17=[base0],(ARG0_OFF-SIGHANDLER_OFF) // get pointer to signal handler's plabel
- ld8 r15=[base1],(ARG1_OFF-RBS_BASE_OFF) // get address of new RBS base (or NULL)
+ ld8 r15=[base1] // get address of new RBS base (or NULL)
cover // push args in interrupted frame onto backing store
;;
+ cmp.ne p8,p0=r15,r0 // do we need to switch the rbs?
+ mov.m r9=ar.bsp // fetch ar.bsp
+ .spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
+(p8) br.cond.spnt setup_rbs // yup -> (clobbers r14, r15, and r16)
+back_from_setup_rbs:
+
.save ar.pfs, r8
alloc r8=ar.pfs,0,0,3,0 // get CFM0, EC0, and CPL0 into r8
ld8 out0=[base0],16 // load arg0 (signum)
+ adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1
;;
ld8 out1=[base1] // load arg1 (siginfop)
ld8 r10=[r17],8 // get signal handler entry point
;;
ld8 out2=[base0] // load arg2 (sigcontextp)
ld8 gp=[r17] // get signal handler's global pointer
- cmp.ne p8,p0=r15,r0 // do we need to switch the rbs?

- mov.m r17=ar.bsp // fetch ar.bsp
- .spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
-(p8) br.cond.spnt.few setup_rbs // yup -> (clobbers r14 and r16)
-back_from_setup_rbs:
adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
;;
.spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF
- st8 [base0]=r17,(CFM_OFF-BSP_OFF) // save sc_ar_bsp
+ st8 [base0]=r9,(CFM_OFF-BSP_OFF) // save sc_ar_bsp
dep r8=0,r8,38,26 // clear EC0, CPL0 and reserved bits
adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
;;
@@ -123,7 +127,7 @@
;;
stf.spill [base0]ñ4,32
stf.spill [base1]ñ5,32
- br.call.sptk.few rp¶ // call the signal handler
+ br.call.sptk.many rp¶ // call the signal handler
.ret0: adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
;;
ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF
@@ -131,7 +135,7 @@
;;
ld8 r8=[base0] // restore (perhaps modified) CFM0, EC0, and CPL0
cmp.ne p8,p0=r14,r15 // do we need to restore the rbs?
-(p8) br.cond.spnt.few restore_rbs // yup -> (clobbers r14 and r16)
+(p8) br.cond.spnt restore_rbs // yup -> (clobbers r14 and r16)
;;
back_from_restore_rbs:
adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
@@ -154,30 +158,52 @@
mov r15=__NR_rt_sigreturn
break __BREAK_SYSCALL

+ .body
+ .copy_state 1
setup_rbs:
- flushrs // must be first in insn
mov ar.rsc=0 // put RSE into enforced lazy mode
- adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp
;;
- mov r14=ar.rnat // get rnat as updated by flushrs
- mov ar.bspstore=r15 // set new register backing store area
+ .save ar.rnat, r16
+ mov r16=ar.rnat // save RNaT before switching backing store area
+ adds r14=(RNAT_OFF+SIGCONTEXT_OFF),sp
+
+ mov ar.bspstore=r15 // switch over to new register backing store area
;;
.spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
- st8 [r16]=r14 // save sc_ar_rnat
+ st8 [r14]=r16 // save sc_ar_rnat
+ adds r14=(LOADRS_OFF+SIGCONTEXT_OFF),sp
+
+ mov.m r16=ar.bsp // sc_loadrs <- (new bsp - new bspstore) << 16
+ ;;
+ invala
+ sub r15=r16,r15
+ ;;
+ shl r15=r15,16
+ ;;
+ st8 [r14]=r15 // save sc_loadrs
mov ar.rsc=0xf // set RSE into eager mode, pl 3
- invala // invalidate ALAT
- br.cond.sptk.many back_from_setup_rbs
+ br.cond.sptk back_from_setup_rbs

+ .prologue
+ .copy_state 1
+ .spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
+ .body
restore_rbs:
- flushrs
- mov ar.rsc=0 // put RSE into enforced lazy mode
+ alloc r2=ar.pfs,0,0,0,0 // alloc null frame
+ adds r16=(LOADRS_OFF+SIGCONTEXT_OFF),sp
+ ;;
+ ld8 r14=[r16]
adds r16=(RNAT_OFF+SIGCONTEXT_OFF),sp
;;
+ mov ar.rsc=r14 // put RSE into enforced lazy mode
ld8 r14=[r16] // get new rnat
- mov ar.bspstore=r15 // set old register backing store area
;;
- mov ar.rnat=r14 // establish new rnat
+ loadrs // restore dirty partition
+ ;;
+ mov ar.bspstore=r15 // switch back to old register backing store area
+ ;;
+ mov ar.rnat=r14 // restore RNaT
mov ar.rsc=0xf // (will be restored later on from sc_ar_rsc)
// invala not necessary as that will happen when returning to user-mode
- br.cond.sptk.many back_from_restore_rbs
+ br.cond.sptk back_from_restore_rbs
END(ia64_sigtramp)
diff -urN linux-davidm/arch/ia64/kernel/head.S linux-2.4.10-lia/arch/ia64/kernel/head.S
--- linux-davidm/arch/ia64/kernel/head.S Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/head.S Mon Sep 24 21:47:23 2001
@@ -6,8 +6,8 @@
* entry point.
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2001 Stephane Eranian <eranian@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
+ * Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
* Copyright (C) 1999 Intel Corp.
@@ -86,7 +86,8 @@
/*
* Switch into virtual mode:
*/
- movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN)
+ movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \
+ |IA64_PSR_DI)
;;
mov cr.ipsr=r16
movl r17\x1f
@@ -183,31 +184,31 @@
alloc r2=ar.pfs,0,0,2,0
movl out0=alive_msg
;;
- br.call.sptk.few rpêrly_printk
+ br.call.sptk.many rpêrly_printk
1: // force new bundle
#endif /* CONFIG_IA64_EARLY_PRINTK */

#ifdef CONFIG_SMP
-(isAP) br.call.sptk.few rp=start_secondary
+(isAP) br.call.sptk.many rp=start_secondary
.ret0:
-(isAP) br.cond.sptk.few self
+(isAP) br.cond.sptk self
#endif

// This is executed by the bootstrap processor (bsp) only:

#ifdef CONFIG_IA64_FW_EMU
// initialize PAL & SAL emulator:
- br.call.sptk.few rp=sys_fw_init
+ br.call.sptk.many rp=sys_fw_init
.ret1:
#endif
- br.call.sptk.few rp=start_kernel
+ br.call.sptk.many rp=start_kernel
.ret2: addl r3=@ltoff(halt_msg),gp
;;
alloc r2=ar.pfs,8,0,2,0
;;
ld8 out0=[r3]
- br.call.sptk.few b0=console_print
-self: br.sptk.few self // endless loop
+ br.call.sptk.many b0=console_print
+self: br.sptk.many self // endless loop
END(_start)

GLOBAL_ENTRY(ia64_save_debug_regs)
@@ -227,10 +228,10 @@
;;
st8.nta [in0]=r16,8
st8.nta [r19]=r17,8
- br.cloop.sptk.few 1b
+ br.cloop.sptk.many 1b
;;
mov ar.lc=r20 // restore ar.lc
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(ia64_save_debug_regs)

GLOBAL_ENTRY(ia64_load_debug_regs)
@@ -251,10 +252,10 @@
srlz.d // Errata 132 (NoFix status)
#endif
mov ibr[r18]=r17
- br.cloop.sptk.few 1b
+ br.cloop.sptk.many 1b
;;
mov ar.lc=r20 // restore ar.lc
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(ia64_load_debug_regs)

GLOBAL_ENTRY(__ia64_save_fpu)
@@ -404,7 +405,7 @@
;;
stf.spill.nta [in0]ñ26,32
stf.spill.nta [ r3]ñ27,32
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(__ia64_save_fpu)

GLOBAL_ENTRY(__ia64_load_fpu)
@@ -554,7 +555,7 @@
;;
ldf.fill.nta f126=[in0],32
ldf.fill.nta f127=[ r3],32
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(__ia64_load_fpu)

GLOBAL_ENTRY(__ia64_init_fpu)
@@ -688,7 +689,7 @@
;;
ldf.fill f126=[sp]
mov f127ð
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(__ia64_init_fpu)

/*
@@ -736,7 +737,7 @@
rfi // must be last insn in group
;;
1: mov rp=r14
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(ia64_switch_mode)

#ifdef CONFIG_IA64_BRL_EMU
@@ -750,7 +751,7 @@
alloc r16=ar.pfs,1,0,0,0; \
mov reg=r32; \
;; \
- br.ret.sptk rp; \
+ br.ret.sptk.many rp; \
END(ia64_set_##reg)

SET_REG(b1);
@@ -814,7 +815,7 @@
;;
cmp.ne p15,p0=tmp,r0
mov tmp=ar.itc
-(p15) br.cond.sptk.few .retry // lock is still busy
+(p15) br.cond.sptk .retry // lock is still busy
;;
// try acquiring lock (we know ar.ccv is still zero!):
mov tmp=1
diff -urN linux-davidm/arch/ia64/kernel/ia64_ksyms.c linux-2.4.10-lia/arch/ia64/kernel/ia64_ksyms.c
--- linux-davidm/arch/ia64/kernel/ia64_ksyms.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/ia64_ksyms.c Mon Sep 24 21:47:44 2001
@@ -145,4 +145,3 @@
#include <linux/proc_fs.h>
extern struct proc_dir_entry *efi_dir;
EXPORT_SYMBOL(efi_dir);
-
diff -urN linux-davidm/arch/ia64/kernel/iosapic.c linux-2.4.10-lia/arch/ia64/kernel/iosapic.c
--- linux-davidm/arch/ia64/kernel/iosapic.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/iosapic.c Mon Sep 24 21:47:52 2001
@@ -343,6 +343,54 @@
}

/*
+ * ACPI can describe IOSAPIC interrupts via static tables and namespace
+ * methods. This provides an interface to register those interrupts and
+ * program the IOSAPIC RTE.
+ */
+int
+iosapic_register_irq (u32 global_vector, unsigned long polarity, unsigned long
+ edge_triggered, u32 base_irq, char *iosapic_address)
+{
+ irq_desc_t *idesc;
+ struct hw_interrupt_type *irq_type;
+ int vector;
+
+ vector = iosapic_irq_to_vector(global_vector);
+ if (vector < 0)
+ vector = ia64_alloc_irq();
+
+ /* fill in information from this vector's IOSAPIC */
+ iosapic_irq[vector].addr = iosapic_address;
+ iosapic_irq[vector].base_irq = base_irq;
+ iosapic_irq[vector].pin = global_vector - iosapic_irq[vector].base_irq;
+ iosapic_irq[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;
+ iosapic_irq[vector].dmode = IOSAPIC_LOWEST_PRIORITY;
+
+ if (edge_triggered) {
+ iosapic_irq[vector].trigger = IOSAPIC_EDGE;
+ irq_type = &irq_type_iosapic_edge;
+ } else {
+ iosapic_irq[vector].trigger = IOSAPIC_LEVEL;
+ irq_type = &irq_type_iosapic_level;
+ }
+
+ idesc = irq_desc(vector);
+ if (idesc->handler != irq_type) {
+ if (idesc->handler != &no_irq_type)
+ printk("iosapic_register_irq(): changing vector 0x%02x from"
+ "%s to %s\n", vector, idesc->handler->typename, irq_type->typename);
+ idesc->handler = irq_type;
+ }
+
+ printk("IOSAPIC %x(%s,%s) -> Vector %x\n", global_vector,
+ (polarity ? "high" : "low"), (edge_triggered ? "edge" : "level"), vector);
+
+ /* program the IOSAPIC routing table */
+ set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);
+ return vector;
+}
+
+/*
* ACPI calls this when it finds an entry for a platform interrupt.
* Note that the irq_base and IOSAPIC address must be set in iosapic_init().
*/
@@ -392,7 +440,7 @@
}

printk("PLATFORM int %x: IOSAPIC %x(%s,%s) -> Vector %x CPU %.02u:%.02u\n",
- int_type, global_vector, (polarity ? "hign" : "low"),
+ int_type, global_vector, (polarity ? "high" : "low"),
(edge_triggered ? "edge" : "level"), vector, eid, id);

/* program the IOSAPIC routing table */
@@ -496,7 +544,7 @@
/* the interrupt route is for another controller... */
continue;

- if (irq < 16)
+ if (pcat_compat && (irq < 16))
vector = isa_irq_to_vector(irq);
else {
vector = iosapic_irq_to_vector(irq);
@@ -575,6 +623,23 @@
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;
+
+#ifdef CONFIG_SMP
+ /*
+ * For platforms that do not support interrupt redirect
+ * via the XTP interface, we can round-robin the PCI
+ * device interrupts to the processors
+ */
+ if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) {
+ static int cpu_index = 0;
+
+ set_rte(vector, cpu_physical_id(cpu_index) & 0xffff);
+
+ cpu_index++;
+ if (cpu_index >= smp_num_cpus)
+ cpu_index = 0;
+ }
+#endif
}
}
/*
diff -urN linux-davidm/arch/ia64/kernel/irq.c linux-2.4.10-lia/arch/ia64/kernel/irq.c
--- linux-davidm/arch/ia64/kernel/irq.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/irq.c Mon Sep 24 21:48:11 2001
@@ -33,6 +33,7 @@
#include <linux/irq.h>
#include <linux/proc_fs.h>

+#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/system.h>
@@ -121,7 +122,10 @@
end_none
};

-volatile unsigned long irq_err_count;
+atomic_t irq_err_count;
+#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG)
+atomic_t irq_mis_count;
+#endif

/*
* Generic, controller-independent functions:
@@ -164,14 +168,17 @@
p += sprintf(p, "%10u ",
nmi_count(cpu_logical_map(j)));
p += sprintf(p, "\n");
-#if defined(CONFIG_SMP) && defined(__i386__)
+#if defined(CONFIG_SMP) && defined(CONFIG_X86)
p += sprintf(p, "LOC: ");
for (j = 0; j < smp_num_cpus; j++)
p += sprintf(p, "%10u ",
apic_timer_irqs[cpu_logical_map(j)]);
p += sprintf(p, "\n");
#endif
- p += sprintf(p, "ERR: %10lu\n", irq_err_count);
+ p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG)
+ p += sprintf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+#endif
return p - buf;
}

@@ -183,7 +190,7 @@

#ifdef CONFIG_SMP
unsigned int global_irq_holder = NO_PROC_ID;
-volatile unsigned long global_irq_lock; /* long for set_bit --RR */
+unsigned volatile long global_irq_lock; /* pedantic: long for set_bit --RR */

extern void show_stack(unsigned long* esp);

@@ -201,14 +208,14 @@
printk(" %d",bh_count(i));

printk(" ]\nStack dumps:");
-#if defined(__ia64__)
+#if defined(CONFIG_IA64)
/*
* We can't unwind the stack of another CPU without access to
* the registers of that CPU. And sending an IPI when we're
* in a potentially wedged state doesn't sound like a smart
* idea.
*/
-#elif defined(__i386__)
+#elif defined(CONFIG_X86)
for(i=0;i< smp_num_cpus;i++) {
unsigned long esp;
if(i=cpu)
@@ -261,7 +268,7 @@
/*
* We have to allow irqs to arrive between __sti and __cli
*/
-# ifdef __ia64__
+# ifdef CONFIG_IA64
# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop 0")
# else
# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop")
@@ -331,6 +338,9 @@
/* Uhhuh.. Somebody else got it. Wait.. */
do {
do {
+#ifdef CONFIG_X86
+ rep_nop();
+#endif
} while (test_bit(0,&global_irq_lock));
} while (test_and_set_bit(0,&global_irq_lock));
}
@@ -364,7 +374,7 @@
{
unsigned int flags;

-#ifdef __ia64__
+#ifdef CONFIG_IA64
__save_flags(flags);
if (flags & IA64_PSR_I) {
__cli();
@@ -403,7 +413,7 @@
int cpu = smp_processor_id();

__save_flags(flags);
-#ifdef __ia64__
+#ifdef CONFIG_IA64
local_enabled = (flags & IA64_PSR_I) != 0;
#else
local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1;
@@ -476,13 +486,19 @@
return status;
}

-/*
- * Generic enable/disable code: this just calls
- * down into the PIC-specific version for the actual
- * hardware disable after having gotten the irq
- * controller lock.
+/**
+ * disable_irq_nosync - disable an irq without waiting
+ * @irq: Interrupt to disable
+ *
+ * Disable the selected interrupt line. Disables and Enables are
+ * nested.
+ * Unlike disable_irq(), this function does not ensure existing
+ * instances of the IRQ handler have completed before returning.
+ *
+ * This function may be called from IRQ context.
*/
-void inline disable_irq_nosync(unsigned int irq)
+
+inline void disable_irq_nosync(unsigned int irq)
{
irq_desc_t *desc = irq_desc(irq);
unsigned long flags;
@@ -495,10 +511,19 @@
spin_unlock_irqrestore(&desc->lock, flags);
}

-/*
- * Synchronous version of the above, making sure the IRQ is
- * no longer running on any other IRQ..
+/**
+ * disable_irq - disable an irq and wait for completion
+ * @irq: Interrupt to disable
+ *
+ * Disable the selected interrupt line. Enables and Disables are
+ * nested.
+ * This function waits for any pending IRQ handlers for this interrupt
+ * to complete before returning. If you use this function while
+ * holding a resource the IRQ handler may need you will deadlock.
+ *
+ * This function may be called - with care - from IRQ context.
*/
+
void disable_irq(unsigned int irq)
{
disable_irq_nosync(irq);
@@ -512,6 +537,17 @@
#endif
}

+/**
+ * enable_irq - enable handling of an irq
+ * @irq: Interrupt to enable
+ *
+ * Undoes the effect of one call to disable_irq(). If this
+ * matches the last disable, processing of interrupts on this
+ * IRQ line is re-enabled.
+ *
+ * This function may be called from IRQ context.
+ */
+
void enable_irq(unsigned int irq)
{
irq_desc_t *desc = irq_desc(irq);
@@ -533,7 +569,8 @@
desc->depth--;
break;
case 0:
- printk("enable_irq() unbalanced from %p\n", (void *) __builtin_return_address(0));
+ printk("enable_irq(%u) unbalanced from %p\n",
+ irq, (void *) __builtin_return_address(0));
}
spin_unlock_irqrestore(&desc->lock, flags);
}
@@ -626,11 +663,41 @@
desc->handler->end(irq);
spin_unlock(&desc->lock);
}
- if (local_softirq_pending())
- do_softirq();
return 1;
}

+/**
+ * request_irq - allocate an interrupt line
+ * @irq: Interrupt line to allocate
+ * @handler: Function to be called when the IRQ occurs
+ * @irqflags: Interrupt type flags
+ * @devname: An ascii name for the claiming device
+ * @dev_id: A cookie passed back to the handler function
+ *
+ * This call allocates interrupt resources and enables the
+ * interrupt line and IRQ handling. From the point this
+ * call is made your handler function may be invoked. Since
+ * your handler function must clear any interrupt the board
+ * raises, you must take care both to initialise your hardware
+ * and to set up the interrupt handler in the right order.
+ *
+ * Dev_id must be globally unique. Normally the address of the
+ * device data structure is used as the cookie. Since the handler
+ * receives this value it makes sense to use it.
+ *
+ * If your interrupt is shared you must pass a non NULL dev_id
+ * as this is required when freeing the interrupt.
+ *
+ * Flags:
+ *
+ * SA_SHIRQ Interrupt is shared
+ *
+ * SA_INTERRUPT Disable local interrupts while processing
+ *
+ * SA_SAMPLE_RANDOM The interrupt can be used for entropy
+ *
+ */
+
int request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
@@ -676,6 +743,24 @@
return retval;
}

+/**
+ * free_irq - free an interrupt
+ * @irq: Interrupt line to free
+ * @dev_id: Device identity to free
+ *
+ * Remove an interrupt handler. The handler is removed and if the
+ * interrupt line is no longer in use by any driver it is disabled.
+ * On a shared IRQ the caller must ensure the interrupt is disabled
+ * on the card it drives before calling this function. The function
+ * does not return until any executing interrupts for this IRQ
+ * have completed.
+ *
+ * This function may be called from interrupt context.
+ *
+ * Bugs: Attempting to free an irq in a handler for the same irq hangs
+ * the machine.
+ */
+
void free_irq(unsigned int irq, void *dev_id)
{
irq_desc_t *desc;
@@ -726,6 +811,17 @@
* with "IRQ_WAITING" cleared and the interrupt
* disabled.
*/
+
+static DECLARE_MUTEX(probe_sem);
+
+/**
+ * probe_irq_on - begin an interrupt autodetect
+ *
+ * Commence probing for an interrupt. The interrupts are scanned
+ * and a mask of potential interrupt lines is returned.
+ *
+ */
+
unsigned long probe_irq_on(void)
{
unsigned int i;
@@ -733,6 +829,7 @@
unsigned long val;
unsigned long delay;

+ down(&probe_sem);
/*
* something may have generated an irq long ago and we want to
* flush such a longstanding irq before considering it as spurious.
@@ -799,10 +896,19 @@
return val;
}

-/*
- * Return a mask of triggered interrupts (this
- * can handle only legacy ISA interrupts).
+/**
+ * probe_irq_mask - scan a bitmap of interrupt lines
+ * @val: mask of interrupts to consider
+ *
+ * Scan the ISA bus interrupt lines and return a bitmap of
+ * active interrupts. The interrupt probe logic state is then
+ * returned to its previous value.
+ *
+ * Note: we need to scan all the irq's even though we will
+ * only return ISA irq numbers - just so that we reset them
+ * all to a known state.
*/
+
unsigned int probe_irq_mask(unsigned long val)
{
int i;
@@ -825,14 +931,29 @@
}
spin_unlock_irq(&desc->lock);
}
+ up(&probe_sem);

return mask & val;
}

-/*
- * Return the one interrupt that triggered (this can
- * handle any interrupt source)
+/**
+ * probe_irq_off - end an interrupt autodetect
+ * @val: mask of potential interrupts (unused)
+ *
+ * Scans the unused interrupt lines and returns the line which
+ * appears to have triggered the interrupt. If no interrupt was
+ * found then zero is returned. If more than one interrupt is
+ * found then minus the first candidate is returned to indicate
+ * their is doubt.
+ *
+ * The interrupt probe logic state is returned to its previous
+ * value.
+ *
+ * BUGS: When used in a module (which arguably shouldnt happen)
+ * nothing prevents two IRQ probe callers from overlapping. The
+ * results of this are non-optimal.
*/
+
int probe_irq_off(unsigned long val)
{
int i, irq_found, nr_irqs;
@@ -857,6 +978,7 @@
}
spin_unlock_irq(&desc->lock);
}
+ up(&probe_sem);

if (nr_irqs > 1)
irq_found = -irq_found;
@@ -911,7 +1033,7 @@

if (!shared) {
desc->depth = 0;
- desc->status &= ~IRQ_DISABLED;
+ desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
desc->handler->startup(irq);
}
spin_unlock_irqrestore(&desc->lock,flags);
@@ -922,20 +1044,9 @@

static struct proc_dir_entry * root_irq_dir;
static struct proc_dir_entry * irq_dir [NR_IRQS];
-static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
-
-static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };

#define HEX_DIGITS 8

-static int irq_affinity_read_proc (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- if (count < HEX_DIGITS+1)
- return -EINVAL;
- return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
-}
-
static unsigned int parse_hex_value (const char *buffer,
unsigned long count, unsigned long *ret)
{
@@ -973,6 +1084,20 @@
return 0;
}

+#if CONFIG_SMP
+
+static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
+
+static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
+
+static int irq_affinity_read_proc (char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ if (count < HEX_DIGITS+1)
+ return -EINVAL;
+ return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
+}
+
static int irq_affinity_write_proc (struct file *file, const char *buffer,
unsigned long count, void *data)
{
@@ -984,7 +1109,6 @@

err = parse_hex_value(buffer, count, &new_value);

-#if CONFIG_SMP
/*
* Do not allow disabling IRQs completely - it's a too easy
* way to make the system unusable accidentally :-) At least
@@ -992,7 +1116,6 @@
*/
if (!(new_value & cpu_online_map))
return -EINVAL;
-#endif

irq_affinity[irq] = new_value;
irq_desc(irq)->handler->set_affinity(irq, new_value);
@@ -1000,6 +1123,8 @@
return full_count;
}

+#endif /* CONFIG_SMP */
+
static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -1027,7 +1152,6 @@

static void register_irq_proc (unsigned int irq)
{
- struct proc_dir_entry *entry;
char name [MAX_NAMELEN];

if (!root_irq_dir || (irq_desc(irq)->handler = &no_irq_type))
@@ -1039,15 +1163,22 @@
/* create /proc/irq/1234 */
irq_dir[irq] = proc_mkdir(name, root_irq_dir);

- /* create /proc/irq/1234/smp_affinity */
- entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
-
- entry->nlink = 1;
- entry->data = (void *)(long)irq;
- entry->read_proc = irq_affinity_read_proc;
- entry->write_proc = irq_affinity_write_proc;
+#if CONFIG_SMP
+ {
+ struct proc_dir_entry *entry;
+ /* create /proc/irq/1234/smp_affinity */
+ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
+
+ if (entry) {
+ entry->nlink = 1;
+ entry->data = (void *)(long)irq;
+ entry->read_proc = irq_affinity_read_proc;
+ entry->write_proc = irq_affinity_write_proc;
+ }

- smp_affinity_entry[irq] = entry;
+ smp_affinity_entry[irq] = entry;
+ }
+#endif
}

unsigned long prof_cpu_mask = -1;
@@ -1062,6 +1193,9 @@

/* create /proc/irq/prof_cpu_mask */
entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
+
+ if (!entry)
+ return;

entry->nlink = 1;
entry->data = (void *)&prof_cpu_mask;
diff -urN linux-davidm/arch/ia64/kernel/irq_ia64.c linux-2.4.10-lia/arch/ia64/kernel/irq_ia64.c
--- linux-davidm/arch/ia64/kernel/irq_ia64.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/irq_ia64.c Mon Sep 24 21:48:36 2001
@@ -1,9 +1,9 @@
/*
* linux/arch/ia64/kernel/irq.c
*
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Stephane Eranian <eranian@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*
* 6/10/99: Updated to bring in sync with x86 version to facilitate
* support for SMP and different interrupt controllers.
@@ -131,6 +131,13 @@
ia64_eoi();
vector = ia64_get_ivr();
}
+ /*
+ * This must be done *after* the ia64_eoi(). For example, the keyboard softirq
+ * handler needs to be able to wait for further keyboard interrupts, which can't
+ * come through until ia64_eoi() has been done.
+ */
+ if (local_softirq_pending())
+ do_softirq();
}

#ifdef CONFIG_SMP
diff -urN linux-davidm/arch/ia64/kernel/ivt.S linux-2.4.10-lia/arch/ia64/kernel/ivt.S
--- linux-davidm/arch/ia64/kernel/ivt.S Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/ivt.S Mon Sep 24 21:48:47 2001
@@ -2,8 +2,8 @@
* arch/ia64/kernel/ivt.S
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 1998-2001 David Mosberger <davidm@hpl.hp.com>
+ * Stephane Eranian <eranian@hpl.hp.com>
+ * David Mosberger <davidm@hpl.hp.com>
*
* 00/08/23 Asit Mallick <asit.k.mallick@intel.com> TLB handling for SMP
* 00/12/20 David Mosberger-Tang <davidm@hpl.hp.com> DTLB/ITLB handler now uses virtual PT.
@@ -157,7 +157,7 @@
;;
(p10) itc.i r18 // insert the instruction TLB entry
(p11) itc.d r18 // insert the data TLB entry
-(p6) br.spnt.many page_fault // handle bad address/page not present (page fault)
+(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault)
mov cr.ifa=r22

/*
@@ -213,7 +213,7 @@
;;
mov b0=r29
tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.cond.spnt.many page_fault
+(p6) br.cond.spnt page_fault
;;
itc.i r18
;;
@@ -251,7 +251,7 @@
;;
mov b0=r29
tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
-(p6) br.cond.spnt.many page_fault
+(p6) br.cond.spnt page_fault
;;
itc.d r18
;;
@@ -286,7 +286,7 @@
;;
(p8) mov cr.iha=r17
(p8) mov r29° // save b0
-(p8) br.cond.dptk.many itlb_fault
+(p8) br.cond.dptk itlb_fault
#endif
extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
shr.u r18=r16,57 // move address bit 61 to bit 4
@@ -297,7 +297,7 @@
dep r19=r17,r19,0,12 // insert PTE control bits into r19
;;
or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6
-(p8) br.cond.spnt.many page_fault
+(p8) br.cond.spnt page_fault
;;
itc.i r19 // insert the TLB entry
mov pr=r31,-1
@@ -324,7 +324,7 @@
;;
(p8) mov cr.iha=r17
(p8) mov r29° // save b0
-(p8) br.cond.dptk.many dtlb_fault
+(p8) br.cond.dptk dtlb_fault
#endif
extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl
tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on?
@@ -333,7 +333,7 @@
;;
andcm r18=0x10,r18 // bit 4=~address-bit(61)
cmp.ne p8,p0=r0,r23
-(p8) br.cond.spnt.many page_fault
+(p8) br.cond.spnt page_fault

dep r21=-1,r21,IA64_PSR_ED_BIT,1
dep r19=r17,r19,0,12 // insert PTE control bits into r19
@@ -429,7 +429,7 @@
;;
(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL?
dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry
-(p6) br.cond.spnt.many page_fault
+(p6) br.cond.spnt page_fault
mov b0=r30
br.sptk.many b0 // return to continuation point
END(nested_dtlb_miss)
@@ -622,7 +622,7 @@
mov r31=pr // prepare to save predicates
;;
cmp.eq p0,p7=r16,r17 // is this a system call? (p7 <- false, if so)
-(p7) br.cond.spnt.many non_syscall
+(p7) br.cond.spnt non_syscall

SAVE_MIN // uses r31; defines r2:

@@ -638,7 +638,7 @@
adds r3=8,r2 // set up second base pointer for SAVE_REST
;;
SAVE_REST
- br.call.sptk rpÞmine_args // clear NaT bits in (potential) syscall args
+ br.call.sptk.many rpÞmine_args // clear NaT bits in (potential) syscall args

mov r3%5
adds r15=-1024,r15 // r15 contains the syscall number---subtract 1024
@@ -680,7 +680,7 @@
st8 [r16]=r18 // store new value for cr.isr

(p8) br.call.sptk.many b6¶ // ignore this return addr
- br.cond.sptk.many ia64_trace_syscall
+ br.cond.sptk ia64_trace_syscall
// NOT REACHED
END(break_fault)

@@ -793,8 +793,8 @@
mov b6=r8
;;
cmp.ne p6,p0=0,r8
-(p6) br.call.dpnt b6¶ // call returns to ia64_leave_kernel
- br.sptk ia64_leave_kernel
+(p6) br.call.dpnt.many b6¶ // call returns to ia64_leave_kernel
+ br.sptk.many ia64_leave_kernel
END(dispatch_illegal_op_fault)

.align 1024
@@ -837,12 +837,12 @@
adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
;;
cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
- st8 [r15]=r8 // save orignal EAX in r1 (IA32 procs don't use the GP)
+ st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP)
;;
alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
;;
ld4 r8=[r14],8 // r8 = EAX (syscall number)
- mov r15"2 // sys_vfork - last implemented system call
+ mov r15"2 // last entry in system call table
;;
cmp.leu.unc p6,p7=r8,r15
ld4 out1=[r14],8 // r9 = ecx
@@ -871,7 +871,7 @@
;;
mov rp=r15
(p8) br.call.sptk.many b6¶
- br.cond.sptk.many ia32_trace_syscall
+ br.cond.sptk ia32_trace_syscall

non_ia32_syscall:
alloc r15=ar.pfs,0,0,2,0
@@ -1067,7 +1067,7 @@
mov r31=pr
;;
cmp4.eq p6,p0=0,r16
-(p6) br.sptk dispatch_illegal_op_fault
+(p6) br.sptk.many dispatch_illegal_op_fault
;;
mov r19$ // fault number
br.sptk.many dispatch_to_fault_handler
diff -urN linux-davidm/arch/ia64/kernel/mca.c linux-2.4.10-lia/arch/ia64/kernel/mca.c
--- linux-davidm/arch/ia64/kernel/mca.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/mca.c Mon Sep 24 21:49:34 2001
@@ -125,7 +125,7 @@
void
ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
{
- IA64_MCA_DEBUG("ia64_mca_cpe_int_handler : received interrupt. vector = %#x\n", cpe_irq);
+ IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. vector = %#x\n", cpe_irq);

/* Get the CMC error record and log it */
ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
@@ -200,12 +200,12 @@
{
/* Register the CPE interrupt vector with SAL */
if (ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0)) {
- printk("ia64_mca_platform_init : failed to register Corrected "
+ printk("ia64_mca_platform_init: failed to register Corrected "
"Platform Error interrupt vector with SAL.\n");
return;
}

- IA64_MCA_DEBUG("ia64_mca_platform_init : corrected platform error "
+ IA64_MCA_DEBUG("ia64_mca_platform_init: corrected platform error "
"vector %#x setup and enabled\n", cpev);
}

@@ -279,11 +279,11 @@
cmcv.cmcv_vector = IA64_CMC_VECTOR;
ia64_set_cmcv(cmcv.cmcv_regval);

- IA64_MCA_DEBUG("ia64_mca_platform_init : CPU %d corrected "
+ IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d corrected "
"machine check vector %#x setup and enabled.\n",
smp_processor_id(), IA64_CMC_VECTOR);

- IA64_MCA_DEBUG("ia64_mca_platform_init : CPU %d CMCV = %#016lx\n",
+ IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d CMCV = %#016lx\n",
smp_processor_id(), ia64_get_cmcv());
}

@@ -331,7 +331,7 @@
int rc;

if ((rc = memcmp((void *)test, (void *)target, sizeof(efi_guid_t)))) {
- IA64_MCA_DEBUG("ia64_mca_print : invalid guid = "
+ IA64_MCA_DEBUG("ia64_mca_print: invalid guid = "
"{ %08x, %04x, %04x, { %#02x, %#02x, %#02x, %#02x, "
"%#02x, %#02x, %#02x, %#02x, } } \n ",
test->data1, test->data2, test->data3, test->data4[0],
@@ -372,10 +372,10 @@
int i;
s64 rc;

- IA64_MCA_DEBUG("ia64_mca_init : begin\n");
+ IA64_MCA_DEBUG("ia64_mca_init: begin\n");

/* Clear the Rendez checkin flag for all cpus */
- for(i = 0 ; i < IA64_MAXCPUS; i++)
+ for(i = 0 ; i < NR_CPUS; i++)
ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;

/*
@@ -389,7 +389,7 @@
IA64_MCA_RENDEZ_TIMEOUT,
0)))
{
- printk("ia64_mca_init : Failed to register rendezvous interrupt "
+ printk("ia64_mca_init: Failed to register rendezvous interrupt "
"with SAL. rc = %ld\n", rc);
return;
}
@@ -400,12 +400,12 @@
IA64_MCA_WAKEUP_VECTOR,
0, 0)))
{
- printk("ia64_mca_init : Failed to register wakeup interrupt with SAL. rc = %ld\n",
+ printk("ia64_mca_init: Failed to register wakeup interrupt with SAL. rc = %ld\n",
rc);
return;
}

- IA64_MCA_DEBUG("ia64_mca_init : registered mca rendezvous spinloop and wakeup mech.\n");
+ IA64_MCA_DEBUG("ia64_mca_init: registered mca rendezvous spinloop and wakeup mech.\n");

ia64_mc_info.imi_mca_handler = __pa(mca_hldlr_ptr->fp);
/*
@@ -421,12 +421,12 @@
ia64_mc_info.imi_mca_handler_size,
0, 0, 0)))
{
- printk("ia64_mca_init : Failed to register os mca handler with SAL. rc = %ld\n",
+ printk("ia64_mca_init: Failed to register os mca handler with SAL. rc = %ld\n",
rc);
return;
}

- IA64_MCA_DEBUG("ia64_mca_init : registered os mca handler with SAL at 0x%lx, gp = 0x%lx\n",
+ IA64_MCA_DEBUG("ia64_mca_init: registered os mca handler with SAL at 0x%lx, gp = 0x%lx\n",
ia64_mc_info.imi_mca_handler, mca_hldlr_ptr->gp);

/*
@@ -438,7 +438,7 @@
ia64_mc_info.imi_slave_init_handler = __pa(slave_init_ptr->fp);
ia64_mc_info.imi_slave_init_handler_size = 0;

- IA64_MCA_DEBUG("ia64_mca_init : os init handler at %lx\n",
+ IA64_MCA_DEBUG("ia64_mca_init: os init handler at %lx\n",
ia64_mc_info.imi_monarch_init_handler);

/* Register the os init handler with SAL */
@@ -450,12 +450,12 @@
__pa(ia64_get_gp()),
ia64_mc_info.imi_slave_init_handler_size)))
{
- printk("ia64_mca_init : Failed to register m/s init handlers with SAL. rc = %ld\n",
+ printk("ia64_mca_init: Failed to register m/s init handlers with SAL. rc = %ld\n",
rc);
return;
}

- IA64_MCA_DEBUG("ia64_mca_init : registered os init handler with SAL\n");
+ IA64_MCA_DEBUG("ia64_mca_init: registered os init handler with SAL\n");

/*
* Configure the CMCI vector and handler. Interrupts for CMC are
@@ -486,7 +486,7 @@
}
ia64_mca_register_cpev(cpev);
} else
- printk("ia64_mca_init : Failed to get routed CPEI vector from ACPI.\n");
+ printk("ia64_mca_init: Failed to get routed CPEI vector from ACPI.\n");
}

/* Initialize the areas set aside by the OS to buffer the
@@ -732,7 +732,7 @@
void
ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
{
- IA64_MCA_DEBUG("ia64_mca_cmc_int_handler : received interrupt vector = %#x on CPU %d\n",
+ IA64_MCA_DEBUG("ia64_mca_cmc_int_handler: received interrupt vector = %#x on CPU %d\n",
cmc_irq, smp_processor_id());

/* Get the CMC error record and log it */
@@ -922,7 +922,7 @@
return total_len;
} else {
IA64_LOG_UNLOCK(sal_info_type);
- prfunc("ia64_log_get : Failed to retrieve SAL error record type %d\n",
+ prfunc("ia64_log_get: Failed to retrieve SAL error record type %d\n",
sal_info_type);
return 0;
}
@@ -1082,7 +1082,7 @@
u64 target_addr;

if (!cache_check_info->valid.check_info) {
- IA64_MCA_DEBUG("ia64_mca_log_print : invalid cache_check_info[%d]\n",i);
+ IA64_MCA_DEBUG("ia64_mca_log_print: invalid cache_check_info[%d]\n",i);
return; /* If check info data not valid, skip it */
}

@@ -1132,7 +1132,7 @@
pal_tlb_check_info_t *info;

if (!tlb_check_info->valid.check_info) {
- IA64_MCA_DEBUG("ia64_mca_log_print : invalid tlb_check_info[%d]\n", i);
+ IA64_MCA_DEBUG("ia64_mca_log_print: invalid tlb_check_info[%d]\n", i);
return; /* If check info data not valid, skip it */
}

@@ -1177,7 +1177,7 @@
/* or obtained from */

if (!bus_check_info->valid.check_info) {
- IA64_MCA_DEBUG("ia64_mca_log_print : invalid bus_check_info[%d]\n", i);
+ IA64_MCA_DEBUG("ia64_mca_log_print: invalid bus_check_info[%d]\n", i);
return; /* If check info data not valid, skip it */
}

@@ -1696,7 +1696,7 @@
#endif // MCA_PRT_XTRA_DATA for test only @FVL

if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) {
- IA64_MCA_DEBUG("ia64_mca_log_print : "
+ IA64_MCA_DEBUG("ia64_mca_log_print: "
"truncated SAL CMC error record. len = %d\n",
lh->len);
return;
@@ -1714,7 +1714,7 @@
#endif // MCA_PRT_XTRA_DATA for test only @FVL

if (verify_guid((void *)&slsh->guid, (void *)&(SAL_PROC_DEV_ERR_SECT_GUID))) {
- IA64_MCA_DEBUG("ia64_mca_log_print : unsupported record section\n");
+ IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n");
continue;
}

@@ -1725,7 +1725,7 @@
printk);
}

- IA64_MCA_DEBUG("ia64_mca_log_print : "
+ IA64_MCA_DEBUG("ia64_mca_log_print: "
"found %d sections in SAL CMC error record. len = %d\n",
n_sects, lh->len);
if (!n_sects) {
@@ -1759,7 +1759,7 @@
#endif // MCA_PRT_XTRA_DATA for test only @FVL

if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) {
- IA64_MCA_DEBUG("ia64_mca_log_print : "
+ IA64_MCA_DEBUG("ia64_mca_log_print: "
"truncated SAL error record. len = %d\n",
lh->len);
return;
@@ -1826,12 +1826,12 @@
ia64_log_plat_bus_err_info_print((sal_log_plat_bus_err_info_t *)slsh,
prfunc);
} else {
- IA64_MCA_DEBUG("ia64_mca_log_print : unsupported record section\n");
+ IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n");
continue;
}
}

- IA64_MCA_DEBUG("ia64_mca_log_print : found %d sections in SAL error record. len = %d\n",
+ IA64_MCA_DEBUG("ia64_mca_log_print: found %d sections in SAL error record. len = %d\n",
n_sects, lh->len);
if (!n_sects) {
prfunc("No Platform Error Info Sections found\n");
diff -urN linux-davidm/arch/ia64/kernel/mca_asm.S linux-2.4.10-lia/arch/ia64/kernel/mca_asm.S
--- linux-davidm/arch/ia64/kernel/mca_asm.S Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/mca_asm.S Mon Sep 24 21:49:52 2001
@@ -116,7 +116,7 @@
// call our handler
movl r2=ia64_mca_ucmc_handler;;
mov b6=r2;;
- br.call.sptk.few b0¶;;
+ br.call.sptk.many b0¶;;
.ret0:
// Revert back to physical mode before going back to SAL
PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4)
@@ -724,7 +724,7 @@
adds out0\x16,sp // out0 = pointer to pt_regs
;;

- br.call.sptk.few rp=ia64_init_handler
+ br.call.sptk.many rp=ia64_init_handler
.ret1:

return_from_init:
diff -urN linux-davidm/arch/ia64/kernel/pal.S linux-2.4.10-lia/arch/ia64/kernel/pal.S
--- linux-davidm/arch/ia64/kernel/pal.S Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/pal.S Mon Sep 24 21:50:01 2001
@@ -4,8 +4,9 @@
*
* Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999-2000 David Mosberger <davidm@hpl.hp.com>
- * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 1999-2001 Hewlett-Packard Co
+ * David Mosberger <davidm@hpl.hp.com>
+ * Stephane Eranian <eranian@hpl.hp.com>
*
* 05/22/2000 eranian Added support for stacked register calls
* 05/24/2000 eranian Added support for physical mode static calls
@@ -31,7 +32,7 @@
movl r2=pal_entry_point
;;
st8 [r2]=in0
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(ia64_pal_handler_init)

/*
@@ -41,7 +42,7 @@
*/
GLOBAL_ENTRY(ia64_pal_default_handler)
mov r8=-1
- br.cond.sptk.few rp
+ br.cond.sptk.many rp
END(ia64_pal_default_handler)

/*
@@ -79,13 +80,13 @@
;;
(p6) srlz.i
mov rp = r8
- br.cond.sptk.few b7
+ br.cond.sptk.many b7
1: mov psr.l = loc3
mov ar.pfs = loc1
mov rp = loc0
;;
srlz.d // seralize restoration of psr.l
- br.ret.sptk.few b0
+ br.ret.sptk.many b0
END(ia64_pal_call_static)

/*
@@ -120,7 +121,7 @@
mov rp = loc0
;;
srlz.d // serialize restoration of psr.l
- br.ret.sptk.few b0
+ br.ret.sptk.many b0
END(ia64_pal_call_stacked)

/*
@@ -173,13 +174,13 @@
or loc3=loc3,r17 // add in psr the bits to set
;;
andcm r16=loc3,r16 // removes bits to clear from psr
- br.call.sptk.few rp=ia64_switch_mode
+ br.call.sptk.many rp=ia64_switch_mode
.ret1: mov rp = r8 // install return address (physical)
- br.cond.sptk.few b7
+ br.cond.sptk.many b7
1:
mov ar.rsc=0 // put RSE in enforced lazy, LE mode
mov r16=loc3 // r16= original psr
- br.call.sptk.few rp=ia64_switch_mode // return to virtual mode
+ br.call.sptk.many rp=ia64_switch_mode // return to virtual mode
.ret2:
mov psr.l = loc3 // restore init PSR

@@ -188,7 +189,7 @@
;;
mov ar.rsc=loc4 // restore RSE configuration
srlz.d // seralize restoration of psr.l
- br.ret.sptk.few b0
+ br.ret.sptk.many b0
END(ia64_pal_call_phys_static)

/*
@@ -227,13 +228,13 @@
mov b7 = loc2 // install target to branch reg
;;
andcm r16=loc3,r16 // removes bits to clear from psr
- br.call.sptk.few rp=ia64_switch_mode
+ br.call.sptk.many rp=ia64_switch_mode
.ret6:
br.call.sptk.many rp· // now make the call
.ret7:
mov ar.rsc=0 // put RSE in enforced lazy, LE mode
mov r16=loc3 // r16= original psr
- br.call.sptk.few rp=ia64_switch_mode // return to virtual mode
+ br.call.sptk.many rp=ia64_switch_mode // return to virtual mode

.ret8: mov psr.l = loc3 // restore init PSR
mov ar.pfs = loc1
@@ -241,6 +242,6 @@
;;
mov ar.rsc=loc4 // restore RSE configuration
srlz.d // seralize restoration of psr.l
- br.ret.sptk.few b0
+ br.ret.sptk.many b0
END(ia64_pal_call_phys_stacked)

diff -urN linux-davidm/arch/ia64/kernel/perfmon.c linux-2.4.10-lia/arch/ia64/kernel/perfmon.c
--- linux-davidm/arch/ia64/kernel/perfmon.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/perfmon.c Mon Sep 24 21:50:18 2001
@@ -33,13 +33,12 @@
#include <asm/signal.h>
#include <asm/system.h>
#include <asm/system.h>
-#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/delay.h> /* for ia64_get_itc() */

#ifdef CONFIG_PERFMON

-#define PFM_VERSION "0.2"
+#define PFM_VERSION "0.3"
#define PFM_SMPL_HDR_VERSION 1

#define PMU_FIRST_COUNTER 4 /* first generic counter */
@@ -53,6 +52,7 @@
#define PFM_DISABLE 0xa6 /* freeze only */
#define PFM_RESTART 0xcf
#define PFM_CREATE_CONTEXT 0xa7
+#define PFM_DESTROY_CONTEXT 0xa8
/*
* 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
@@ -61,6 +61,8 @@
#define PFM_DEBUG_ON 0xe0
#define PFM_DEBUG_OFF 0xe1

+#define PFM_DEBUG_BASE PFM_DEBUG_ON
+

/*
* perfmon API flags
@@ -69,7 +71,8 @@
#define PFM_FL_INHERIT_ONCE 0x01 /* clone pfm_context only once across fork() */
#define PFM_FL_INHERIT_ALL 0x02 /* always clone pfm_context across fork() */
#define PFM_FL_SMPL_OVFL_NOBLOCK 0x04 /* do not block on sampling buffer overflow */
-#define PFM_FL_SYSTEMWIDE 0x08 /* create a systemwide context */
+#define PFM_FL_SYSTEM_WIDE 0x08 /* create a system wide context */
+#define PFM_FL_EXCL_INTR 0x10 /* exclude interrupt from system wide monitoring */

/*
* PMC API flags
@@ -88,7 +91,7 @@
#endif

#define PMC_IS_IMPL(i) (i < pmu_conf.num_pmcs && pmu_conf.impl_regs[i>>6] & (1<< (i&~(64-1))))
-#define PMD_IS_IMPL(i) (i < pmu_conf.num_pmds && pmu_conf.impl_regs[4+(i>>6)] & (1<< (i&~(64-1))))
+#define PMD_IS_IMPL(i) (i < pmu_conf.num_pmds && 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))

@@ -198,7 +201,8 @@
unsigned int noblock:1; /* block/don't block on overflow with notification */
unsigned int system:1; /* do system wide monitoring */
unsigned int frozen:1; /* pmu must be kept frozen on ctxsw in */
- unsigned int reserved:27;
+ unsigned int exclintr:1;/* exlcude interrupts from system wide monitoring */
+ unsigned int reserved:26;
} pfm_context_flags_t;

typedef struct pfm_context {
@@ -208,26 +212,33 @@
unsigned long ctx_iear_counter; /* which PMD holds I-EAR */
unsigned long ctx_btb_counter; /* which PMD holds BTB */

- pid_t ctx_notify_pid; /* who to notify on overflow */
- int ctx_notify_sig; /* XXX: SIGPROF or other */
- pfm_context_flags_t ctx_flags; /* block/noblock */
- pid_t ctx_creator; /* pid of creator (debug) */
- unsigned long ctx_ovfl_regs; /* which registers just overflowed (notification) */
- unsigned long ctx_smpl_regs; /* which registers to record on overflow */
+ spinlock_t ctx_notify_lock;
+ pfm_context_flags_t ctx_flags; /* block/noblock */
+ int ctx_notify_sig; /* XXX: SIGPROF or other */
+ struct task_struct *ctx_notify_task; /* who to notify on overflow */
+ struct task_struct *ctx_creator; /* pid of creator (debug) */
+
+ unsigned long ctx_ovfl_regs; /* which registers just overflowed (notification) */
+ unsigned long ctx_smpl_regs; /* which registers to record on overflow */
+
+ struct semaphore ctx_restart_sem; /* use for blocking notification mode */

- struct semaphore ctx_restart_sem; /* use for blocking notification mode */
+ unsigned long ctx_used_pmds[4]; /* bitmask of used PMD (speedup ctxsw) */
+ unsigned long ctx_used_pmcs[4]; /* bitmask of used PMC (speedup ctxsw) */

pfm_counter_t ctx_pmds[IA64_NUM_PMD_COUNTERS]; /* XXX: size should be dynamic */
+
} pfm_context_t;

+#define CTX_USED_PMD(ctx,n) (ctx)->ctx_used_pmds[(n)>>6] |= 1<< ((n) % 64)
+#define CTX_USED_PMC(ctx,n) (ctx)->ctx_used_pmcs[(n)>>6] |= 1<< ((n) % 64)
+
#define ctx_fl_inherit ctx_flags.inherit
#define ctx_fl_noblock ctx_flags.noblock
#define ctx_fl_system ctx_flags.system
#define ctx_fl_frozen ctx_flags.frozen
+#define ctx_fl_exclintr ctx_flags.exclintr

-#define CTX_IS_DEAR(c,n) ((c)->ctx_dear_counter = (n))
-#define CTX_IS_IEAR(c,n) ((c)->ctx_iear_counter = (n))
-#define CTX_IS_BTB(c,n) ((c)->ctx_btb_counter = (n))
#define CTX_OVFL_NOBLOCK(c) ((c)->ctx_fl_noblock = 1)
#define CTX_INHERIT_MODE(c) ((c)->ctx_fl_inherit)
#define CTX_HAS_SMPL(c) ((c)->ctx_smpl_buf != NULL)
@@ -235,17 +246,15 @@
static pmu_config_t pmu_conf;

/* for debug only */
-static unsigned long pfm_debug=0; /* 0= nodebug, >0= debug output on */
+static int pfm_debug=0; /* 0= nodebug, >0= debug output on */
+
#define DBprintk(a) \
do { \
- if (pfm_debug >0) { printk(__FUNCTION__" "); printk a; } \
+ if (pfm_debug >0) { printk(__FUNCTION__" %d: ", __LINE__); printk a; } \
} while (0);

-static void perfmon_softint(unsigned long ignored);
static void ia64_reset_pmu(void);

-DECLARE_TASKLET(pfm_tasklet, perfmon_softint, 0);
-
/*
* structure used to pass information between the interrupt handler
* and the tasklet.
@@ -257,26 +266,42 @@
unsigned long bitvect; /* which counters have overflowed */
} notification_info_t;

-#define notification_is_invalid(i) (i->to_pid < 2)

-/* will need to be cache line padded */
-static notification_info_t notify_info[NR_CPUS];
+typedef struct {
+ unsigned long pfs_proc_sessions;
+ unsigned long pfs_sys_session; /* can only be 0/1 */
+ unsigned long pfs_dfl_dcr; /* XXX: hack */
+ unsigned int pfs_pp;
+} pfm_session_t;

-/*
- * We force cache line alignment to avoid false sharing
- * given that we have one entry per CPU.
- */
-static struct {
+struct {
struct task_struct *owner;
} ____cacheline_aligned pmu_owners[NR_CPUS];
-/* helper macros */
+
+
+/*
+ * helper macros
+ */
#define SET_PMU_OWNER(t) do { pmu_owners[smp_processor_id()].owner = (t); } while(0);
#define PMU_OWNER() pmu_owners[smp_processor_id()].owner

+#ifdef CONFIG_SMP
+#define PFM_CAN_DO_LAZY() (smp_num_cpus=1 && pfs_info.pfs_sys_session=0)
+#else
+#define PFM_CAN_DO_LAZY() (pfs_info.pfs_sys_session=0)
+#endif
+
+static void pfm_lazy_save_regs (struct task_struct *ta);
+
/* for debug only */
static struct proc_dir_entry *perfmon_dir;

/*
+ * XXX: hack to indicate that a system wide monitoring session is active
+ */
+static pfm_session_t pfs_info;
+
+/*
* finds the number of PM(C|D) registers given
* the bitvector returned by PAL
*/
@@ -340,8 +365,7 @@
static inline unsigned long
kvirt_to_pa(unsigned long adr)
{
- __u64 pa;
- __asm__ __volatile__ ("tpa %0 = %1" : "=r"(pa) : "r"(adr) : "memory");
+ __u64 pa = ia64_tpa(adr);
DBprintk(("kv2pa(%lx-->%lx)\n", adr, pa));
return pa;
}
@@ -569,25 +593,44 @@
static int
pfx_is_sane(pfreq_context_t *pfx)
{
+ int ctx_flags;
+
/* valid signal */
- if (pfx->notify_sig < 1 || pfx->notify_sig >= _NSIG) return 0;
+ //if (pfx->notify_sig < 1 || pfx->notify_sig >= _NSIG) return -EINVAL;
+ if (pfx->notify_sig !=0 && pfx->notify_sig != SIGPROF) return -EINVAL;

/* cannot send to process 1, 0 means do not notify */
- if (pfx->notify_pid < 0 || pfx->notify_pid = 1) return 0;
+ if (pfx->notify_pid < 0 || pfx->notify_pid = 1) return -EINVAL;
+
+ ctx_flags = pfx->flags;

+ if (ctx_flags & PFM_FL_SYSTEM_WIDE) {
+#ifdef CONFIG_SMP
+ if (smp_num_cpus > 1) {
+ printk("perfmon: system wide monitoring on SMP not yet supported\n");
+ return -EINVAL;
+ }
+#endif
+ if ((ctx_flags & PFM_FL_SMPL_OVFL_NOBLOCK) = 0) {
+ printk("perfmon: system wide monitoring cannot use blocking notification mode\n");
+ return -EINVAL;
+ }
+ }
/* probably more to add here */

- return 1;
+ return 0;
}

static int
-pfm_context_create(struct task_struct *task, int flags, perfmon_req_t *req)
+pfm_context_create(int flags, perfmon_req_t *req)
{
pfm_context_t *ctx;
+ struct task_struct *task = NULL;
perfmon_req_t tmp;
void *uaddr = NULL;
- int ret = -EFAULT;
+ int ret;
int ctx_flags;
+ pid_t pid;

/* to go away */
if (flags) {
@@ -596,48 +639,156 @@

if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;

+ ret = pfx_is_sane(&tmp.pfr_ctx);
+ if (ret < 0) return ret;
+
ctx_flags = tmp.pfr_ctx.flags;

- /* not yet supported */
- if (ctx_flags & PFM_FL_SYSTEMWIDE) return -EINVAL;
+ if (ctx_flags & PFM_FL_SYSTEM_WIDE) {
+ /*
+ * XXX: This is not AT ALL SMP safe
+ */
+ if (pfs_info.pfs_proc_sessions > 0) return -EBUSY;
+ if (pfs_info.pfs_sys_session > 0) return -EBUSY;
+
+ pfs_info.pfs_sys_session = 1;

- if (!pfx_is_sane(&tmp.pfr_ctx)) return -EINVAL;
+ } else if (pfs_info.pfs_sys_session >0) {
+ /* no per-process monitoring while there is a system wide session */
+ return -EBUSY;
+ } else
+ pfs_info.pfs_proc_sessions++;

ctx = pfm_context_alloc();
- if (!ctx) return -ENOMEM;
+ if (!ctx) goto error;
+
+ /* record the creator (debug only) */
+ ctx->ctx_creator = current;
+
+ pid = tmp.pfr_ctx.notify_pid;
+
+ spin_lock_init(&ctx->ctx_notify_lock);
+
+ if (pid = current->pid) {
+ ctx->ctx_notify_task = task = current;
+ current->thread.pfm_context = ctx;
+
+ atomic_set(&current->thread.pfm_notifiers_check, 1);

- /* record who the creator is (for debug) */
- ctx->ctx_creator = task->pid;
+ } else if (pid!=0) {
+ read_lock(&tasklist_lock);
+
+ task = find_task_by_pid(pid);
+ if (task) {
+ /*
+ * record who to notify
+ */
+ ctx->ctx_notify_task = task;
+
+ /*
+ * make visible
+ * must be done inside critical section
+ *
+ * if the initialization does not go through it is still
+ * okay because child will do the scan for nothing which
+ * won't hurt.
+ */
+ current->thread.pfm_context = ctx;
+
+ /*
+ * will cause task to check on exit for monitored
+ * processes that would notify it. see release_thread()
+ * Note: the scan MUST be done in release thread, once the
+ * task has been detached from the tasklist otherwise you are
+ * exposed to race conditions.
+ */
+ atomic_add(1, &task->thread.pfm_notifiers_check);
+ }
+ read_unlock(&tasklist_lock);
+ }
+
+ /*
+ * notification process does not exist
+ */
+ if (pid != 0 && task = NULL) {
+ ret = -EINVAL;
+ goto buffer_error;
+ }

- ctx->ctx_notify_pid = tmp.pfr_ctx.notify_pid;
ctx->ctx_notify_sig = SIGPROF; /* siginfo imposes a fixed signal */

if (tmp.pfr_ctx.smpl_entries) {
DBprintk((" sampling entries=%ld\n",tmp.pfr_ctx.smpl_entries));
- if ((ret=pfm_smpl_buffer_alloc(ctx, tmp.pfr_ctx.smpl_regs, tmp.pfr_ctx.smpl_entries, &uaddr)) ) goto buffer_error;
+
+ ret = pfm_smpl_buffer_alloc(ctx, tmp.pfr_ctx.smpl_regs,
+ tmp.pfr_ctx.smpl_entries, &uaddr);
+ if (ret<0) goto buffer_error;
+
tmp.pfr_ctx.smpl_vaddr = uaddr;
}
/* initialization of context's flags */
- ctx->ctx_fl_inherit = ctx_flags & PFM_FL_INHERIT_MASK;
- ctx->ctx_fl_noblock = (ctx_flags & PFM_FL_SMPL_OVFL_NOBLOCK) ? 1 : 0;
- ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEMWIDE) ? 1: 0;
- ctx->ctx_fl_frozen = 0;
+ ctx->ctx_fl_inherit = ctx_flags & PFM_FL_INHERIT_MASK;
+ ctx->ctx_fl_noblock = (ctx_flags & PFM_FL_SMPL_OVFL_NOBLOCK) ? 1 : 0;
+ ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0;
+ ctx->ctx_fl_exclintr = (ctx_flags & PFM_FL_EXCL_INTR) ? 1: 0;
+ ctx->ctx_fl_frozen = 0;
+
+ /*
+ * Keep track of the pmds we want to sample
+ * XXX: may be we don't need to save/restore the DEAR/IEAR pmds
+ * but we do need the BTB for sure. This is because of a hardware
+ * buffer of 1 only for non-BTB pmds.
+ */
+ ctx->ctx_used_pmds[0] = tmp.pfr_ctx.smpl_regs;
+ ctx->ctx_used_pmcs[0] = 1; /* always save/restore PMC[0] */

sema_init(&ctx->ctx_restart_sem, 0); /* init this semaphore to locked */

- if (copy_to_user(req, &tmp, sizeof(tmp))) goto buffer_error;

- DBprintk((" context=%p, pid=%d notify_sig %d notify_pid=%d\n",(void *)ctx, task->pid, ctx->ctx_notify_sig, ctx->ctx_notify_pid));
- DBprintk((" context=%p, pid=%d flags=0x%x inherit=%d noblock=%d system=%d\n",(void *)ctx, task->pid, ctx_flags, ctx->ctx_fl_inherit, ctx->ctx_fl_noblock, ctx->ctx_fl_system));
+ if (copy_to_user(req, &tmp, sizeof(tmp))) {
+ ret = -EFAULT;
+ goto buffer_error;
+ }
+
+ DBprintk((" context=%p, pid=%d notify_sig %d notify_task=%p\n",(void *)ctx, current->pid, ctx->ctx_notify_sig, ctx->ctx_notify_task));
+ DBprintk((" context=%p, pid=%d flags=0x%x inherit=%d noblock=%d system=%d\n",(void *)ctx, current->pid, ctx_flags, ctx->ctx_fl_inherit, ctx->ctx_fl_noblock, ctx->ctx_fl_system));
+
+ /*
+ * when no notification is required, we can make this visible at the last moment
+ */
+ if (pid = 0) current->thread.pfm_context = ctx;
+
+ /*
+ * by default, we always include interrupts for system wide
+ * DCR.pp is set by default to zero by kernel in cpu_init()
+ */
+ if (ctx->ctx_fl_system) {
+ if (ctx->ctx_fl_exclintr = 0) {
+ unsigned long dcr = ia64_get_dcr();
+
+ ia64_set_dcr(dcr|IA64_DCR_PP);
+ /*
+ * keep track of the kernel default value
+ */
+ pfs_info.pfs_dfl_dcr = dcr;

- /* link with task */
- task->thread.pfm_context = ctx;
+ DBprintk((" dcr.pp is set\n"));
+ }
+ }

return 0;

buffer_error:
- vfree(ctx);
-
+ pfm_context_free(ctx);
+error:
+ /*
+ * undo session reservation
+ */
+ if (ctx_flags & PFM_FL_SYSTEM_WIDE) {
+ pfs_info.pfs_sys_session = 0;
+ } else {
+ pfs_info.pfs_proc_sessions--;
+ }
return ret;
}

@@ -658,10 +809,10 @@
/* upper part is ignored on rval */
ia64_set_pmd(cnum, ctx->ctx_pmds[i].smpl_rval);

- /*
+ /*
* we must reset BTB index (clears pmd16.full to make
* sure we do not report the same branches twice.
- * The non-blocking case in handled in update_counters().
+ * The non-blocking case in handled in update_counters()
*/
if (cnum = ctx->ctx_btb_counter) {
DBprintk(("reseting PMD16\n"));
@@ -669,6 +820,8 @@
}
}
}
+ /* just in case ! */
+ ctx->ctx_ovfl_regs = 0;
}

static int
@@ -706,20 +859,23 @@
} else if (PMC_IS_BTB(&tmp.pfr_reg.reg_value)) {
ctx->ctx_btb_counter = cnum;
}
-
+#if 0
if (tmp.pfr_reg.reg_flags & PFM_REGFL_OVFL_NOTIFY)
ctx->ctx_pmds[cnum - PMU_FIRST_COUNTER].flags |= PFM_REGFL_OVFL_NOTIFY;
+#endif
}
-
+ /* keep track of what we use */
+ CTX_USED_PMC(ctx, cnum);
ia64_set_pmc(cnum, tmp.pfr_reg.reg_value);
- DBprintk((" setting PMC[%ld]=0x%lx flags=0x%x\n", cnum, tmp.pfr_reg.reg_value, ctx->ctx_pmds[cnum - PMU_FIRST_COUNTER].flags));
+
+ DBprintk((" setting PMC[%ld]=0x%lx flags=0x%x used_pmcs=0%lx\n", cnum, tmp.pfr_reg.reg_value, ctx->ctx_pmds[cnum - PMU_FIRST_COUNTER].flags, ctx->ctx_used_pmcs[0]));

}
/*
* we have to set this here event hough we haven't necessarily started monitoring
* because we may be context switched out
*/
- th->flags |= IA64_THREAD_PM_VALID;
+ if (ctx->ctx_fl_system=0) th->flags |= IA64_THREAD_PM_VALID;

return 0;
}
@@ -752,25 +908,32 @@
ctx->ctx_pmds[k].val = tmp.pfr_reg.reg_value & ~pmu_conf.perf_ovfl_val;
ctx->ctx_pmds[k].smpl_rval = tmp.pfr_reg.reg_smpl_reset;
ctx->ctx_pmds[k].ovfl_rval = tmp.pfr_reg.reg_ovfl_reset;
+
+ if (tmp.pfr_reg.reg_flags & PFM_REGFL_OVFL_NOTIFY)
+ ctx->ctx_pmds[cnum - PMU_FIRST_COUNTER].flags |= PFM_REGFL_OVFL_NOTIFY;
}
+ /* keep track of what we use */
+ CTX_USED_PMD(ctx, cnum);

/* writes to unimplemented part is ignored, so this is safe */
ia64_set_pmd(cnum, tmp.pfr_reg.reg_value);

/* to go away */
ia64_srlz_d();
- DBprintk((" setting PMD[%ld]: pmd.val=0x%lx pmd.ovfl_rval=0x%lx pmd.smpl_rval=0x%lx pmd=%lx\n",
+ DBprintk((" setting PMD[%ld]: ovfl_notify=%d pmd.val=0x%lx pmd.ovfl_rval=0x%lx pmd.smpl_rval=0x%lx pmd=%lx used_pmds=0%lx\n",
cnum,
+ PMD_OVFL_NOTIFY(ctx, cnum - PMU_FIRST_COUNTER),
ctx->ctx_pmds[k].val,
ctx->ctx_pmds[k].ovfl_rval,
ctx->ctx_pmds[k].smpl_rval,
- ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val));
+ ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val,
+ ctx->ctx_used_pmds[0]));
}
/*
* we have to set this here event hough we haven't necessarily started monitoring
* because we may be context switched out
*/
- th->flags |= IA64_THREAD_PM_VALID;
+ if (ctx->ctx_fl_system=0) th->flags |= IA64_THREAD_PM_VALID;

return 0;
}
@@ -821,7 +984,8 @@
}
tmp.pfr_reg.reg_value = val;

- DBprintk((" reading PMD[%ld]=0x%lx reg=0x%lx ctx_val=0x%lx pmc=0x%lx\n", tmp.pfr_reg.reg_num, val, reg_val, ctx_val, ia64_get_pmc(tmp.pfr_reg.reg_num)));
+ DBprintk((" reading PMD[%ld]=0x%lx reg=0x%lx ctx_val=0x%lx pmc=0x%lx\n",
+ tmp.pfr_reg.reg_num, val, reg_val, ctx_val, ia64_get_pmc(tmp.pfr_reg.reg_num)));

if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
}
@@ -836,7 +1000,7 @@
void *sem = &ctx->ctx_restart_sem;

if (task = current) {
- DBprintk((" restartig self %d frozen=%d \n", current->pid, ctx->ctx_fl_frozen));
+ DBprintk((" restarting self %d frozen=%d \n", current->pid, ctx->ctx_fl_frozen));

pfm_reset_regs(ctx);

@@ -885,6 +1049,23 @@
return 0;
}

+/*
+ * system-wide mode: propagate activation/desactivation throughout the tasklist
+ *
+ * XXX: does not work for SMP, of course
+ */
+static void
+pfm_process_tasklist(int cmd)
+{
+ struct task_struct *p;
+ struct pt_regs *regs;
+
+ for_each_task(p) {
+ regs = (struct pt_regs *)((unsigned long)p + IA64_STK_OFFSET);
+ regs--;
+ ia64_psr(regs)->pp = cmd;
+ }
+}

static int
do_perfmonctl (struct task_struct *task, int cmd, int flags, perfmon_req_t *req, int count, struct pt_regs *regs)
@@ -895,19 +1076,26 @@

memset(&tmp, 0, sizeof(tmp));

+ if (ctx = NULL && cmd != PFM_CREATE_CONTEXT && cmd < PFM_DEBUG_BASE) {
+ DBprintk((" PFM_WRITE_PMCS: no context for task %d\n", task->pid));
+ return -EINVAL;
+ }
+
switch (cmd) {
case PFM_CREATE_CONTEXT:
/* a context has already been defined */
if (ctx) return -EBUSY;

- /* may be a temporary limitation */
+ /*
+ * cannot directly create a context in another process
+ */
if (task != current) return -EINVAL;

if (req = NULL || count != 1) return -EINVAL;

if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;

- return pfm_context_create(task, flags, req);
+ return pfm_context_create(flags, req);

case PFM_WRITE_PMCS:
/* we don't quite support this right now */
@@ -915,10 +1103,6 @@

if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;

- if (!ctx) {
- DBprintk((" PFM_WRITE_PMCS: no context for task %d\n", task->pid));
- return -EINVAL;
- }
return pfm_write_pmcs(task, req, count);

case PFM_WRITE_PMDS:
@@ -927,45 +1111,41 @@

if (!access_ok(VERIFY_READ, req, sizeof(struct perfmon_req_t)*count)) return -EFAULT;

- if (!ctx) {
- DBprintk((" PFM_WRITE_PMDS: no context for task %d\n", task->pid));
- return -EINVAL;
- }
return pfm_write_pmds(task, req, count);

case PFM_START:
/* we don't quite support this right now */
if (task != current) return -EINVAL;

- if (!ctx) {
- DBprintk((" PFM_START: no context for task %d\n", task->pid));
- return -EINVAL;
- }
+ if (PMU_OWNER() && PMU_OWNER() != current && PFM_CAN_DO_LAZY()) pfm_lazy_save_regs(PMU_OWNER());

SET_PMU_OWNER(current);

/* will start monitoring right after rfi */
ia64_psr(regs)->up = 1;
+ ia64_psr(regs)->pp = 1;
+
+ if (ctx->ctx_fl_system) {
+ pfm_process_tasklist(1);
+ pfs_info.pfs_pp = 1;
+ }

/*
* mark the state as valid.
* this will trigger save/restore at context switch
*/
- th->flags |= IA64_THREAD_PM_VALID;
+ if (ctx->ctx_fl_system=0) th->flags |= IA64_THREAD_PM_VALID;

ia64_set_pmc(0, 0);
ia64_srlz_d();

- break;
+ break;

case PFM_ENABLE:
/* we don't quite support this right now */
if (task != current) return -EINVAL;

- if (!ctx) {
- DBprintk((" PFM_ENABLE: no context for task %d\n", task->pid));
- return -EINVAL;
- }
+ if (PMU_OWNER() && PMU_OWNER() != current && PFM_CAN_DO_LAZY()) pfm_lazy_save_regs(PMU_OWNER());

/* reset all registers to stable quiet state */
ia64_reset_pmu();
@@ -983,7 +1163,7 @@
* mark the state as valid.
* this will trigger save/restore at context switch
*/
- th->flags |= IA64_THREAD_PM_VALID;
+ if (ctx->ctx_fl_system=0) th->flags |= IA64_THREAD_PM_VALID;

/* simply unfreeze */
ia64_set_pmc(0, 0);
@@ -997,54 +1177,41 @@
/* simply freeze */
ia64_set_pmc(0, 1);
ia64_srlz_d();
+ /*
+ * XXX: cannot really toggle IA64_THREAD_PM_VALID
+ * but context is still considered valid, so any
+ * read request would return something valid. Same
+ * thing when this task terminates (pfm_flush_regs()).
+ */
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;

- if (!ctx) {
- DBprintk((" PFM_READ_PMDS: no context for task %d\n", task->pid));
- return -EINVAL;
- }
return pfm_read_pmds(task, req, count);

case PFM_STOP:
/* we don't quite support this right now */
if (task != current) return -EINVAL;

- ia64_set_pmc(0, 1);
- ia64_srlz_d();
-
+ /* simply stop monitors, not PMU */
ia64_psr(regs)->up = 0;
+ ia64_psr(regs)->pp = 0;

- th->flags &= ~IA64_THREAD_PM_VALID;
-
- SET_PMU_OWNER(NULL);
-
- /* we probably will need some more cleanup here */
- break;
-
- case PFM_DEBUG_ON:
- printk(" debugging on\n");
- pfm_debug = 1;
- break;
+ if (ctx->ctx_fl_system) {
+ pfm_process_tasklist(0);
+ pfs_info.pfs_pp = 0;
+ }

- case PFM_DEBUG_OFF:
- printk(" debugging off\n");
- pfm_debug = 0;
break;

case PFM_RESTART: /* temporary, will most likely end up as a PFM_ENABLE */

- if ((th->flags & IA64_THREAD_PM_VALID) = 0) {
+ if ((th->flags & IA64_THREAD_PM_VALID) = 0 && ctx->ctx_fl_system=0) {
printk(" PFM_RESTART not monitoring\n");
return -EINVAL;
}
- if (!ctx) {
- printk(" PFM_RESTART no ctx for %d\n", task->pid);
- return -EINVAL;
- }
if (CTX_OVFL_NOBLOCK(ctx) = 0 && ctx->ctx_fl_frozen=0) {
printk("task %d without pmu_frozen set\n", task->pid);
return -EINVAL;
@@ -1052,6 +1219,37 @@

return pfm_do_restart(task); /* we only look at first entry */

+ case PFM_DESTROY_CONTEXT:
+ /* we don't quite support this right now */
+ if (task != current) return -EINVAL;
+
+ /* first stop monitors */
+ ia64_psr(regs)->up = 0;
+ ia64_psr(regs)->pp = 0;
+
+ /* then freeze PMU */
+ ia64_set_pmc(0, 1);
+ ia64_srlz_d();
+
+ /* don't save/restore on context switch */
+ if (ctx->ctx_fl_system =0) task->thread.flags &= ~IA64_THREAD_PM_VALID;
+
+ SET_PMU_OWNER(NULL);
+
+ /* now free context and related state */
+ pfm_context_exit(task);
+ break;
+
+ case PFM_DEBUG_ON:
+ printk("perfmon debugging on\n");
+ pfm_debug = 1;
+ break;
+
+ case PFM_DEBUG_OFF:
+ printk("perfmon debugging off\n");
+ pfm_debug = 0;
+ break;
+
default:
DBprintk((" UNknown command 0x%x\n", cmd));
return -EINVAL;
@@ -1088,11 +1286,8 @@
/* XXX: pid interface is going away in favor of pfm context */
if (pid != current->pid) {
read_lock(&tasklist_lock);
- {
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- }
+
+ child = find_task_by_pid(pid);

if (!child) goto abort_call;

@@ -1115,93 +1310,44 @@
return ret;
}

-
-/*
- * This function is invoked on the exit path of the kernel. Therefore it must make sure
- * it does does modify the caller's input registers (in0-in7) in case of entry by system call
- * which can be restarted. That's why it's declared as a system call and all 8 possible args
- * are declared even though not used.
- */
#if __GNUC__ >= 3
void asmlinkage
-pfm_overflow_notify(void)
+pfm_block_on_overflow(void)
#else
void asmlinkage
-pfm_overflow_notify(u64 arg0, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7)
+pfm_block_on_overflow(u64 arg0, u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7)
#endif
{
- struct task_struct *task;
struct thread_struct *th = &current->thread;
pfm_context_t *ctx = current->thread.pfm_context;
- struct siginfo si;
int ret;

/*
- * do some sanity checks first
- */
- if (!ctx) {
- printk("perfmon: process %d has no PFM context\n", current->pid);
- return;
- }
- if (ctx->ctx_notify_pid < 2) {
- printk("perfmon: process %d invalid notify_pid=%d\n", current->pid, ctx->ctx_notify_pid);
- return;
- }
-
- DBprintk((" current=%d ctx=%p bv=0%lx\n", current->pid, (void *)ctx, ctx->ctx_ovfl_regs));
- /*
* NO matter what notify_pid is,
* we clear overflow, won't notify again
*/
- th->pfm_pend_notify = 0;
+ th->pfm_must_block = 0;

/*
- * When measuring in kernel mode and non-blocking fashion, it is possible to
- * get an overflow while executing this code. Therefore the state of pend_notify
- * and ovfl_regs can be altered. The important point is not to loose any notification.
- * It is fine to get called for nothing. To make sure we do collect as much state as
- * possible, update_counters() always uses |= to add bit to the ovfl_regs field.
- *
- * In certain cases, it is possible to come here, with ovfl_regs = 0;
- *
- * XXX: pend_notify and ovfl_regs could be merged maybe !
+ * do some sanity checks first
*/
- if (ctx->ctx_ovfl_regs = 0) {
- DBprintk(("perfmon: spurious overflow notification from pid %d\n", current->pid));
+ if (!ctx) {
+ printk("perfmon: process %d has no PFM context\n", current->pid);
return;
}
- read_lock(&tasklist_lock);
-
- task = find_task_by_pid(ctx->ctx_notify_pid);
-
- if (task) {
- si.si_signo = ctx->ctx_notify_sig;
- si.si_errno = 0;
- si.si_code = PROF_OVFL; /* goes to user */
- si.si_addr = NULL;
- si.si_pid = current->pid; /* who is sending */
- si.si_pfm_ovfl = ctx->ctx_ovfl_regs;
-
- DBprintk((" SIGPROF to %d @ %p\n", task->pid, (void *)task));
-
- /* must be done with tasklist_lock locked */
- ret = send_sig_info(ctx->ctx_notify_sig, &si, task);
- if (ret != 0) {
- DBprintk((" send_sig_info(process %d, SIGPROF)=%d\n", ctx->ctx_notify_pid, ret));
- task = NULL; /* will cause return */
- }
- } else {
- printk("perfmon: notify_pid %d not found\n", ctx->ctx_notify_pid);
+ if (ctx->ctx_notify_task = 0) {
+ printk("perfmon: process %d has no task to notify\n", current->pid);
+ return;
}

- read_unlock(&tasklist_lock);
+ DBprintk((" current=%d task=%d\n", current->pid, ctx->ctx_notify_task->pid));

- /* now that we have released the lock handle error condition */
- if (!task || CTX_OVFL_NOBLOCK(ctx)) {
- /* we clear all pending overflow bits in noblock mode */
- ctx->ctx_ovfl_regs = 0;
+ /* should not happen */
+ if (CTX_OVFL_NOBLOCK(ctx)) {
+ printk("perfmon: process %d non-blocking ctx should not be here\n", current->pid);
return;
}
+
DBprintk((" CPU%d %d before sleep\n", smp_processor_id(), current->pid));

/*
@@ -1225,9 +1371,6 @@

pfm_reset_regs(ctx);

- /* now we can clear this mask */
- ctx->ctx_ovfl_regs = 0;
-
/*
* Unlock sampling buffer and reset index atomically
* XXX: not really needed when blocking
@@ -1246,84 +1389,14 @@
}
}

-static void
-perfmon_softint(unsigned long ignored)
-{
- notification_info_t *info;
- int my_cpu = smp_processor_id();
- struct task_struct *task;
- struct siginfo si;
-
- info = notify_info+my_cpu;
-
- DBprintk((" CPU%d current=%d to_pid=%d from_pid=%d bv=0x%lx\n", \
- smp_processor_id(), current->pid, info->to_pid, info->from_pid, info->bitvect));
-
- /* assumption check */
- if (info->from_pid = info->to_pid) {
- DBprintk((" Tasklet assumption error: from=%d tor=%d\n", info->from_pid, info->to_pid));
- return;
- }
-
- if (notification_is_invalid(info)) {
- DBprintk((" invalid notification information\n"));
- return;
- }
-
- /* sanity check */
- if (info->to_pid = 1) {
- DBprintk((" cannot notify init\n"));
- return;
- }
- /*
- * XXX: needs way more checks here to make sure we send to a task we have control over
- */
- read_lock(&tasklist_lock);
-
- task = find_task_by_pid(info->to_pid);
-
- DBprintk((" after find %p\n", (void *)task));
-
- if (task) {
- int ret;
-
- si.si_signo = SIGPROF;
- si.si_errno = 0;
- si.si_code = PROF_OVFL; /* goes to user */
- si.si_addr = NULL;
- si.si_pid = info->from_pid; /* who is sending */
- si.si_pfm_ovfl = info->bitvect;
-
- DBprintk((" SIGPROF to %d @ %p\n", task->pid, (void *)task));
-
- /* must be done with tasklist_lock locked */
- ret = send_sig_info(SIGPROF, &si, task);
- if (ret != 0)
- DBprintk((" send_sig_info(process %d, SIGPROF)=%d\n", info->to_pid, ret));
-
- /* invalidate notification */
- info->to_pid = info->from_pid = 0;
- info->bitvect = 0;
- }
-
- read_unlock(&tasklist_lock);
-
- DBprintk((" after unlock %p\n", (void *)task));
-
- if (!task) {
- printk("perfmon: CPU%d cannot find process %d\n", smp_processor_id(), info->to_pid);
- }
-}
-
/*
* main overflow processing routine.
* it can be called from the interrupt path or explicitely during the context switch code
* Return:
- * 0 : do not unfreeze the PMU
- * 1 : PMU can be unfrozen
+ * new value of pmc[0]. if 0x0 then unfreeze, else keep frozen
*/
-static unsigned long
-update_counters (struct task_struct *ta, u64 pmc0, struct pt_regs *regs)
+unsigned long
+update_counters (struct task_struct *task, u64 pmc0, struct pt_regs *regs)
{
unsigned long mask, i, cnum;
struct thread_struct *th;
@@ -1331,7 +1404,9 @@
unsigned long bv = 0;
int my_cpu = smp_processor_id();
int ret = 1, buffer_is_full = 0;
- int ovfl_is_smpl, can_notify, need_reset_pmd16=0;
+ int ovfl_has_long_recovery, can_notify, need_reset_pmd16=0;
+ struct siginfo si;
+
/*
* 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
@@ -1345,25 +1420,23 @@
* valid one, i.e. the one that caused the interrupt.
*/

- if (ta = NULL) {
+ if (task = NULL) {
DBprintk((" owners[%d]=NULL\n", my_cpu));
return 0x1;
}
- th = &ta->thread;
+ th = &task->thread;
ctx = th->pfm_context;

/*
* XXX: debug test
* Don't think this could happen given upfront tests
*/
- if ((th->flags & IA64_THREAD_PM_VALID) = 0) {
- DBprintk(("perfmon: Spurious overflow interrupt: process %d not using perfmon\n",
- ta->pid));
+ if ((th->flags & IA64_THREAD_PM_VALID) = 0 && ctx->ctx_fl_system = 0) {
+ printk("perfmon: Spurious overflow interrupt: process %d not using perfmon\n", task->pid);
return 0x1;
}
if (!ctx) {
- DBprintk(("perfmon: Spurious overflow interrupt: process %d has no PFM context\n",
- ta->pid));
+ printk("perfmon: Spurious overflow interrupt: process %d has no PFM context\n", task->pid);
return 0;
}

@@ -1371,16 +1444,21 @@
* sanity test. Should never happen
*/
if ((pmc0 & 0x1 )= 0) {
- printk("perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n", ta->pid, pmc0);
+ printk("perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n", task->pid, pmc0);
return 0x0;
}

mask = pmc0 >> PMU_FIRST_COUNTER;

- DBprintk(("pmc0=0x%lx pid=%d\n", pmc0, ta->pid));
-
- DBprintk(("ctx is in %s mode\n", CTX_OVFL_NOBLOCK(ctx) ? "NO-BLOCK" : "BLOCK"));
+ DBprintk(("pmc0=0x%lx pid=%d owner=%d iip=0x%lx, ctx is in %s mode used_pmds=0x%lx used_pmcs=0x%lx\n",
+ pmc0, task->pid, PMU_OWNER()->pid, regs->cr_iip,
+ CTX_OVFL_NOBLOCK(ctx) ? "NO-BLOCK" : "BLOCK",
+ ctx->ctx_used_pmds[0],
+ ctx->ctx_used_pmcs[0]));

+ /*
+ * XXX: need to record sample only when an EAR/BTB has overflowed
+ */
if (CTX_HAS_SMPL(ctx)) {
pfm_smpl_buffer_desc_t *psb = ctx->ctx_smpl_buf;
unsigned long *e, m, idx=0;
@@ -1388,11 +1466,15 @@
int j;

idx = ia64_fetch_and_add(1, &psb->psb_index);
- DBprintk((" trying to record index=%ld entries=%ld\n", idx, psb->psb_entries));
+ DBprintk((" recording index=%ld entries=%ld\n", idx, psb->psb_entries));

/*
* XXX: there is a small chance that we could run out on index before resetting
* but index is unsigned long, so it will take some time.....
+ * We use > instead of = because fetch_and_add() is off by one (see below)
+ *
+ * This case can happen in non-blocking mode or with multiple processes.
+ * For non-blocking, we need to reload and continue.
*/
if (idx > psb->psb_entries) {
buffer_is_full = 1;
@@ -1404,7 +1486,7 @@

h = (perfmon_smpl_entry_t *)(((char *)psb->psb_addr) + idx*(psb->psb_entry_size));

- h->pid = ta->pid;
+ h->pid = task->pid;
h->cpu = my_cpu;
h->rate = 0;
h->ip = regs ? regs->cr_iip : 0x0; /* where did the fault happened */
@@ -1414,6 +1496,7 @@
h->stamp = perfmon_get_stamp();

e = (unsigned long *)(h+1);
+
/*
* selectively store PMDs in increasing index number
*/
@@ -1422,35 +1505,66 @@
if (PMD_IS_COUNTER(j))
*e = ctx->ctx_pmds[j-PMU_FIRST_COUNTER].val
+ (ia64_get_pmd(j) & pmu_conf.perf_ovfl_val);
- else
+ else {
*e = ia64_get_pmd(j); /* slow */
+ }
DBprintk((" e=%p pmd%d =0x%lx\n", (void *)e, j, *e));
e++;
}
}
- /* make the new entry visible to user, needs to be atomic */
+ /*
+ * make the new entry visible to user, needs to be atomic
+ */
ia64_fetch_and_add(1, &psb->psb_hdr->hdr_count);

DBprintk((" index=%ld entries=%ld hdr_count=%ld\n", idx, psb->psb_entries, psb->psb_hdr->hdr_count));
-
- /* sampling buffer full ? */
+ /*
+ * sampling buffer full ?
+ */
if (idx = (psb->psb_entries-1)) {
- bv = mask;
+ /*
+ * will cause notification, cannot be 0
+ */
+ bv = mask << PMU_FIRST_COUNTER;
+
buffer_is_full = 1;

DBprintk((" sampling buffer full must notify bv=0x%lx\n", bv));

- if (!CTX_OVFL_NOBLOCK(ctx)) goto buffer_full;
+ /*
+ * we do not reload here, when context is blocking
+ */
+ if (!CTX_OVFL_NOBLOCK(ctx)) goto no_reload;
+
/*
* here, we have a full buffer but we are in non-blocking mode
- * so we need to reloads overflowed PMDs with sampling reset values
- * and restart
+ * so we need to reload overflowed PMDs with sampling reset values
+ * and restart right away.
*/
}
+ /* FALL THROUGH */
}
reload_pmds:
- ovfl_is_smpl = CTX_OVFL_NOBLOCK(ctx) && buffer_is_full;
- can_notify = CTX_HAS_SMPL(ctx) = 0 && ctx->ctx_notify_pid;
+
+ /*
+ * in the case of a non-blocking context, we reload
+ * with the ovfl_rval when no user notification is taking place (short recovery)
+ * otherwise when the buffer is full which requires user interaction) then we use
+ * smpl_rval which is the long_recovery path (disturbance introduce by user execution).
+ *
+ * XXX: implies that when buffer is full then there is always notification.
+ */
+ ovfl_has_long_recovery = CTX_OVFL_NOBLOCK(ctx) && buffer_is_full;
+
+ /*
+ * XXX: CTX_HAS_SMPL() should really be something like CTX_HAS_SMPL() and is activated,i.e.,
+ * one of the PMC is configured for EAR/BTB.
+ *
+ * When sampling, we can only notify when the sampling buffer is full.
+ */
+ can_notify = CTX_HAS_SMPL(ctx) = 0 && ctx->ctx_notify_task;
+
+ DBprintk((" ovfl_has_long_recovery=%d can_notify=%d\n", ovfl_has_long_recovery, can_notify));

for (i = 0, cnum = PMU_FIRST_COUNTER; mask ; cnum++, i++, mask >>= 1) {

@@ -1472,7 +1586,7 @@
DBprintk((" pmod[%ld].val=0x%lx pmd=0x%lx\n", i, ctx->ctx_pmds[i].val, ia64_get_pmd(cnum)&pmu_conf.perf_ovfl_val));

if (can_notify && PMD_OVFL_NOTIFY(ctx, i)) {
- DBprintk((" CPU%d should notify process %d with signal %d\n", my_cpu, ctx->ctx_notify_pid, ctx->ctx_notify_sig));
+ DBprintk((" CPU%d should notify task %p with signal %d\n", my_cpu, ctx->ctx_notify_task, ctx->ctx_notify_sig));
bv |= 1 << i;
} else {
DBprintk((" CPU%d PMD[%ld] overflow, no notification\n", my_cpu, cnum));
@@ -1483,93 +1597,150 @@
*/

/* writes to upper part are ignored, so this is safe */
- if (ovfl_is_smpl) {
- DBprintk((" CPU%d PMD[%ld] reloaded with smpl_val=%lx\n", my_cpu, cnum,ctx->ctx_pmds[i].smpl_rval));
+ if (ovfl_has_long_recovery) {
+ DBprintk((" CPU%d PMD[%ld] reload with smpl_val=%lx\n", my_cpu, cnum,ctx->ctx_pmds[i].smpl_rval));
ia64_set_pmd(cnum, ctx->ctx_pmds[i].smpl_rval);
} else {
- DBprintk((" CPU%d PMD[%ld] reloaded with ovfl_val=%lx\n", my_cpu, cnum,ctx->ctx_pmds[i].smpl_rval));
+ DBprintk((" CPU%d PMD[%ld] reload with ovfl_val=%lx\n", my_cpu, cnum,ctx->ctx_pmds[i].smpl_rval));
ia64_set_pmd(cnum, ctx->ctx_pmds[i].ovfl_rval);
}
}
if (cnum = ctx->ctx_btb_counter) need_reset_pmd16=1;
}
/*
- * In case of BTB, overflow
- * we need to reset the BTB index.
+ * In case of BTB overflow we need to reset the BTB index.
*/
if (need_reset_pmd16) {
DBprintk(("reset PMD16\n"));
ia64_set_pmd(16, 0);
}
-buffer_full:
- /* see pfm_overflow_notify() on details for why we use |= here */
- ctx->ctx_ovfl_regs |= bv;

- /* nobody to notify, return and unfreeze */
+no_reload:
+
+ /*
+ * some counters overflowed, but they did not require
+ * user notification, so after having reloaded them above
+ * we simply restart
+ */
if (!bv) return 0x0;

+ ctx->ctx_ovfl_regs = bv; /* keep track of what to reset when unblocking */
+ /*
+ * Now we know that:
+ * - we have some counters which overflowed (contains in bv)
+ * - someone has asked to be notified on overflow.
+ */
+
+
+ /*
+ * If the notification task is still present, then notify_task is non
+ * null. It is clean by that task if it ever exits before we do.
+ */

- if (ctx->ctx_notify_pid = ta->pid) {
- struct siginfo si;
+ if (ctx->ctx_notify_task) {

si.si_errno = 0;
si.si_addr = NULL;
- si.si_pid = ta->pid; /* who is sending */
-
+ si.si_pid = task->pid; /* who is sending */

si.si_signo = ctx->ctx_notify_sig; /* is SIGPROF */
si.si_code = PROF_OVFL; /* goes to user */
si.si_pfm_ovfl = bv;

+
/*
- * in this case, we don't stop the task, we let it go on. It will
- * necessarily go to the signal handler (if any) when it goes back to
- * user mode.
+ * when the target of the signal is not ourself, we have to be more
+ * careful. The notify_task may being cleared by the target task itself
+ * in release_thread(). We must ensure mutual exclusion here such that
+ * the signal is delivered (even to a dying task) safely.
*/
- DBprintk((" sending %d notification to self %d\n", si.si_signo, ta->pid));
-

- /* this call is safe in an interrupt handler */
- ret = send_sig_info(ctx->ctx_notify_sig, &si, ta);
- if (ret != 0)
- printk(" send_sig_info(process %d, SIGPROF)=%d\n", ta->pid, ret);
- /*
- * no matter if we block or not, we keep PMU frozen and do not unfreeze on ctxsw
- */
- ctx->ctx_fl_frozen = 1;
+ if (ctx->ctx_notify_task != current) {
+ /*
+ * grab the notification lock for this task
+ */
+ spin_lock(&ctx->ctx_notify_lock);

- } else {
-#if 0
/*
- * The tasklet is guaranteed to be scheduled for this CPU only
+ * now notify_task cannot be modified until we're done
+ * if NULL, they it got modified while we were in the handler
*/
- notify_info[my_cpu].to_pid = ctx->notify_pid;
- notify_info[my_cpu].from_pid = ta->pid; /* for debug only */
- notify_info[my_cpu].bitvect = bv;
- /* tasklet is inserted and active */
- tasklet_schedule(&pfm_tasklet);
-#endif
+ if (ctx->ctx_notify_task = NULL) {
+ spin_unlock(&ctx->ctx_notify_lock);
+ goto lost_notify;
+ }
/*
- * stored the vector of overflowed registers for use in notification
- * mark that a notification/blocking is pending (arm the trap)
+ * required by send_sig_info() to make sure the target
+ * task does not disappear on us.
*/
- th->pfm_pend_notify = 1;
+ read_lock(&tasklist_lock);
+ }
+ /*
+ * in this case, we don't stop the task, we let it go on. It will
+ * necessarily go to the signal handler (if any) when it goes back to
+ * user mode.
+ */
+ DBprintk((" %d sending %d notification to %d\n", task->pid, si.si_signo, ctx->ctx_notify_task->pid));

+
+ /*
+ * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock
+ */
+ ret = send_sig_info(ctx->ctx_notify_sig, &si, ctx->ctx_notify_task);
+ if (ret != 0) printk(" send_sig_info(process %d, SIGPROF)=%d\n", ctx->ctx_notify_task->pid, ret);
/*
- * if we do block, then keep PMU frozen until restart
+ * now undo the protections in order
*/
- if (!CTX_OVFL_NOBLOCK(ctx)) ctx->ctx_fl_frozen = 1;
+ if (ctx->ctx_notify_task != current) {
+ read_unlock(&tasklist_lock);
+ spin_unlock(&ctx->ctx_notify_lock);
+ }
+
+ /*
+ * if we block set the pfm_must_block bit
+ * when in block mode, we can effectively block only when the notified
+ * task is not self, otherwise we would deadlock.
+ * in this configuration, the notification is sent, the task will not
+ * block on the way back to user mode, but the PMU will be kept frozen
+ * until PFM_RESTART.
+ * Note that here there is still a race condition with notify_task
+ * possibly being nullified behind our back, but this is fine because
+ * it can only be changed to NULL which by construction, can only be
+ * done when notify_task != current. So if it was already different
+ * before, changing it to NULL will still maintain this invariant.
+ * Of course, when it is equal to current it cannot change at this point.
+ */
+ if (!CTX_OVFL_NOBLOCK(ctx) && ctx->ctx_notify_task != current) {
+ th->pfm_must_block = 1; /* will cause blocking */
+ }
+ } else {
+lost_notify:
+ DBprintk((" notification task has disappeared !\n"));
+ /*
+ * for a non-blocking context, we make sure we do not fall into the pfm_overflow_notify()
+ * trap. Also in the case of a blocking context with lost notify process, then we do not
+ * want to block either (even though it is interruptible). In this case, the PMU will be kept
+ * frozen and the process will run to completion without monitoring enabled.
+ *
+ * Of course, we cannot loose notify process when self-monitoring.
+ */
+ th->pfm_must_block = 0;

- DBprintk((" process %d notify ovfl_regs=0x%lx\n", ta->pid, bv));
}
/*
- * keep PMU frozen (and overflowed bits cleared) when we have to stop,
- * otherwise return a resume 'value' for PMC[0]
- *
- * XXX: maybe that's enough to get rid of ctx_fl_frozen ?
+ * if we block, we keep the PMU frozen. If non-blocking we restart.
+ * in the case of non-blocking were the notify process is lost, we also
+ * restart.
*/
- DBprintk((" will return pmc0=0x%x\n",ctx->ctx_fl_frozen ? 0x1 : 0x0));
+ if (!CTX_OVFL_NOBLOCK(ctx))
+ ctx->ctx_fl_frozen = 1;
+ else
+ ctx->ctx_fl_frozen = 0;
+
+ DBprintk((" reload pmc0=0x%x must_block=%ld\n",
+ ctx->ctx_fl_frozen ? 0x1 : 0x0, th->pfm_must_block));
+
return ctx->ctx_fl_frozen ? 0x1 : 0x0;
}

@@ -1599,8 +1770,7 @@
ia64_set_pmc(0, pmc0);
ia64_srlz_d();
} else {
- DBprintk(("perfmon: Spurious PMU overflow interrupt: pmc0=0x%lx owner=%p\n",
- pmc0, (void *)PMU_OWNER()));
+ printk("perfmon: Spurious PMU overflow interrupt: pmc0=0x%lx owner=%p\n", pmc0, (void *)PMU_OWNER());
}
}

@@ -1612,10 +1782,17 @@
u64 pmc0 = ia64_get_pmc(0);
int i;

- p += sprintf(p, "PMC[0]=%lx\nPerfmon debug: %s\n", pmc0, pfm_debug ? "On" : "Off");
+ p += sprintf(p, "CPU%d.pmc[0]=%lx\nPerfmon debug: %s\n", smp_processor_id(), pmc0, pfm_debug ? "On" : "Off");
+ p += sprintf(p, "proc_sessions=%lu sys_sessions=%lu\n",
+ pfs_info.pfs_proc_sessions,
+ pfs_info.pfs_sys_session);
+
for(i=0; i < NR_CPUS; i++) {
- if (cpu_is_online(i))
- p += sprintf(p, "CPU%d.PMU %d\n", i, pmu_owners[i].owner ? pmu_owners[i].owner->pid: 0);
+ if (cpu_is_online(i)) {
+ p += sprintf(p, "CPU%d.pmu_owner: %-6d\n",
+ i,
+ pmu_owners[i].owner ? pmu_owners[i].owner->pid: -1);
+ }
}
return p - page;
}
@@ -1698,21 +1875,19 @@
ia64_srlz_d();
}

-/*
- * XXX: for system wide this function MUST never be called
- */
void
pfm_save_regs (struct task_struct *ta)
{
struct task_struct *owner;
+ pfm_context_t *ctx;
struct thread_struct *t;
u64 pmc0, psr;
+ unsigned long mask;
int i;

- if (ta = NULL) {
- panic(__FUNCTION__" task is NULL\n");
- }
- t = &ta->thread;
+ t = &ta->thread;
+ ctx = ta->thread.pfm_context;
+
/*
* We must make sure that we don't loose any potential overflow
* interrupt while saving PMU context. In this code, external
@@ -1732,7 +1907,7 @@
* in kernel.
* By now, we could still have an overflow interrupt in-flight.
*/
- __asm__ __volatile__ ("rum psr.up;;"::: "memory");
+ __asm__ __volatile__ ("rsm psr.up|psr.pp;;"::: "memory");

/*
* Mark the PMU as not owned
@@ -1761,7 +1936,6 @@
* next process does not start with monitoring on if not requested
*/
ia64_set_pmc(0, 1);
- ia64_srlz_d();

/*
* Check for overflow bits and proceed manually if needed
@@ -1772,87 +1946,104 @@
* next time the task exits from the kernel.
*/
if (pmc0 & ~0x1) {
- if (owner != ta) printk(__FUNCTION__" owner=%p task=%p\n", (void *)owner, (void *)ta);
- DBprintk((__FUNCTION__" Warning: pmc[0]=0x%lx explicit call\n", pmc0));
-
- pmc0 = update_counters(owner, pmc0, NULL);
+ update_counters(owner, pmc0, NULL);
/* we will save the updated version of pmc0 */
}
-
/*
* restore PSR for context switch to save
*/
__asm__ __volatile__ ("mov psr.l=%0;; srlz.i;;"::"r"(psr): "memory");

+ /*
+ * we do not save registers if we can do lazy
+ */
+ if (PFM_CAN_DO_LAZY()) {
+ SET_PMU_OWNER(owner);
+ return;
+ }

/*
* XXX needs further optimization.
* Also must take holes into account
*/
- for (i=0; i< pmu_conf.num_pmds; i++) {
- t->pmd[i] = ia64_get_pmd(i);
+ mask = ctx->ctx_used_pmds[0];
+ for (i=0; mask; i++, mask>>=1) {
+ if (mask & 0x1) t->pmd[i] =ia64_get_pmd(i);
}

/* skip PMC[0], we handle it separately */
- for (i=1; i< pmu_conf.num_pmcs; i++) {
- t->pmc[i] = ia64_get_pmc(i);
+ mask = ctx->ctx_used_pmcs[0]>>1;
+ for (i=1; mask; i++, mask>>=1) {
+ if (mask & 0x1) t->pmc[i] = ia64_get_pmc(i);
}
-
/*
* Throughout this code we could have gotten an overflow interrupt. It is transformed
* into a spurious interrupt as soon as we give up pmu ownership.
*/
}

-void
-pfm_load_regs (struct task_struct *ta)
+static void
+pfm_lazy_save_regs (struct task_struct *ta)
{
- struct thread_struct *t = &ta->thread;
- pfm_context_t *ctx = ta->thread.pfm_context;
+ pfm_context_t *ctx;
+ struct thread_struct *t;
+ unsigned long mask;
int i;

+ DBprintk((" on [%d] by [%d]\n", ta->pid, current->pid));
+
+ t = &ta->thread;
+ ctx = ta->thread.pfm_context;
/*
* XXX needs further optimization.
* Also must take holes into account
*/
- for (i=0; i< pmu_conf.num_pmds; i++) {
- ia64_set_pmd(i, t->pmd[i]);
+ mask = ctx->ctx_used_pmds[0];
+ for (i=0; mask; i++, mask>>=1) {
+ if (mask & 0x1) t->pmd[i] =ia64_get_pmd(i);
}
-
- /* skip PMC[0] to avoid side effects */
- for (i=1; i< pmu_conf.num_pmcs; i++) {
- ia64_set_pmc(i, t->pmc[i]);
+
+ /* skip PMC[0], we handle it separately */
+ mask = ctx->ctx_used_pmcs[0]>>1;
+ for (i=1; mask; i++, mask>>=1) {
+ if (mask & 0x1) t->pmc[i] = ia64_get_pmc(i);
}
+ SET_PMU_OWNER(NULL);
+}
+
+void
+pfm_load_regs (struct task_struct *ta)
+{
+ struct thread_struct *t = &ta->thread;
+ pfm_context_t *ctx = ta->thread.pfm_context;
+ struct task_struct *owner;
+ unsigned long mask;
+ int i;
+
+ owner = PMU_OWNER();
+ if (owner = ta) goto skip_restore;
+ if (owner) pfm_lazy_save_regs(owner);

- /*
- * 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
- */
SET_PMU_OWNER(ta);

-#if 0
- /*
- * check if we had pending overflow before context switching out
- * If so, we invoke the handler manually, i.e. simulate interrupt.
- *
- * XXX: given that we do not use the tasklet anymore to stop, we can
- * move this back to the pfm_save_regs() routine.
- */
- if (t->pmc[0] & ~0x1) {
- /* freeze set in pfm_save_regs() */
- DBprintk((" pmc[0]=0x%lx manual interrupt\n",t->pmc[0]));
- update_counters(ta, t->pmc[0], NULL);
+ mask = ctx->ctx_used_pmds[0];
+ for (i=0; mask; i++, mask>>=1) {
+ if (mask & 0x1) ia64_set_pmd(i, t->pmd[i]);
}
-#endif

+ /* skip PMC[0] to avoid side effects */
+ mask = ctx->ctx_used_pmcs[0]>>1;
+ for (i=1; mask; i++, mask>>=1) {
+ if (mask & 0x1) ia64_set_pmc(i, t->pmc[i]);
+ }
+skip_restore:
/*
* unfreeze only when possible
*/
if (ctx->ctx_fl_frozen = 0) {
ia64_set_pmc(0, 0);
ia64_srlz_d();
+ /* place where we potentially (kernel level) start monitoring again */
}
}

@@ -2002,7 +2193,7 @@

/* clears all PMD registers */
for(i=0;i< pmu_conf.num_pmds; i++) {
- if (PMD_IS_IMPL(i)) ia64_set_pmd(i,0);
+ if (PMD_IS_IMPL(i)) ia64_set_pmd(i,0);
}
ia64_srlz_d();
}
@@ -2011,7 +2202,7 @@
* task is the newly created task
*/
int
-pfm_inherit(struct task_struct *task)
+pfm_inherit(struct task_struct *task, struct pt_regs *regs)
{
pfm_context_t *ctx = current->thread.pfm_context;
pfm_context_t *nctx;
@@ -2019,12 +2210,22 @@
int i, cnum;

/*
+ * bypass completely for system wide
+ */
+ if (pfs_info.pfs_sys_session) {
+ DBprintk((" enabling psr.pp for %d\n", task->pid));
+ ia64_psr(regs)->pp = pfs_info.pfs_pp;
+ return 0;
+ }
+
+ /*
* takes care of easiest case first
*/
if (CTX_INHERIT_MODE(ctx) = PFM_FL_INHERIT_NONE) {
DBprintk((" removing PFM context for %d\n", task->pid));
task->thread.pfm_context = NULL;
- task->thread.pfm_pend_notify = 0;
+ task->thread.pfm_must_block = 0;
+ atomic_set(&task->thread.pfm_notifiers_check, 0);
/* copy_thread() clears IA64_THREAD_PM_VALID */
return 0;
}
@@ -2034,9 +2235,11 @@
/* copy content */
*nctx = *ctx;

- if (ctx->ctx_fl_inherit = PFM_FL_INHERIT_ONCE) {
+ if (CTX_INHERIT_MODE(ctx) = PFM_FL_INHERIT_ONCE) {
nctx->ctx_fl_inherit = PFM_FL_INHERIT_NONE;
+ atomic_set(&task->thread.pfm_notifiers_check, 0);
DBprintk((" downgrading to INHERIT_NONE for %d\n", task->pid));
+ pfs_info.pfs_proc_sessions++;
}

/* initialize counters in new context */
@@ -2058,7 +2261,7 @@
sema_init(&nctx->ctx_restart_sem, 0); /* reset this semaphore to locked */

/* clear pending notification */
- th->pfm_pend_notify = 0;
+ th->pfm_must_block = 0;

/* link with new task */
th->pfm_context = nctx;
@@ -2077,7 +2280,10 @@
return 0;
}

-/* called from exit_thread() */
+/*
+ * called from release_thread(), at this point this task is not in the
+ * tasklist anymore
+ */
void
pfm_context_exit(struct task_struct *task)
{
@@ -2093,16 +2299,126 @@
pfm_smpl_buffer_desc_t *psb = ctx->ctx_smpl_buf;

/* if only user left, then remove */
- DBprintk((" pid %d: task %d sampling psb->refcnt=%d\n", current->pid, task->pid, psb->psb_refcnt.counter));
+ DBprintk((" [%d] [%d] psb->refcnt=%d\n", current->pid, task->pid, psb->psb_refcnt.counter));

if (atomic_dec_and_test(&psb->psb_refcnt) ) {
rvfree(psb->psb_hdr, psb->psb_size);
vfree(psb);
- DBprintk((" pid %d: cleaning task %d sampling buffer\n", current->pid, task->pid ));
+ DBprintk((" [%d] cleaning [%d] sampling buffer\n", current->pid, task->pid ));
+ }
+ }
+ DBprintk((" [%d] cleaning [%d] pfm_context @%p\n", current->pid, task->pid, (void *)ctx));
+
+ /*
+ * To avoid getting the notified task scan the entire process list
+ * when it exits because it would have pfm_notifiers_check set, we
+ * decrease it by 1 to inform the task, that one less task is going
+ * to send it notification. each new notifer increases this field by
+ * 1 in pfm_context_create(). Of course, there is race condition between
+ * decreasing the value and the notified task exiting. The danger comes
+ * from the fact that we have a direct pointer to its task structure
+ * thereby bypassing the tasklist. We must make sure that if we have
+ * notify_task!= NULL, the target task is still somewhat present. It may
+ * already be detached from the tasklist but that's okay. Note that it is
+ * okay if we 'miss the deadline' and the task scans the list for nothing,
+ * it will affect performance but not correctness. The correctness is ensured
+ * by using the notify_lock whic prevents the notify_task from changing on us.
+ * Once holdhing this lock, if we see notify_task!= NULL, then it will stay like
+ * that until we release the lock. If it is NULL already then we came too late.
+ */
+ spin_lock(&ctx->ctx_notify_lock);
+
+ if (ctx->ctx_notify_task) {
+ DBprintk((" [%d] [%d] atomic_sub on [%d] notifiers=%u\n", current->pid, task->pid,
+ ctx->ctx_notify_task->pid,
+ atomic_read(&ctx->ctx_notify_task->thread.pfm_notifiers_check)));
+
+ atomic_sub(1, &ctx->ctx_notify_task->thread.pfm_notifiers_check);
+ }
+
+ spin_unlock(&ctx->ctx_notify_lock);
+
+ if (ctx->ctx_fl_system) {
+ /*
+ * if included interrupts (true by default), then reset
+ * to get default value
+ */
+ if (ctx->ctx_fl_exclintr = 0) {
+ /*
+ * reload kernel default DCR value
+ */
+ ia64_set_dcr(pfs_info.pfs_dfl_dcr);
+ DBprintk((" restored dcr to 0x%lx\n", pfs_info.pfs_dfl_dcr));
}
+ /*
+ * free system wide session slot
+ */
+ pfs_info.pfs_sys_session = 0;
+ } else {
+ pfs_info.pfs_proc_sessions--;
}
- DBprintk((" pid %d: task %d pfm_context is freed @%p\n", current->pid, task->pid, (void *)ctx));
+
pfm_context_free(ctx);
+ /*
+ * clean pfm state in thread structure,
+ */
+ task->thread.pfm_context = NULL;
+ task->thread.pfm_must_block = 0;
+ /* pfm_notifiers is cleaned in pfm_cleanup_notifiers() */
+
+}
+
+void
+pfm_cleanup_notifiers(struct task_struct *task)
+{
+ struct task_struct *p;
+ pfm_context_t *ctx;
+
+ DBprintk((" [%d] called\n", task->pid));
+
+ read_lock(&tasklist_lock);
+
+ for_each_task(p) {
+ /*
+ * It is safe to do the 2-step test here, because thread.ctx
+ * is cleaned up only in release_thread() and at that point
+ * the task has been detached from the tasklist which is an
+ * operation which uses the write_lock() on the tasklist_lock
+ * so it cannot run concurrently to this loop. So we have the
+ * guarantee that if we find p and it has a perfmon ctx then
+ * it is going to stay like this for the entire execution of this
+ * loop.
+ */
+ ctx = p->thread.pfm_context;
+
+ DBprintk((" [%d] scanning task [%d] ctx=%p\n", task->pid, p->pid, ctx));
+
+ if (ctx && ctx->ctx_notify_task = task) {
+ DBprintk((" trying for notifier %d in %d\n", task->pid, p->pid));
+ /*
+ * the spinlock is required to take care of a race condition
+ * with the send_sig_info() call. We must make sure that
+ * either the send_sig_info() completes using a valid task,
+ * or the notify_task is cleared before the send_sig_info()
+ * can pick up a stale value. Note that by the time this
+ * function is executed the 'task' is already detached from the
+ * tasklist. The problem is that the notifiers have a direct
+ * pointer to it. It is okay to send a signal to a task in this
+ * stage, it simply will have no effect. But it is better than sending
+ * to a completely destroyed task or worse to a new task using the same
+ * task_struct address.
+ */
+ spin_lock(&ctx->ctx_notify_lock);
+
+ ctx->ctx_notify_task = NULL;
+
+ spin_unlock(&ctx->ctx_notify_lock);
+
+ DBprintk((" done for notifier %d in %d\n", task->pid, p->pid));
+ }
+ }
+ read_unlock(&tasklist_lock);
+
}

#else /* !CONFIG_PERFMON */
diff -urN linux-davidm/arch/ia64/kernel/process.c linux-2.4.10-lia/arch/ia64/kernel/process.c
--- linux-davidm/arch/ia64/kernel/process.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/process.c Mon Sep 24 23:22:59 2001
@@ -63,7 +63,8 @@
{
unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;

- printk("\npsr : %016lx ifs : %016lx ip : [<%016lx>]\n",
+ printk("\nPid: %d, comm: %20s\n", current->pid, current->comm);
+ printk("psr : %016lx ifs : %016lx ip : [<%016lx>]\n",
regs->cr_ipsr, regs->cr_ifs, ip);
printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
@@ -201,7 +202,7 @@
{
unsigned long rbs, child_rbs, rbs_size, stack_offset, stack_top, stack_used;
struct switch_stack *child_stack, *stack;
- extern char ia64_ret_from_clone;
+ extern char ia64_ret_from_clone, ia32_ret_from_clone;
struct pt_regs *child_ptregs;
int retval = 0;

@@ -250,7 +251,10 @@
child_ptregs->r12 = (unsigned long) (child_ptregs + 1); /* kernel sp */
child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */
}
- child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
+ if (IS_IA32_PROCESS(regs))
+ child_stack->b0 = (unsigned long) &ia32_ret_from_clone;
+ else
+ child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
child_stack->ar_bspstore = child_rbs + rbs_size;

/* copy parts of thread_struct: */
@@ -285,9 +289,8 @@
ia32_save_state(p);
#endif
#ifdef CONFIG_PERFMON
- p->thread.pfm_pend_notify = 0;
if (p->thread.pfm_context)
- retval = pfm_inherit(p);
+ retval = pfm_inherit(p, child_ptregs);
#endif
return retval;
}
@@ -441,11 +444,24 @@
}

#ifdef CONFIG_PERFMON
+/*
+ * By the time we get here, the task is detached from the tasklist. This is important
+ * because it means that no other tasks can ever find it as a notifiied task, therfore
+ * there is no race condition between this code and let's say a pfm_context_create().
+ * Conversely, the pfm_cleanup_notifiers() cannot try to access a task's pfm context if
+ * this other task is in the middle of its own pfm_context_exit() because it would alreayd
+ * be out of the task list. Note that this case is very unlikely between a direct child
+ * and its parents (if it is the notified process) because of the way the exit is notified
+ * via SIGCHLD.
+ */
void
release_thread (struct task_struct *task)
{
if (task->thread.pfm_context)
pfm_context_exit(task);
+
+ if(atomic_read(&task->thread.pfm_notifiers_check) >0)
+ pfm_cleanup_notifiers(task);
}
#endif

@@ -524,6 +540,10 @@
void
machine_halt (void)
{
+#if 0
+ while (1)
+ ia64_pal_halt(0);
+#endif
}

void
diff -urN linux-davidm/arch/ia64/kernel/ptrace.c linux-2.4.10-lia/arch/ia64/kernel/ptrace.c
--- linux-davidm/arch/ia64/kernel/ptrace.c Mon Sep 24 15:06:13 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/ptrace.c Mon Sep 24 21:51:40 2001
@@ -2,7 +2,7 @@
* Kernel support for the ptrace() and syscall tracing interfaces.
*
* Copyright (C) 1999-2001 Hewlett-Packard Co
- * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*
* Derived from the x86 and Alpha versions. Most of the code in here
* could actually be factored into a common set of routines.
@@ -794,11 +794,14 @@
*
* Make sure the single step bit is not set.
*/
-void ptrace_disable(struct task_struct *child)
+void
+ptrace_disable (struct task_struct *child)
{
+ struct ia64_psr *child_psr = ia64_psr(ia64_task_regs(child));
+
/* make sure the single step/take-branch tra bits are not set: */
- ia64_psr(pt)->ss = 0;
- ia64_psr(pt)->tb = 0;
+ child_psr->ss = 0;
+ child_psr->tb = 0;

/* Turn off flag indicating that the KRBS is sync'd with child's VM: */
child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED;
@@ -855,6 +858,19 @@
if (child->p_pptr != current)
goto out_tsk;

+ if (request != PTRACE_KILL) {
+ if (child->state != TASK_STOPPED)
+ goto out_tsk;
+
+#ifdef CONFIG_SMP
+ while (child->has_cpu) {
+ if (child->state != TASK_STOPPED)
+ goto out_tsk;
+ barrier();
+ }
+#endif
+ }
+
pt = ia64_task_regs(child);
sw = (struct switch_stack *) (child->thread.ksp + 16);

@@ -925,7 +941,7 @@
child->ptrace &= ~PT_TRACESYS;
child->exit_code = data;

- /* make sure the single step/take-branch tra bits are not set: */
+ /* make sure the single step/taken-branch trap bits are not set: */
ia64_psr(pt)->ss = 0;
ia64_psr(pt)->tb = 0;

diff -urN linux-davidm/arch/ia64/kernel/sal.c linux-2.4.10-lia/arch/ia64/kernel/sal.c
--- linux-davidm/arch/ia64/kernel/sal.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/sal.c Mon Sep 24 21:51:59 2001
@@ -2,7 +2,7 @@
* System Abstraction Layer (SAL) interface routines.
*
* Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
*/
@@ -18,8 +18,6 @@
#include <asm/sal.h>
#include <asm/pal.h>

-#define SAL_DEBUG
-
spinlock_t sal_lock = SPIN_LOCK_UNLOCKED;

static struct {
@@ -122,10 +120,8 @@
switch (*p) {
case SAL_DESC_ENTRY_POINT:
ep = (struct ia64_sal_desc_entry_point *) p;
-#ifdef SAL_DEBUG
- printk("sal[%d] - entry: pal_proc=0x%lx, sal_proc=0x%lx\n",
- i, ep->pal_proc, ep->sal_proc);
-#endif
+ printk("SAL: entry: pal_proc=0x%lx, sal_proc=0x%lx\n",
+ ep->pal_proc, ep->sal_proc);
ia64_pal_handler_init(__va(ep->pal_proc));
ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp));
break;
@@ -138,17 +134,12 @@
#ifdef CONFIG_SMP
{
struct ia64_sal_desc_ap_wakeup *ap = (void *) p;
-# ifdef SAL_DEBUG
- printk("sal[%d] - wakeup type %x, 0x%lx\n",
- i, ap->mechanism, ap->vector);
-# endif
+
switch (ap->mechanism) {
case IA64_SAL_AP_EXTERNAL_INT:
ap_wakeup_vector = ap->vector;
-# ifdef SAL_DEBUG
printk("SAL: AP wakeup using external interrupt "
"vector 0x%lx\n", ap_wakeup_vector);
-# endif
break;

default:
@@ -169,7 +160,7 @@
if (pf->feature_mask & (1 << 1)) {
printk("IRQ_Redirection ");
#ifdef CONFIG_SMP
- if (no_int_routing)
+ if (no_int_routing)
smp_int_redirect &= ~SMP_IRQ_REDIRECTION;
else
smp_int_redirect |= SMP_IRQ_REDIRECTION;
diff -urN linux-davidm/arch/ia64/kernel/setup.c linux-2.4.10-lia/arch/ia64/kernel/setup.c
--- linux-davidm/arch/ia64/kernel/setup.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/setup.c Mon Sep 24 21:52:16 2001
@@ -534,10 +534,13 @@
/*
* Initialize default control register to defer all speculative faults. The
* kernel MUST NOT depend on a particular setting of these bits (in other words,
- * the kernel must have recovery code for all speculative accesses).
+ * the kernel must have recovery code for all speculative accesses). Turn on
+ * dcr.lc as per recommendation by the architecture team. Most IA-32 apps
+ * shouldn't be affected by this (moral: keep your ia32 locks aligned and you'll
+ * be fine).
*/
ia64_set_dcr( IA64_DCR_DM | IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_DR
- | IA64_DCR_DA | IA64_DCR_DD);
+ | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC);
#ifndef CONFIG_SMP
ia64_set_fpu_owner(0);
#endif
diff -urN linux-davidm/arch/ia64/kernel/sigframe.h linux-2.4.10-lia/arch/ia64/kernel/sigframe.h
--- linux-davidm/arch/ia64/kernel/sigframe.h Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/sigframe.h Mon Sep 24 21:52:26 2001
@@ -7,10 +7,11 @@
unsigned long arg0; /* signum */
unsigned long arg1; /* siginfo pointer */
unsigned long arg2; /* sigcontext pointer */
+ /*
+ * End of architected state.
+ */

- unsigned long rbs_base; /* base of new register backing store (or NULL) */
void *handler; /* pointer to the plabel of the signal handler */
-
struct siginfo info;
struct sigcontext sc;
};
diff -urN linux-davidm/arch/ia64/kernel/signal.c linux-2.4.10-lia/arch/ia64/kernel/signal.c
--- linux-davidm/arch/ia64/kernel/signal.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/signal.c Mon Sep 24 21:52:38 2001
@@ -139,10 +139,9 @@
struct ia64_psr *psr = ia64_psr(&scr->pt);

__copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16);
- if (!psr->dfh) {
- psr->mfh = 0;
+ psr->mfh = 0; /* drop signal handler's fph contents... */
+ if (!psr->dfh)
__ia64_load_fpu(current->thread.fph);
- }
}
return err;
}
@@ -380,7 +379,8 @@
err = __put_user(sig, &frame->arg0);
err |= __put_user(&frame->info, &frame->arg1);
err |= __put_user(&frame->sc, &frame->arg2);
- err |= __put_user(new_rbs, &frame->rbs_base);
+ err |= __put_user(new_rbs, &frame->sc.sc_rbs_base);
+ err |= __put_user(0, &frame->sc.sc_loadrs); /* initialize to zero */
err |= __put_user(ka->sa.sa_handler, &frame->handler);

err |= copy_siginfo_to_user(&frame->info, info);
@@ -460,6 +460,7 @@
long
ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
{
+ struct signal_struct *sig;
struct k_sigaction *ka;
siginfo_t info;
long restart = in_syscall;
@@ -571,8 +572,8 @@
case SIGSTOP:
current->state = TASK_STOPPED;
current->exit_code = signr;
- if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags
- & SA_NOCLDSTOP))
+ sig = current->p_pptr->sig;
+ if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
notify_parent(current, SIGCHLD);
schedule();
continue;
diff -urN linux-davidm/arch/ia64/kernel/smp.c linux-2.4.10-lia/arch/ia64/kernel/smp.c
--- linux-davidm/arch/ia64/kernel/smp.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/smp.c Mon Sep 24 21:53:18 2001
@@ -222,8 +222,9 @@
atomic_set(&data.finished, 0);

spin_lock_bh(&call_lock);
- call_data = &data;

+ call_data = &data;
+ mb(); /* ensure store to call_data precedes setting of IPI_CALL_FUNC */
send_IPI_single(cpuid, IPI_CALL_FUNC);

/* Wait for response */
@@ -275,8 +276,9 @@
atomic_set(&data.finished, 0);

spin_lock_bh(&call_lock);
- call_data = &data;

+ call_data = &data;
+ mb(); /* ensure store to call_data precedes setting of IPI_CALL_FUNC */
send_IPI_allbutself(IPI_CALL_FUNC);

/* Wait for response */
diff -urN linux-davidm/arch/ia64/kernel/smpboot.c linux-2.4.10-lia/arch/ia64/kernel/smpboot.c
--- linux-davidm/arch/ia64/kernel/smpboot.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/smpboot.c Mon Sep 24 21:53:33 2001
@@ -33,6 +33,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/machvec.h>
+#include <asm/mca.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
@@ -42,6 +43,8 @@
#include <asm/system.h>
#include <asm/unistd.h>

+#define SMP_DEBUG 0
+
#if SMP_DEBUG
#define Dprintk(x...) printk(x)
#else
@@ -310,7 +313,7 @@
}

-void __init
+static void __init
smp_callin (void)
{
int cpuid, phys_id;
@@ -369,14 +372,15 @@
{
extern int cpu_idle (void);

+ Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
efi_map_pal_code();
cpu_init();
smp_callin();
- Dprintk("CPU %d is set to go. \n", smp_processor_id());
+ Dprintk("CPU %d is set to go.\n", smp_processor_id());
while (!atomic_read(&smp_commenced))
;

- Dprintk("CPU %d is starting idle. \n", smp_processor_id());
+ Dprintk("CPU %d is starting idle.\n", smp_processor_id());
return cpu_idle();
}

@@ -420,7 +424,7 @@
unhash_process(idle);
init_tasks[cpu] = idle;

- Dprintk("Sending Wakeup Vector to AP 0x%x/0x%x.\n", cpu, sapicid);
+ Dprintk("Sending wakeup vector %u to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);

platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);

@@ -429,7 +433,6 @@
*/
Dprintk("Waiting on callin_map ...");
for (timeout = 0; timeout < 100000; timeout++) {
- Dprintk(".");
if (test_bit(cpu, &cpu_callin_map))
break; /* It has booted */
udelay(100);
diff -urN linux-davidm/arch/ia64/kernel/sys_ia64.c linux-2.4.10-lia/arch/ia64/kernel/sys_ia64.c
--- linux-davidm/arch/ia64/kernel/sys_ia64.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/sys_ia64.c Mon Sep 24 21:53:53 2001
@@ -19,24 +19,29 @@
#include <asm/shmparam.h>
#include <asm/uaccess.h>

-#define COLOR_ALIGN(addr) (((addr) + SHMLBA - 1) & ~(SHMLBA - 1))
-
unsigned long
arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
{
- struct vm_area_struct * vmm;
long map_shared = (flags & MAP_SHARED);
+ unsigned long align_mask = PAGE_SIZE - 1;
+ struct vm_area_struct * vmm;

if (len > RGN_MAP_LIMIT)
return -ENOMEM;
if (!addr)
addr = TASK_UNMAPPED_BASE;

- if (map_shared)
- addr = COLOR_ALIGN(addr);
- else
- addr = PAGE_ALIGN(addr);
+ if (map_shared && (TASK_SIZE > 0xfffffffful))
+ /*
+ * For 64-bit tasks, align shared segments to 1MB to avoid potential
+ * performance penalty due to virtual aliasing (see ASDM). For 32-bit
+ * tasks, we prefer to avoid exhausting the address space too quickly by
+ * limiting alignment to a single page.
+ */
+ align_mask = SHMLBA - 1;
+
+ addr = (addr + align_mask) & ~align_mask;

for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
/* At this point: (!vmm || addr < vmm->vm_end). */
@@ -46,9 +51,7 @@
return -ENOMEM;
if (!vmm || addr + len <= vmm->vm_start)
return addr;
- addr = vmm->vm_end;
- if (map_shared)
- addr = COLOR_ALIGN(addr);
+ addr = (vmm->vm_end + align_mask) & ~align_mask;
}
}

@@ -184,8 +187,10 @@
if (!file)
return -EBADF;

- if (!file->f_op || !file->f_op->mmap)
- return -ENODEV;
+ if (!file->f_op || !file->f_op->mmap) {
+ addr = -ENODEV;
+ goto out;
+ }
}

/*
@@ -194,22 +199,26 @@
*/
len = PAGE_ALIGN(len);
if (len = 0)
- return addr;
+ goto out;

/* don't permit mappings into unmapped space or the virtual page table of a region: */
roff = rgn_offset(addr);
- if ((len | roff | (roff + len)) >= RGN_MAP_LIMIT)
- return -EINVAL;
+ if ((len | roff | (roff + len)) >= RGN_MAP_LIMIT) {
+ addr = -EINVAL;
+ goto out;
+ }

/* don't permit mappings that would cross a region boundary: */
- if (rgn_index(addr) != rgn_index(addr + len))
- return -EINVAL;
+ if (rgn_index(addr) != rgn_index(addr + len)) {
+ addr = -EINVAL;
+ goto out;
+ }

down_write(&current->mm->mmap_sem);
addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up_write(&current->mm->mmap_sem);

- if (file)
+out: if (file)
fput(file);
return addr;
}
diff -urN linux-davidm/arch/ia64/kernel/traps.c linux-2.4.10-lia/arch/ia64/kernel/traps.c
--- linux-davidm/arch/ia64/kernel/traps.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/traps.c Mon Sep 24 21:54:49 2001
@@ -2,7 +2,7 @@
* Architecture-specific trap handling.
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*
* 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE
*/
@@ -32,13 +32,17 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
+#include <linux/vt_kern.h> /* For unblank_screen() */

+#include <asm/hardirq.h>
#include <asm/ia32.h>
#include <asm/processor.h>
#include <asm/uaccess.h>

#include <asm/fpswa.h>

+extern spinlock_t timerlist_lock;
+
static fpswa_interface_t *fpswa_interface;

void __init
@@ -50,22 +54,48 @@
fpswa_interface = __va(ia64_boot_param->fpswa);
}

+/*
+ * Unlock any spinlocks which will prevent us from getting the message out (timerlist_lock
+ * is acquired through the console unblank code)
+ */
void
-die_if_kernel (char *str, struct pt_regs *regs, long err)
+bust_spinlocks (int yes)
{
- if (user_mode(regs)) {
-#if 0
- /* XXX for debugging only */
- printk ("!!die_if_kernel: %s(%d): %s %ld\n",
- current->comm, current->pid, str, err);
- show_regs(regs);
+ spin_lock_init(&timerlist_lock);
+ if (yes) {
+ oops_in_progress = 1;
+#ifdef CONFIG_SMP
+ global_irq_lock = 0; /* Many serial drivers do __global_cli() */
#endif
- return;
+ } else {
+ int loglevel_save = console_loglevel;
+#ifdef CONFIG_VT
+ unblank_screen();
+#endif
+ oops_in_progress = 0;
+ /*
+ * OK, the message is on the console. Now we call printk() without
+ * oops_in_progress set so that printk will give klogd a poke. Hold onto
+ * your hats...
+ */
+ console_loglevel = 15; /* NMI oopser may have shut the console up */
+ printk(" ");
+ console_loglevel = loglevel_save;
}
+}

- printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err);
+void
+die (const char *str, struct pt_regs *regs, long err)
+{
+ static spinlock_t die_lock = SPIN_LOCK_UNLOCKED;

+ console_verbose();
+ spin_lock_irq(&die_lock);
+ bust_spinlocks(1);
+ printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err);
show_regs(regs);
+ bust_spinlocks(0);
+ spin_unlock_irq(&die_lock);

if (current->thread.flags & IA64_KERNEL_DEATH) {
printk("die_if_kernel recursion detected.\n");
@@ -77,6 +107,13 @@
}

void
+die_if_kernel (char *str, struct pt_regs *regs, long err)
+{
+ if (!user_mode(regs))
+ die(str, regs, err);
+}
+
+void
ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
{
siginfo_t siginfo;
@@ -168,14 +205,12 @@
}

/*
- * disabled_fph_fault() is called when a user-level process attempts
- * to access one of the registers f32..f127 when it doesn't own the
- * fp-high register partition. When this happens, we save the current
- * fph partition in the task_struct of the fpu-owner (if necessary)
- * and then load the fp-high partition of the current task (if
- * necessary). Note that the kernel has access to fph by the time we
- * get here, as the IVT's "Diabled FP-Register" handler takes care of
- * clearing psr.dfh.
+ * disabled_fph_fault() is called when a user-level process attempts to access f32..f127
+ * and it doesn't own the fp-high register partition. When this happens, we save the
+ * current fph partition in the task_struct of the fpu-owner (if necessary) and then load
+ * the fp-high partition of the current task (if necessary). Note that the kernel has
+ * access to fph by the time we get here, as the IVT's "Disabled FP-Register" handler takes
+ * care of clearing psr.dfh.
*/
static inline void
disabled_fph_fault (struct pt_regs *regs)
diff -urN linux-davidm/arch/ia64/kernel/unwind.c linux-2.4.10-lia/arch/ia64/kernel/unwind.c
--- linux-davidm/arch/ia64/kernel/unwind.c Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/kernel/unwind.c Mon Sep 24 21:55:01 2001
@@ -504,7 +504,7 @@
return 0;
}

-inline int
+int
unw_access_pr (struct unw_frame_info *info, unsigned long *val, int write)
{
unsigned long *addr;
diff -urN linux-davidm/arch/ia64/lib/clear_page.S linux-2.4.10-lia/arch/ia64/lib/clear_page.S
--- linux-davidm/arch/ia64/lib/clear_page.S Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/lib/clear_page.S Mon Sep 24 21:55:10 2001
@@ -47,5 +47,5 @@
br.cloop.dptk.few 1b
;;
mov ar.lc = r2 // restore lc
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(clear_page)
diff -urN linux-davidm/arch/ia64/lib/clear_user.S linux-2.4.10-lia/arch/ia64/lib/clear_user.S
--- linux-davidm/arch/ia64/lib/clear_user.S Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/lib/clear_user.S Mon Sep 24 21:55:19 2001
@@ -8,7 +8,7 @@
* r8: number of bytes that didn't get cleared due to a fault
*
* Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ * Stephane Eranian <eranian@hpl.hp.com>
*/

#include <asm/asmmacro.h>
@@ -62,11 +62,11 @@
;; // avoid WAW on CFM
adds tmp=-1,len // br.ctop is repeat/until
mov ret0=len // return value is length at this point
-(p6) br.ret.spnt.few rp
+(p6) br.ret.spnt.many rp
;;
cmp.lt p6,p0\x16,len // if len > 16 then long memset
mov ar.lc=tmp // initialize lc for small count
-(p6) br.cond.dptk.few long_do_clear
+(p6) br.cond.dptk .long_do_clear
;; // WAR on ar.lc
//
// worst case 16 iterations, avg 8 iterations
@@ -79,7 +79,7 @@
1:
EX( .Lexit1, st1 [buf]=r0,1 )
adds len=-1,len // countdown length using len
- br.cloop.dptk.few 1b
+ br.cloop.dptk 1b
;; // avoid RAW on ar.lc
//
// .Lexit4: comes from byte by byte loop
@@ -87,7 +87,7 @@
.Lexit1:
mov ret0=len // faster than using ar.lc
mov ar.lc=saved_lc
- br.ret.sptk.few rp // end of short clear_user
+ br.ret.sptk.many rp // end of short clear_user

//
@@ -98,7 +98,7 @@
// instead of ret0 is due to the fact that the exception code
// changes the values of r8.
//
-long_do_clear:
+.long_do_clear:
tbit.nz p6,p0=buf,0 // odd alignment (for long_do_clear)
;;
EX( .Lexit3, (p6) st1 [buf]=r0,1 ) // 1-byte aligned
@@ -119,7 +119,7 @@
;;
cmp.eq p6,p0=r0,cnt
adds tmp=-1,cnt
-(p6) br.cond.dpnt.few .dotail // we have less than 16 bytes left
+(p6) br.cond.dpnt .dotail // we have less than 16 bytes left
;;
adds buf2=8,buf // setup second base pointer
mov ar.lc=tmp
@@ -148,7 +148,7 @@
;; // needed to get len correct when error
st8 [buf2]=r0,16
adds len=-16,len
- br.cloop.dptk.few 2b
+ br.cloop.dptk 2b
;;
mov ar.lc=saved_lc
//
@@ -178,7 +178,7 @@
;;
EX( .Lexit2, (p7) st1 [buf]=r0 ) // only 1 byte left
mov ret0=r0 // success
- br.ret.dptk.few rp // end of most likely path
+ br.ret.sptk.many rp // end of most likely path

//
// Outlined error handling code
@@ -205,5 +205,5 @@
.Lexit3:
mov ret0=len
mov ar.lc=saved_lc
- br.ret.dptk.few rp
+ br.ret.sptk.many rp
END(__do_clear_user)
diff -urN linux-davidm/arch/ia64/lib/copy_page.S linux-2.4.10-lia/arch/ia64/lib/copy_page.S
--- linux-davidm/arch/ia64/lib/copy_page.S Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/lib/copy_page.S Mon Sep 24 21:55:37 2001
@@ -90,5 +90,5 @@
mov pr=saved_pr,0xffffffffffff0000 // restore predicates
mov ar.pfs=saved_pfs
mov ar.lc=saved_lc
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(copy_page)
diff -urN linux-davidm/arch/ia64/lib/copy_user.S linux-2.4.10-lia/arch/ia64/lib/copy_user.S
--- linux-davidm/arch/ia64/lib/copy_user.S Tue Jul 31 10:30:08 2001
+++ linux-2.4.10-lia/arch/ia64/lib/copy_user.S Mon Sep 24 21:55:46 2001
@@ -19,8 +19,8 @@
* ret0 0 in case of success. The number of bytes NOT copied in
* case of error.
*
- * Copyright (C) 2000 Hewlett-Packard Co
- * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 2000-2001 Hewlett-Packard Co
+ * Stephane Eranian <eranian@hpl.hp.com>
*
* Fixme:
* - handle the case where we have more than 16 bytes and the alignment
@@ -85,7 +85,7 @@
cmp.eq p8,p0=r0,len // check for zero length
.save ar.lc, saved_lc
mov saved_lc=ar.lc // preserve ar.lc (slow)
-(p8) br.ret.spnt.few rp // empty mempcy()
+(p8) br.ret.spnt.many rp // empty mempcy()
;;
add enddst=dst,len // first byte after end of source
add endsrc=src,len // first byte after end of destination
@@ -103,26 +103,26 @@
cmp.lt p10,p7=COPY_BREAK,len // if len > COPY_BREAK then long copy

xor tmp=src,dst // same alignment test prepare
-(p10) br.cond.dptk.few long_copy_user
+(p10) br.cond.dptk .long_copy_user
;; // RAW pr.rot/p16 ?
//
// Now we do the byte by byte loop with software pipeline
//
// p7 is necessarily false by now
1:
- EX(failure_in_pipe1,(p16) ld1 val1[0]=[src1],1)
- EX(failure_out,(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1)
+ 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 1b
;;
mov ar.lc=saved_lc
mov pr=saved_pr,0xffffffffffff0000
mov ar.pfs=saved_pfs // restore ar.ec
- br.ret.sptk.few rp // end of short memcpy
+ br.ret.sptk.many rp // end of short memcpy

//
// Not 8-byte aligned
//
-diff_align_copy_user:
+.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
@@ -153,7 +153,7 @@
// We know src1 is not 8-byte aligned in this case.
//
cmp.eq p14,p15=r0,dst2
-(p15) br.cond.spnt.few 1f
+(p15) br.cond.spnt 1f
;;
sub t1=8,src2
mov t2=src2
@@ -163,7 +163,7 @@
;;
sub lshiftd,rshift
;;
- br.cond.spnt.few word_copy_user
+ br.cond.spnt .word_copy_user
;;
1:
cmp.leu p14,p15=src2,dst2
@@ -192,15 +192,15 @@
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)
+ 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:
+.word_copy_user:
cmp.gtu p9,p0\x16,len1
-(p9) br.cond.spnt.few 4f // if (16 > len1) skip 8-byte copy
+(p9) br.cond.spnt 4f // if (16 > len1) skip 8-byte copy
;;
shr.u cnt=len1,3 // number of 64-bit words
;;
@@ -232,24 +232,24 @@
#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
+ (pred) br.cond.spnt .copy_user_bit##shift
#define BODY(rshift) \
-copy_user_bit##rshift: \
+.copy_user_bit##rshift: \
1: \
- EX(failure_out,(EPI) st8 [dst1]=tmp,8); \
+ EX(.failure_out,(EPI) st8 [dst1]=tmp,8); \
(EPI_1) shrp tmp=val1[PIPE_DEPTH-3],val1[PIPE_DEPTH-2],rshift; \
EX(3f,(p16) ld8 val1[0]=[src1],8); \
- br.ctop.dptk.few 1b; \
+ br.ctop.dptk 1b; \
;; \
- br.cond.sptk.few .diff_align_do_tail; \
+ br.cond.sptk.many .diff_align_do_tail; \
2: \
(EPI) st8 [dst1]=tmp,8; \
(EPI_1) shrp tmp=val1[PIPE_DEPTH-3],val1[PIPE_DEPTH-2],rshift; \
3: \
(p16) mov val1[0]=r0; \
- br.ctop.dptk.few 2b; \
+ br.ctop.dptk 2b; \
;; \
- br.cond.sptk.few failure_in2
+ br.cond.sptk.many .failure_in2

//
// Since the instruction 'shrp' requires a fixed 128-bit value
@@ -301,25 +301,25 @@
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)
+ 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 ar.lc=saved_lc
mov pr=saved_pr,0xffffffffffff0000
mov ar.pfs=saved_pfs
- br.ret.dptk.few rp
+ br.ret.sptk.many rp

//
// Beginning of long mempcy (i.e. > 16 bytes)
//
-long_copy_user:
+.long_copy_user:
tbit.nz p6,p7=src1,0 // odd alignement
and tmp=7,tmp
;;
cmp.eq p10,p8=r0,tmp
mov len1=len // copy because of rotation
-(p8) br.cond.dpnt.few diff_align_copy_user
+(p8) br.cond.dpnt .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
@@ -327,11 +327,11 @@
// forward slowly until we reach 16byte alignment: no need to
// worry about reaching the end of buffer.
//
- EX(failure_in1,(p6) ld1 val1[0]=[src1],1) // 1-byte aligned
+ EX(.failure_in1,(p6) ld1 val1[0]=[src1],1) // 1-byte aligned
(p6) adds len1=-1,len1;;
tbit.nz p7,p0=src1,1
;;
- EX(failure_in1,(p7) ld2 val1[1]=[src1],2) // 2-byte aligned
+ EX(.failure_in1,(p7) ld2 val1[1]=[src1],2) // 2-byte aligned
(p7) adds len1=-2,len1;;
tbit.nz p8,p0=src1,2
;;
@@ -339,28 +339,28 @@
// Stop bit not required after ld4 because if we fail on ld4
// we have never executed the ld1, therefore st1 is not executed.
//
- EX(failure_in1,(p8) ld4 val2[0]=[src1],4) // 4-byte aligned
+ EX(.failure_in1,(p8) ld4 val2[0]=[src1],4) // 4-byte aligned
;;
- EX(failure_out,(p6) st1 [dst1]=val1[0],1)
+ EX(.failure_out,(p6) st1 [dst1]=val1[0],1)
tbit.nz p9,p0=src1,3
;;
//
// Stop bit not required after ld8 because if we fail on ld8
// we have never executed the ld2, therefore st2 is not executed.
//
- EX(failure_in1,(p9) ld8 val2[1]=[src1],8) // 8-byte aligned
- EX(failure_out,(p7) st2 [dst1]=val1[1],2)
+ EX(.failure_in1,(p9) ld8 val2[1]=[src1],8) // 8-byte aligned
+ EX(.failure_out,(p7) st2 [dst1]=val1[1],2)
(p8) adds len1=-4,len1
;;
- EX(failure_out, (p8) st4 [dst1]=val2[0],4)
+ EX(.failure_out, (p8) st4 [dst1]=val2[0],4)
(p9) adds len1=-8,len1;;
shr.u cnt=len1,4 // number of 128-bit (2x64bit) words
;;
- EX(failure_out, (p9) st8 [dst1]=val2[1],8)
+ EX(.failure_out, (p9) st8 [dst1]=val2[1],8)
tbit.nz p6,p0=len1,3
cmp.eq p7,p0=r0,cnt
adds tmp=-1,cnt // br.ctop is repeat/until
-(p7) br.cond.dpnt.few .dotail // we have less than 16 bytes left
+(p7) br.cond.dpnt .dotail // we have less than 16 bytes left
;;
adds src2=8,src1
adds dst2=8,dst1
@@ -370,12 +370,12 @@
// 16bytes/iteration
//
2:
- EX(failure_in3,(p16) ld8 val1[0]=[src1],16)
+ EX(.failure_in3,(p16) ld8 val1[0]=[src1],16)
(p16) ld8 val2[0]=[src2],16

- EX(failure_out, (EPI) st8 [dst1]=val1[PIPE_DEPTH-1],16)
+ EX(.failure_out, (EPI) st8 [dst1]=val1[PIPE_DEPTH-1],16)
(EPI) st8 [dst2]=val2[PIPE_DEPTH-1],16
- br.ctop.dptk.few 2b
+ br.ctop.dptk 2b
;; // RAW on src1 when fall through from loop
//
// Tail correction based on len only
@@ -384,29 +384,28 @@
// is 16 byte aligned AND we have less than 16 bytes to copy.
//
.dotail:
- EX(failure_in1,(p6) ld8 val1[0]=[src1],8) // at least 8 bytes
+ EX(.failure_in1,(p6) ld8 val1[0]=[src1],8) // at least 8 bytes
tbit.nz p7,p0=len1,2
;;
- EX(failure_in1,(p7) ld4 val1[1]=[src1],4) // at least 4 bytes
+ EX(.failure_in1,(p7) ld4 val1[1]=[src1],4) // at least 4 bytes
tbit.nz p8,p0=len1,1
;;
- EX(failure_in1,(p8) ld2 val2[0]=[src1],2) // at least 2 bytes
+ EX(.failure_in1,(p8) ld2 val2[0]=[src1],2) // at least 2 bytes
tbit.nz p9,p0=len1,0
;;
- EX(failure_out, (p6) st8 [dst1]=val1[0],8)
+ EX(.failure_out, (p6) st8 [dst1]=val1[0],8)
;;
- EX(failure_in1,(p9) ld1 val2[1]=[src1]) // only 1 byte left
+ EX(.failure_in1,(p9) ld1 val2[1]=[src1]) // only 1 byte left
mov ar.lc=saved_lc
;;
- EX(failure_out,(p7) st4 [dst1]=val1[1],4)
+ EX(.failure_out,(p7) st4 [dst1]=val1[1],4)
mov pr=saved_pr,0xffffffffffff0000
;;
- EX(failure_out, (p8) st2 [dst1]=val2[0],2)
+ EX(.failure_out, (p8) st2 [dst1]=val2[0],2)
mov ar.pfs=saved_pfs
;;
- EX(failure_out, (p9) st1 [dst1]=val2[1])
- br.ret.dptk.few rp
-
+ EX(.failure_out, (p9) st1 [dst1]=val2[1])
+ br.ret.sptk.many rp

//
@@ -433,32 +432,32 @@
// pipeline going. We can't really do this inline because
// p16 is always reset to 1 when lc > 0.
//
-failure_in_pipe1:
+.failure_in_pipe1:
sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
1:
(p16) mov val1[0]=r0
(EPI) st1 [dst1]=val1[PIPE_DEPTH-1],1
- br.ctop.dptk.few 1b
+ br.ctop.dptk 1b
;;
mov pr=saved_pr,0xffffffffffff0000
mov ar.lc=saved_lc
mov ar.pfs=saved_pfs
- br.ret.dptk.few rp
+ br.ret.sptk.many 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:
+.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
+ br.ctop.dptk 2b
;;
sub len=enddst,dst1,1 // precompute len
- br.cond.dptk.few failure_in1bis
+ br.cond.dptk.many .failure_in1bis
;;

//
@@ -533,9 +532,7 @@
// This means that we are in a situation similar the a fault in the
// head part. That's nice!
//
-failure_in1:
-// sub ret0=enddst,dst1 // number of bytes to zero, i.e. not copied
-// sub len=enddst,dst1,1
+.failure_in1:
sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
sub len=endsrc,src1,1
//
@@ -546,18 +543,17 @@
// calling side.
//
;;
-failure_in1bis: // from (failure_in3)
+.failure_in1bis: // from (.failure_in3)
mov ar.lc=len // Continue with a stupid byte store.
;;
5:
st1 [dst1]=r0,1
- br.cloop.dptk.few 5b
+ br.cloop.dptk 5b
;;
-skip_loop:
mov pr=saved_pr,0xffffffffffff0000
mov ar.lc=saved_lc
mov ar.pfs=saved_pfs
- br.ret.dptk.few rp
+ br.ret.sptk.many rp

//
// Here we simply restart the loop but instead
@@ -569,7 +565,7 @@
// we MUST use src1/endsrc here and not dst1/enddst because
// of the pipeline effect.
//
-failure_in3:
+.failure_in3:
sub ret0=endsrc,src1 // number of bytes to zero, i.e. not copied
;;
2:
@@ -577,36 +573,36 @@
(p16) mov val2[0]=r0
(EPI) st8 [dst1]=val1[PIPE_DEPTH-1],16
(EPI) st8 [dst2]=val2[PIPE_DEPTH-1],16
- br.ctop.dptk.few 2b
+ br.ctop.dptk 2b
;;
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
+(p6) br.cond.dptk .failure_in1bis
;;
mov pr=saved_pr,0xffffffffffff0000
mov ar.lc=saved_lc
mov ar.pfs=saved_pfs
- br.ret.dptk.few rp
+ br.ret.sptk.many rp

-failure_in2:
+.failure_in2:
sub ret0=endsrc,src1
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
+(p6) br.cond.dptk .failure_in1bis
;;
mov pr=saved_pr,0xffffffffffff0000
mov ar.lc=saved_lc
mov ar.pfs=saved_pfs
- br.ret.dptk.few rp
+ br.ret.sptk.many rp

//
// handling of failures on stores: that's the easy part
//
-failure_out:
+.failure_out:
sub ret0=enddst,dst1
mov pr=saved_pr,0xffffffffffff0000
mov ar.lc=saved_lc

mov ar.pfs=saved_pfs
- br.ret.dptk.few rp
+ br.ret.sptk.many rp
END(__copy_user)
diff -urN linux-davidm/arch/ia64/lib/do_csum.S linux-2.4.10-lia/arch/ia64/lib/do_csum.S
--- linux-davidm/arch/ia64/lib/do_csum.S Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/lib/do_csum.S Mon Sep 24 21:56:08 2001
@@ -129,7 +129,7 @@
;; // avoid WAW on CFM
mov tmp3=0x7 // a temporary mask/value
add tmp1=buf,len // last byte's address
-(p6) br.ret.spnt.few rp // return if true (hope we can avoid that)
+(p6) br.ret.spnt.many rp // return if true (hope we can avoid that)

and firstoff=7,buf // how many bytes off for first1 element
tbit.nz p15,p0=buf,0 // is buf an odd address ?
@@ -180,9 +180,9 @@
cmp.ltu p6,p0=result1[0],word1[0] // check the carry
;;
(p6) adds result1[0]=1,result1[0]
-(p8) br.cond.dptk.few do_csum_exit // if (within an 8-byte word)
+(p8) br.cond.dptk .do_csum_exit // if (within an 8-byte word)
;;
-(p11) br.cond.dptk.few do_csum16 // if (count is even)
+(p11) br.cond.dptk .do_csum16 // if (count is even)
;;
// Here count is odd.
ld8 word1[1]=[first1],8 // load an 8-byte word
@@ -195,14 +195,14 @@
;;
(p6) adds result1[0]=1,result1[0]
;;
-(p9) br.cond.sptk.few do_csum_exit // if (count = 1) exit
+(p9) br.cond.sptk .do_csum_exit // if (count = 1) exit
// Fall through to caluculate the checksum, feeding result1[0] as
// the initial value in result1[0].
;;
//
// Calculate the checksum loading two 8-byte words per loop.
//
-do_csum16:
+.do_csum16:
mov saved_lc=ar.lc
shr.u count=count,1 // we do 16 bytes per loop
;;
@@ -224,7 +224,7 @@
;;
add first2=8,first1
;;
-(p9) br.cond.sptk.few do_csum_exit
+(p9) br.cond.sptk .do_csum_exit
;;
nop.m 0
nop.i 0
@@ -240,7 +240,7 @@
2:
(p16) ld8 word1[0]=[first1],16
(p16) ld8 word2[0]=[first2],16
- br.ctop.sptk.few 1b
+ br.ctop.sptk 1b
;;
// Since len is a 32-bit value, carry cannot be larger than
// a 64-bit value.
@@ -262,7 +262,7 @@
;;
(p6) adds result1[0]=1,result1[0]
;;
-do_csum_exit:
+.do_csum_exit:
movl tmp3=0xffffffff
;;
// XXX Fixme
@@ -298,7 +298,7 @@
;;
mov ar.lc=saved_lc
(p15) shr.u ret0=ret0,64-16 // + shift back to position = swap bytes
- br.ret.sptk.few rp
+ br.ret.sptk.many rp

// I (Jun Nakajima) wrote an equivalent code (see below), but it was
// not much better than the original. So keep the original there so that
@@ -330,6 +330,6 @@
//(p15) mux1 ret0=ret0,@rev // reverse word
// ;;
//(p15) shr.u ret0=ret0,64-16 // + shift back to position = swap bytes
-// br.ret.sptk.few rp
+// br.ret.sptk.many rp

END(do_csum)
diff -urN linux-davidm/arch/ia64/lib/idiv32.S linux-2.4.10-lia/arch/ia64/lib/idiv32.S
--- linux-davidm/arch/ia64/lib/idiv32.S Mon Oct 9 17:54:56 2000
+++ linux-2.4.10-lia/arch/ia64/lib/idiv32.S Mon Sep 24 21:56:20 2001
@@ -79,5 +79,5 @@
;;
#endif
getf.sig r8 = f6 // transfer result to result register
- br.ret.sptk rp
+ br.ret.sptk.many rp
END(NAME)
diff -urN linux-davidm/arch/ia64/lib/idiv64.S linux-2.4.10-lia/arch/ia64/lib/idiv64.S
--- linux-davidm/arch/ia64/lib/idiv64.S Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/arch/ia64/lib/idiv64.S Mon Sep 24 21:56:27 2001
@@ -89,5 +89,5 @@
#endif
getf.sig r8 = f17 // transfer result to result register
ldf.fill f17 = [sp]
- br.ret.sptk rp
+ br.ret.sptk.many rp
END(NAME)
diff -urN linux-davidm/arch/ia64/lib/memcpy.S linux-2.4.10-lia/arch/ia64/lib/memcpy.S
--- linux-davidm/arch/ia64/lib/memcpy.S Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/lib/memcpy.S Mon Sep 24 21:56:35 2001
@@ -9,9 +9,9 @@
* Output:
* no return value
*
- * Copyright (C) 2001 Hewlett-Packard Co
- * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2000-2001 Hewlett-Packard Co
+ * Stephane Eranian <eranian@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/config.h>

@@ -97,8 +97,8 @@
cmp.ne p6,p0=t0,r0

mov src=in1 // copy because of rotation
-(p7) br.cond.spnt.few memcpy_short
-(p6) br.cond.spnt.few memcpy_long
+(p7) br.cond.spnt.few .memcpy_short
+(p6) br.cond.spnt.few .memcpy_long
;;
nop.m 0
;;
@@ -133,7 +133,7 @@
* issues, we want to avoid read-modify-write of entire words.
*/
.align 32
-memcpy_short:
+.memcpy_short:
adds cnt=-1,in2 // br.ctop is repeat/until
mov ar.ec=MEM_LAT
brp.loop.imp 1f, 2f
@@ -196,7 +196,7 @@

#define LOG_LOOP_SIZE 6

-memcpy_long:
+.memcpy_long:
alloc t3=ar.pfs,3,Nrot,0,Nrot // resize register frame
and t0=-8,src // t0 = src & ~7
and t2=7,src // t2 = src & 7
@@ -241,7 +241,7 @@
mov t4=ip
} ;;
and src2=-8,src // align source pointer
- adds t4=memcpy_loops-1b,t4
+ adds t4=.memcpy_loops-1b,t4
mov ar.ec=N

and t0=7,src // t0 = src & 7
@@ -260,7 +260,7 @@
mov pr=cnt,0x38 // set (p5,p4,p3) to # of bytes last-word bytes to copy
mov ar.lc=t2
;;
- nop.m 0
+ nop.m 0
;;
nop.m 0
nop.i 0
@@ -272,7 +272,7 @@
br.sptk.few b6
;;

-memcpy_tail:
+.memcpy_tail:
// At this point, (p5,p4,p3) are set to the number of bytes left to copy (which is
// less than 8) and t0 contains the last few bytes of the src buffer:
(p5) st4 [dst]=t0,4
@@ -305,8 +305,8 @@
ld8 val[N-1]=[src_end]; /* load last word (may be same as val[N]) */ \
;; \
shrp t0=val[N-1],val[N-index],shift; \
- br memcpy_tail
-memcpy_loops:
+ br .memcpy_tail
+.memcpy_loops:
COPY(0, 1) /* no point special casing this---it doesn't go any faster without shrp */
COPY(8, 0)
COPY(16, 0)
diff -urN linux-davidm/arch/ia64/lib/memset.S linux-2.4.10-lia/arch/ia64/lib/memset.S
--- linux-davidm/arch/ia64/lib/memset.S Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/arch/ia64/lib/memset.S Mon Sep 24 21:56:50 2001
@@ -43,11 +43,11 @@

adds tmp=-1,len // br.ctop is repeat/until
tbit.nz p6,p0=buf,0 // odd alignment
-(p8) br.ret.spnt.few rp
+(p8) br.ret.spnt.many rp

cmp.lt p7,p0\x16,len // if len > 16 then long memset
mux1 val=val,@brcst // prepare value
-(p7) br.cond.dptk.few long_memset
+(p7) br.cond.dptk .long_memset
;;
mov ar.lc=tmp // initialize lc for small count
;; // avoid RAW and WAW on ar.lc
@@ -57,11 +57,11 @@
;; // avoid RAW on ar.lc
mov ar.lc=saved_lc
mov ar.pfs=saved_pfs
- br.ret.sptk.few rp // end of short memset
+ br.ret.sptk.many rp // end of short memset

// at this point we know we have more than 16 bytes to copy
// so we focus on alignment
-long_memset:
+.long_memset:
(p6) st1 [buf]=val,1 // 1-byte aligned
(p6) adds len=-1,len;; // sync because buf is modified
tbit.nz p6,p0=buf,1
@@ -80,7 +80,7 @@
;;
cmp.eq p6,p0=r0,cnt
adds tmp=-1,cnt
-(p6) br.cond.dpnt.few .dotail // we have less than 16 bytes left
+(p6) br.cond.dpnt .dotail // we have less than 16 bytes left
;;
adds buf2=8,buf // setup second base pointer
mov ar.lc=tmp
@@ -104,5 +104,5 @@
mov ar.lc=saved_lc
;;
(p6) st1 [buf]=val // only 1 byte left
- br.ret.dptk.few rp
+ br.ret.sptk.many rp
END(memset)
diff -urN linux-davidm/arch/ia64/lib/strlen.S linux-2.4.10-lia/arch/ia64/lib/strlen.S
--- linux-davidm/arch/ia64/lib/strlen.S Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/arch/ia64/lib/strlen.S Mon Sep 24 21:56:58 2001
@@ -11,7 +11,7 @@
* does not count the \0
*
* Copyright (C) 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
+ * Stephane Eranian <eranian@hpl.hp.com>
*
* 09/24/99 S.Eranian add speculation recovery code
*/
@@ -116,7 +116,7 @@
ld8.s w[0]=[src],8 // speculatively load next to next
cmp.eq.and p6,p0=8,val1 // p6 = p6 and val1=8
cmp.eq.and p6,p0=8,val2 // p6 = p6 and mask=8
-(p6) br.wtop.dptk.few 1b // loop until p6 = 0
+(p6) br.wtop.dptk 1b // loop until p6 = 0
;;
//
// We must return try the recovery code iff
@@ -127,14 +127,14 @@
//
cmp.eq p8,p9=8,val1 // p6 = val1 had zero (disambiguate)
tnat.nz p6,p7=val1 // test NaT on val1
-(p6) br.cond.spnt.few recover// jump to recovery if val1 is NaT
+(p6) br.cond.spnt .recover // jump to recovery if val1 is NaT
;;
//
// if we come here p7 is true, i.e., initialized for // cmp
//
cmp.eq.and p7,p0=8,val1// val1=8?
tnat.nz.and p7,p0=val2 // test NaT if val2
-(p7) br.cond.spnt.few recover// jump to recovery if val2 is NaT
+(p7) br.cond.spnt .recover // jump to recovery if val2 is NaT
;;
(p8) mov val1=val2 // the other test got us out of the loop
(p8) adds src=-16,src // correct position when 3 ahead
@@ -146,7 +146,7 @@
;;
sub ret0=ret0,tmp // adjust
mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what
- br.ret.sptk.few rp // end of normal execution
+ br.ret.sptk.many rp // end of normal execution

//
// Outlined recovery code when speculation failed
@@ -165,7 +165,7 @@
// - today we restart from the beginning of the string instead
// of trying to continue where we left off.
//
-recover:
+.recover:
ld8 val=[base],8 // will fail if unrecoverable fault
;;
or val=val,mask // remask first bytes
@@ -180,7 +180,7 @@
czx1.r val1=val // search 0 byte from right
;;
cmp.eq p6,p0=8,val1 // val1=8 ?
-(p6) br.wtop.dptk.few 2b // loop until p6 = 0
+(p6) br.wtop.dptk 2b // loop until p6 = 0
;; // (avoid WAW on p63)
sub ret0ºse,orig // distance from base
sub tmp=8,val1
@@ -188,5 +188,5 @@
;;
sub ret0=ret0,tmp // length=now - back -1
mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what
- br.ret.sptk.few rp // end of successful recovery code
+ br.ret.sptk.many rp // end of successful recovery code
END(strlen)
diff -urN linux-davidm/arch/ia64/lib/strlen_user.S linux-2.4.10-lia/arch/ia64/lib/strlen_user.S
--- linux-davidm/arch/ia64/lib/strlen_user.S Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/arch/ia64/lib/strlen_user.S Mon Sep 24 21:57:08 2001
@@ -8,8 +8,8 @@
* ret0 0 in case of fault, strlen(buffer)+1 otherwise
*
* Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
- * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
+ * Stephane Eranian <eranian@hpl.hp.com>
*
* 01/19/99 S.Eranian heavily enhanced version (see details below)
* 09/24/99 S.Eranian added speculation recovery code
@@ -108,7 +108,7 @@
mov ar.ec=r0 // clear epilogue counter (saved in ar.pfs)
;;
add base=-16,src // keep track of aligned base
- chk.s v[1], recover // if already NaT, then directly skip to recover
+ chk.s v[1], .recover // if already NaT, then directly skip to recover
or v[1]=v[1],mask // now we have a safe initial byte pattern
;;
1:
@@ -130,14 +130,14 @@
//
cmp.eq p8,p9=8,val1 // p6 = val1 had zero (disambiguate)
tnat.nz p6,p7=val1 // test NaT on val1
-(p6) br.cond.spnt.few recover// jump to recovery if val1 is NaT
+(p6) br.cond.spnt .recover // jump to recovery if val1 is NaT
;;
//
// if we come here p7 is true, i.e., initialized for // cmp
//
cmp.eq.and p7,p0=8,val1// val1=8?
tnat.nz.and p7,p0=val2 // test NaT if val2
-(p7) br.cond.spnt.few recover// jump to recovery if val2 is NaT
+(p7) br.cond.spnt .recover // jump to recovery if val2 is NaT
;;
(p8) mov val1=val2 // val2 contains the value
(p8) adds src=-16,src // correct position when 3 ahead
@@ -149,7 +149,7 @@
;;
sub ret0=ret0,tmp // length=now - back -1
mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what
- br.ret.sptk.few rp // end of normal execution
+ br.ret.sptk.many rp // end of normal execution

//
// Outlined recovery code when speculation failed
@@ -162,7 +162,7 @@
// - today we restart from the beginning of the string instead
// of trying to continue where we left off.
//
-recover:
+.recover:
EX(.Lexit1, ld8 val=[base],8) // load the initial bytes
;;
or val=val,mask // remask first bytes
@@ -185,7 +185,7 @@
;;
sub ret0=ret0,tmp // length=now - back -1
mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what
- br.ret.sptk.few rp // end of successful recovery code
+ br.ret.sptk.many rp // end of successful recovery code

//
// We failed even on the normal load (called from exception handler)
@@ -194,5 +194,5 @@
mov ret0=0
mov pr=saved_pr,0xffffffffffff0000
mov ar.pfs=saved_pfs // because of ar.ec, restore no matter what
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(__strlen_user)
diff -urN linux-davidm/arch/ia64/lib/strncpy_from_user.S linux-2.4.10-lia/arch/ia64/lib/strncpy_from_user.S
--- linux-davidm/arch/ia64/lib/strncpy_from_user.S Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/arch/ia64/lib/strncpy_from_user.S Mon Sep 24 21:57:19 2001
@@ -40,5 +40,5 @@
(p6) mov r8=in2 // buffer filled up---return buffer length
(p7) sub r8=in1,r9,1 // return string length (excluding NUL character)
[.Lexit:]
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(__strncpy_from_user)
diff -urN linux-davidm/arch/ia64/lib/strnlen_user.S linux-2.4.10-lia/arch/ia64/lib/strnlen_user.S
--- linux-davidm/arch/ia64/lib/strnlen_user.S Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/arch/ia64/lib/strnlen_user.S Mon Sep 24 21:57:28 2001
@@ -33,7 +33,7 @@
add r9=1,r9
;;
cmp.eq p6,p0=r8,r0
-(p6) br.dpnt.few .Lexit
+(p6) br.cond.dpnt .Lexit
br.cloop.dptk.few .Loop1

add r9=1,in1 // NUL not found---return N+1
@@ -41,5 +41,5 @@
.Lexit:
mov r8=r9
mov ar.lc=r16 // restore ar.lc
- br.ret.sptk.few rp
+ br.ret.sptk.many rp
END(__strnlen_user)
diff -urN linux-davidm/arch/ia64/mm/fault.c linux-2.4.10-lia/arch/ia64/mm/fault.c
--- linux-davidm/arch/ia64/mm/fault.c Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/arch/ia64/mm/fault.c Mon Sep 24 21:58:13 2001
@@ -1,8 +1,8 @@
/*
* MMU fault handling support.
*
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -16,7 +16,7 @@
#include <asm/uaccess.h>
#include <asm/hardirq.h>

-extern void die_if_kernel (char *, struct pt_regs *, long);
+extern void die (char *, struct pt_regs *, long);

/*
* This routine is analogous to expand_stack() but instead grows the
@@ -46,16 +46,15 @@
void
ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
{
+ int signal = SIGSEGV, code = SEGV_MAPERR;
+ struct vm_area_struct *vma, *prev_vma;
struct mm_struct *mm = current->mm;
struct exception_fixup fix;
- struct vm_area_struct *vma, *prev_vma;
struct siginfo si;
- int signal = SIGSEGV;
unsigned long mask;

/*
- * If we're in an interrupt or have no user
- * context, we must not take the fault..
+ * If we're in an interrupt or have no user context, we must not take the fault..
*/
if (in_interrupt() || !mm)
goto no_context;
@@ -71,6 +70,8 @@
goto check_expansion;

good_area:
+ code = SEGV_ACCERR;
+
/* OK, we've got a good vm_area for this memory area. Check the access permissions: */

# define VM_READ_BIT 0
@@ -89,12 +90,13 @@
if ((vma->vm_flags & mask) != mask)
goto bad_area;

+ survive:
/*
* If for any reason at all we couldn't handle the fault, make
* sure we exit gracefully rather than endlessly redo the
* fault.
*/
- switch (handle_mm_fault(mm, vma, address, mask) != 0) {
+ switch (handle_mm_fault(mm, vma, address, mask)) {
case 1:
++current->min_flt;
break;
@@ -147,7 +149,7 @@
if (user_mode(regs)) {
si.si_signo = signal;
si.si_errno = 0;
- si.si_code = SI_KERNEL;
+ si.si_code = code;
si.si_addr = (void *) address;
force_sig_info(signal, &si, current);
return;
@@ -174,17 +176,29 @@
}

/*
- * Oops. The kernel tried to access some bad page. We'll have
- * to terminate things with extreme prejudice.
+ * Oops. The kernel tried to access some bad page. We'll have to terminate things
+ * with extreme prejudice.
*/
- printk(KERN_ALERT "Unable to handle kernel paging request at "
- "virtual address %016lx\n", address);
- die_if_kernel("Oops", regs, isr);
+ bust_spinlocks(1);
+
+ if (address < PAGE_SIZE)
+ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+ else
+ printk(KERN_ALERT "Unable to handle kernel paging request at "
+ "virtual address %016lx\n", address);
+ die("Oops", regs, isr);
+ bust_spinlocks(0);
do_exit(SIGKILL);
return;

out_of_memory:
up_read(&mm->mmap_sem);
+ if (current->pid = 1) {
+ current->policy |= SCHED_YIELD;
+ schedule();
+ down_read(&mm->mmap_sem);
+ goto survive;
+ }
printk("VM: killing process %s\n", current->comm);
if (user_mode(regs))
do_exit(SIGKILL);
diff -urN linux-davidm/arch/ia64/mm/tlb.c linux-2.4.10-lia/arch/ia64/mm/tlb.c
--- linux-davidm/arch/ia64/mm/tlb.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/arch/ia64/mm/tlb.c Mon Sep 24 21:59:16 2001
@@ -2,7 +2,7 @@
* TLB support routines.
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*
* 08/02/00 A. Mallick <asit.k.mallick@intel.com>
* Modified RID allocation for SMP
@@ -41,11 +41,6 @@
};

/*
- * Seralize usage of ptc.g
- */
-spinlock_t ptcg_lock = SPIN_LOCK_UNLOCKED; /* see <asm/pgtable.h> */
-
-/*
* Acquire the ia64_ctx.lock before calling this function!
*/
void
@@ -84,6 +79,26 @@
flush_tlb_all();
}

+static void
+ia64_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits)
+{
+ static spinlock_t ptcg_lock = SPIN_LOCK_UNLOCKED;
+
+ /* HW requires global serialization of ptc.ga. */
+ spin_lock(&ptcg_lock);
+ {
+ do {
+ /*
+ * Flush ALAT entries also.
+ */
+ asm volatile ("ptc.ga %0,%1;;srlz.i;;" :: "r"(start), "r"(nbits<<2)
+ : "memory");
+ start += (1UL << nbits);
+ } while (start < end);
+ }
+ spin_unlock(&ptcg_lock);
+}
+
void
__flush_tlb_all (void)
{
@@ -144,19 +159,15 @@
}
start &= ~((1UL << nbits) - 1);

- spin_lock(&ptcg_lock);
do {
# ifdef CONFIG_SMP
- /*
- * Flush ALAT entries also.
- */
- asm volatile ("ptc.ga %0,%1;;srlz.i;;" :: "r"(start), "r"(nbits<<2) : "memory");
+ platform_global_tlb_purge(start, end, nbits);
# else
asm volatile ("ptc.l %0,%1" :: "r"(start), "r"(nbits<<2) : "memory");
# endif
start += (1UL << nbits);
} while (start < end);
- spin_unlock(&ptcg_lock);
+
ia64_insn_group_barrier();
ia64_srlz_i(); /* srlz.i implies srlz.d */
ia64_insn_group_barrier();
diff -urN linux-davidm/arch/ia64/tools/print_offsets.c linux-2.4.10-lia/arch/ia64/tools/print_offsets.c
--- linux-davidm/arch/ia64/tools/print_offsets.c Tue Jul 31 10:30:09 2001
+++ linux-2.4.10-lia/arch/ia64/tools/print_offsets.c Mon Sep 24 21:59:30 2001
@@ -61,7 +61,7 @@
{ "IA64_TASK_THREAD_SIGMASK_OFFSET",offsetof (struct task_struct, thread.un.sigmask) },
#endif
#ifdef CONFIG_PERFMON
- { "IA64_TASK_PFM_NOTIFY_OFFSET", offsetof(struct task_struct, thread.pfm_pend_notify) },
+ { "IA64_TASK_PFM_MUST_BLOCK_OFFSET",offsetof(struct task_struct, thread.pfm_must_block) },
#endif
{ "IA64_TASK_PID_OFFSET", offsetof (struct task_struct, pid) },
{ "IA64_TASK_MM_OFFSET", offsetof (struct task_struct, mm) },
@@ -165,17 +165,18 @@
{ "IA64_SIGCONTEXT_FR6_OFFSET", offsetof (struct sigcontext, sc_fr[6]) },
{ "IA64_SIGCONTEXT_PR_OFFSET", offsetof (struct sigcontext, sc_pr) },
{ "IA64_SIGCONTEXT_R12_OFFSET", offsetof (struct sigcontext, sc_gr[12]) },
+ { "IA64_SIGCONTEXT_RBS_BASE_OFFSET",offsetof (struct sigcontext, sc_rbs_base) },
+ { "IA64_SIGCONTEXT_LOADRS_OFFSET", offsetof (struct sigcontext, sc_loadrs) },
{ "IA64_SIGFRAME_ARG0_OFFSET", offsetof (struct sigframe, arg0) },
{ "IA64_SIGFRAME_ARG1_OFFSET", offsetof (struct sigframe, arg1) },
{ "IA64_SIGFRAME_ARG2_OFFSET", offsetof (struct sigframe, arg2) },
- { "IA64_SIGFRAME_RBS_BASE_OFFSET", offsetof (struct sigframe, rbs_base) },
{ "IA64_SIGFRAME_HANDLER_OFFSET", offsetof (struct sigframe, handler) },
{ "IA64_SIGFRAME_SIGCONTEXT_OFFSET", offsetof (struct sigframe, sc) },
{ "IA64_CLONE_VFORK", CLONE_VFORK },
{ "IA64_CLONE_VM", CLONE_VM },
{ "IA64_CPU_IRQ_COUNT_OFFSET", offsetof (struct cpuinfo_ia64, irq_stat.f.irq_count) },
{ "IA64_CPU_BH_COUNT_OFFSET", offsetof (struct cpuinfo_ia64, irq_stat.f.bh_count) },
- { "IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET", offsetof (struct cpuinfo_ia64, phys_stacked_size_p8) },
+ { "IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET",offsetof (struct cpuinfo_ia64, phys_stacked_size_p8)},
};

static const char *tabs = "\t\t\t\t\t\t\t\t\t\t";
diff -urN linux-davidm/drivers/acpi/Makefile linux-2.4.10-lia/drivers/acpi/Makefile
--- linux-davidm/drivers/acpi/Makefile Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/acpi/Makefile Mon Sep 24 21:59:51 2001
@@ -39,7 +39,7 @@
obj-$(CONFIG_ACPI) += os.o acpi_ksyms.o
obj-$(CONFIG_ACPI) += $(foreach dir,$(acpi-subdirs),$(dir)/$(dir).o)
ifdef CONFIG_ACPI_KERNEL_CONFIG
- obj-$(CONFIG_ACPI) += acpiconf.o osconf.o
+ obj-$(CONFIG_ACPI) += acpiconf.o osconf.o driver.o
endif
obj-$(CONFIG_ACPI) += driver.o

diff -urN linux-davidm/drivers/acpi/acpiconf.c linux-2.4.10-lia/drivers/acpi/acpiconf.c
--- linux-davidm/drivers/acpi/acpiconf.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/acpi/acpiconf.c Mon Sep 24 22:00:01 2001
@@ -30,12 +30,12 @@

static int acpi_cf_initialized __initdata = 0;

-ACPI_STATUS __init
+acpi_status __init
acpi_cf_init (
void * rsdp
)
{
- ACPI_STATUS status;
+ acpi_status status;

acpi_os_bind_osd(ACPI_CF_PHASE_BOOTTIME);

@@ -44,9 +44,9 @@
printk ("Acpi cfg:initialize_subsystem error=0x%x\n", status);
return status;
}
- dprintk(("Acpi cfg:initializ_subsysteme pass\n"));
+ dprintk(("Acpi cfg:initialize_subsystem pass\n"));

- status = acpi_load_tables ((u64)rsdp);
+ status = acpi_load_tables ();
if (ACPI_FAILURE(status)) {
printk ("Acpi cfg:load firmware tables error=0x%x\n", status);
acpi_terminate();
@@ -68,13 +68,15 @@
}

-ACPI_STATUS __init
+acpi_status __init
acpi_cf_terminate ( void )
{
- ACPI_STATUS status;
+ acpi_status status;

- if (! ACPI_CF_INITIALIZED())
+ if (! ACPI_CF_INITIALIZED()) {
+ acpi_os_bind_osd(ACPI_CF_PHASE_RUNTIME);
return AE_ERROR;
+ }

status = acpi_disable ();
if (ACPI_FAILURE(status)) {
@@ -97,13 +99,13 @@
}

-ACPI_STATUS __init
+acpi_status __init
acpi_cf_get_pci_vectors (
struct pci_vector_struct **vectors,
int *num_pci_vectors
)
{
- ACPI_STATUS status;
+ acpi_status status;
void *prts;

if (! ACPI_CF_INITIALIZED()) {
@@ -134,28 +136,28 @@
}

-static PCI_ROUTING_TABLE *pci_routing_tables[PCI_MAX_BUS] __initdata = {NULL};
+static pci_routing_table *pci_routing_tables[PCI_MAX_BUS] __initdata = {NULL};

typedef struct _acpi_rpb {
NATIVE_UINT rpb_busnum;
NATIVE_UINT lastbusnum;
- ACPI_HANDLE rpb_handle;
+ acpi_handle rpb_handle;
} acpi_rpb_t;

-static ACPI_STATUS __init
+static acpi_status __init
acpi_cf_evaluate_method (
- ACPI_HANDLE handle,
+ acpi_handle handle,
UINT8 *method_name,
NATIVE_UINT *nuint
)
{
UINT32 tnuint = 0;
- ACPI_STATUS status;
+ acpi_status status;

- ACPI_BUFFER ret_buf;
- ACPI_OBJECT *ext_obj;
+ acpi_buffer ret_buf;
+ acpi_object *ext_obj;
UINT8 buf[PATHNAME_MAX];

@@ -170,7 +172,7 @@
printk("Acpi cfg: %s fail=0x%x\n", method_name, status);
}
} else {
- ext_obj = (ACPI_OBJECT *) ret_buf.pointer;
+ ext_obj = (acpi_object *) ret_buf.pointer;

switch (ext_obj->type) {
case ACPI_TYPE_INTEGER:
@@ -188,14 +190,14 @@
}

-static ACPI_STATUS __init
+static acpi_status __init
acpi_cf_evaluate_PRT (
- ACPI_HANDLE handle,
- PCI_ROUTING_TABLE **prt
+ acpi_handle handle,
+ pci_routing_table **prt
)
{
- ACPI_BUFFER acpi_buffer;
- ACPI_STATUS status;
+ acpi_buffer acpi_buffer;
+ acpi_status status;

acpi_buffer.length = 0;
acpi_buffer.pointer = NULL;
@@ -213,7 +215,7 @@
return status;
}

- *prt = (PCI_ROUTING_TABLE *) acpi_os_callocate (acpi_buffer.length);
+ *prt = (pci_routing_table *) acpi_os_callocate (acpi_buffer.length);
if (!*prt) {
printk("Acpi cfg: callocate %d bytes for _PRT fail\n",
acpi_buffer.length);
@@ -230,23 +232,22 @@
return status;
}

-static ACPI_STATUS __init
+static acpi_status __init
acpi_cf_get_root_pci_callback (
- ACPI_HANDLE handle,
+ acpi_handle handle,
UINT32 Level,
void *context,
void **retval
)
{
NATIVE_UINT busnum = 0;
- ACPI_STATUS status;
+ acpi_status status;
acpi_rpb_t rpb;
- PCI_ROUTING_TABLE *prt;
+ pci_routing_table *prt;

UINT8 path_name[PATHNAME_MAX];
-
#ifdef CONFIG_ACPI_KERNEL_CONFIG_DEBUG
- ACPI_BUFFER ret_buf;
+ acpi_buffer ret_buf;

ret_buf.length = PATHNAME_MAX;
ret_buf.pointer = (void *) path_name;
@@ -313,23 +314,24 @@
/*
* handle _PRTs of immediate P2Ps of root pci.
*/
-static ACPI_STATUS __init
+static acpi_status __init
acpi_cf_associate_prt_to_bus (
- ACPI_HANDLE handle,
+ acpi_handle handle,
acpi_rpb_t *rpb,
NATIVE_UINT *retbusnum,
NATIVE_UINT depth
)
{
- ACPI_STATUS status;
+ acpi_status status;
UINT32 segbus;
NATIVE_UINT devfn;
UINT8 bn;

UINT8 path_name[PATHNAME_MAX];
+ acpi_pci_id pci_id;

#ifdef CONFIG_ACPI_KERNEL_CONFIG_DEBUG
- ACPI_BUFFER ret_buf;
+ acpi_buffer ret_buf;

ret_buf.length = PATHNAME_MAX;
ret_buf.pointer = (void *) path_name;
@@ -356,10 +358,13 @@
* access pci config space for bus number
* segbus = from rpb, devfn = from _ADR
*/
- segbus = (UINT32)(rpb->rpb_busnum & 0xFFFFFFFF);
+ pci_id.segment = 0;
+ pci_id.bus = (u16)(rpb->rpb_busnum & 0xffffffff);
+ pci_id.device = (u16)((devfn >> 16) & 0xffff);
+ pci_id.function = (u16)(devfn & 0xffff);

- status = acpi_os_read_pci_cfg_byte(segbus,
- (UINT32)devfn, PCI_PRIMARY_BUS, &bn);
+ status = acpi_os_read_pci_configuration(&pci_id, PCI_PRIMARY_BUS,
+ &bn, 1);
if (ACPI_FAILURE(status)) {
*retbusnum = rpb->rpb_busnum + 1;
printk("Acpi cfg:%s pci read fail=0x%x. b:df:a=%x:%x:%x\n",
@@ -372,8 +377,8 @@
dprintk(("Acpi cfg:%s pribus %d\n", path_name, bn));

- status = acpi_os_read_pci_cfg_byte(segbus,
- (UINT32)devfn, PCI_SECONDARY_BUS, &bn);
+ status = acpi_os_read_pci_configuration(&pci_id, PCI_SECONDARY_BUS,
+ &bn, 1);
if (ACPI_FAILURE(status)) {
*retbusnum = rpb->rpb_busnum + 1;
printk("Acpi cfg:%s pci read fail=0x%x. b:df:a=%x:%x:%x\n",
@@ -390,12 +395,12 @@
}

-static ACPI_STATUS __init
+static acpi_status __init
acpi_cf_get_prt (
void **prts
)
{
- ACPI_STATUS status;
+ acpi_status status;

status = acpi_get_devices ( PCI_ROOT_HID_STRING,
acpi_cf_get_root_pci_callback,
@@ -411,23 +416,23 @@
return status;
}

-static ACPI_STATUS __init
+static acpi_status __init
acpi_cf_get_prt_callback (
- ACPI_HANDLE handle,
+ acpi_handle handle,
UINT32 Level,
void *context,
void **retval
)
{
- PCI_ROUTING_TABLE *prt;
+ pci_routing_table *prt;
NATIVE_UINT busnum = 0;
NATIVE_UINT temp = 0x0F;
- ACPI_STATUS status;
+ acpi_status status;

UINT8 path_name[PATHNAME_MAX];

#ifdef CONFIG_ACPI_KERNEL_CONFIG_DEBUG
- ACPI_BUFFER ret_buf;
+ acpi_buffer ret_buf;

ret_buf.length = PATHNAME_MAX;
ret_buf.pointer = (void *) path_name;
@@ -487,7 +492,7 @@
static void __init
acpi_cf_add_to_pci_routing_tables (
NATIVE_UINT busnum,
- PCI_ROUTING_TABLE *prt
+ pci_routing_table *prt
)
{
if ( busnum >= PCI_MAX_BUS ) {
@@ -507,7 +512,7 @@

#define DUMPVECTOR(pv) printk("PCI bus=0x%x id=0x%x pin=0x%x irq=0x%x\n", pv->bus, pv->pci_id, pv->pin, pv->irq);

-static ACPI_STATUS __init
+static acpi_status __init
acpi_cf_convert_prt_to_vectors (
void *prts,
struct pci_vector_struct **vectors,
@@ -515,18 +520,18 @@
)
{
struct pci_vector_struct *pvec;
- PCI_ROUTING_TABLE **pprts, *prt, *prtf;
+ pci_routing_table **pprts, *prt, *prtf;
int nvec = 0;
int i;

- pprts = (PCI_ROUTING_TABLE **)prts;
+ pprts = (pci_routing_table **)prts;

for ( i = 0; i < PCI_MAX_BUS; i++) {
prt = *pprts++;
if (prt) {
for ( ; prt->length > 0; nvec++) {
- prt = (PCI_ROUTING_TABLE *) ((NATIVE_UINT)prt + (NATIVE_UINT)prt->length);
+ prt = (pci_routing_table *) ((NATIVE_UINT)prt + (NATIVE_UINT)prt->length);
}
}
}
@@ -539,7 +544,7 @@
}

pvec = *vectors;
- pprts = (PCI_ROUTING_TABLE **)prts;
+ pprts = (pci_routing_table **)prts;

for ( i = 0; i < PCI_MAX_BUS; i++) {
prt = prtf = *pprts++;
@@ -550,7 +555,7 @@
pvec->pin = (UINT8)prt->pin;
pvec->irq = (UINT8)prt->source_index;

- prt = (PCI_ROUTING_TABLE *) ((NATIVE_UINT)prt + (NATIVE_UINT)prt->length);
+ prt = (pci_routing_table *) ((NATIVE_UINT)prt + (NATIVE_UINT)prt->length);
}
acpi_os_free((void *)prtf);
}
diff -urN linux-davidm/drivers/acpi/acpiconf.h linux-2.4.10-lia/drivers/acpi/acpiconf.h
--- linux-davidm/drivers/acpi/acpiconf.h Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/acpi/acpiconf.h Mon Sep 24 22:21:57 2001
@@ -27,14 +27,14 @@

static
-ACPI_STATUS __init
+acpi_status __init
acpi_cf_get_prt (void **prts);

static
-ACPI_STATUS __init
+acpi_status __init
acpi_cf_get_prt_callback (
- ACPI_HANDLE handle,
+ acpi_handle handle,
UINT32 level,
void *context,
void **retval
@@ -45,12 +45,12 @@
void __init
acpi_cf_add_to_pci_routing_tables (
NATIVE_UINT busnum,
- PCI_ROUTING_TABLE *prt
+ pci_routing_table *prt
);

static
-ACPI_STATUS __init
+acpi_status __init
acpi_cf_convert_prt_to_vectors (
void *prts,
struct pci_vector_struct **vectors,
diff -urN linux-davidm/drivers/acpi/driver.c linux-2.4.10-lia/drivers/acpi/driver.c
--- linux-davidm/drivers/acpi/driver.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/acpi/driver.c Mon Sep 24 21:30:52 2001
@@ -112,9 +112,7 @@

printk(KERN_INFO "ACPI: Subsystem enabled\n");

-#ifdef CONFIG_PM
pm_active = 1;
-#endif

return 0;
}
@@ -127,9 +125,7 @@
{
acpi_terminate();

-#ifdef CONFIG_PM
pm_active = 0;
-#endif

printk(KERN_ERR "ACPI: Subsystem disabled\n");
}
diff -urN linux-davidm/drivers/acpi/hardware/hwacpi.c linux-2.4.10-lia/drivers/acpi/hardware/hwacpi.c
--- linux-davidm/drivers/acpi/hardware/hwacpi.c Mon Sep 24 15:06:41 2001
+++ linux-2.4.10-lia/drivers/acpi/hardware/hwacpi.c Mon Sep 24 22:00:26 2001
@@ -196,6 +196,7 @@
{

acpi_status status = AE_NO_HARDWARE_RESPONSE;
+ u32 retries = 20;

FUNCTION_TRACE ("Hw_set_mode");
@@ -220,11 +221,14 @@

/* Give the platform some time to react */

- acpi_os_stall (5000);
+ while (retries-- > 0) {
+ acpi_os_stall (5000);

- if (acpi_hw_get_mode () = mode) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", mode));
- status = AE_OK;
+ if (acpi_hw_get_mode () = mode) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Mode %X successfully enabled\n", mode));
+ status = AE_OK;
+ break;
+ }
}

return_ACPI_STATUS (status);
diff -urN linux-davidm/drivers/acpi/include/actypes.h linux-2.4.10-lia/drivers/acpi/include/actypes.h
--- linux-davidm/drivers/acpi/include/actypes.h Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/acpi/include/actypes.h Mon Sep 24 22:00:40 2001
@@ -60,7 +60,7 @@
typedef int INT32;
typedef unsigned int UINT32;
typedef COMPILER_DEPENDENT_UINT64 UINT64;
-typedef long INT64;
+typedef long INT64;

typedef UINT64 NATIVE_UINT;
typedef INT64 NATIVE_INT;
diff -urN linux-davidm/drivers/acpi/os.c linux-2.4.10-lia/drivers/acpi/os.c
--- linux-davidm/drivers/acpi/os.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/acpi/os.c Mon Sep 24 21:30:48 2001
@@ -39,13 +39,10 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/kmod.h>
-#include <linux/irq.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <acpi.h>
-#ifndef CONFIG_ACPI_KERNEL_CONFIG_ONLY
#include "driver.h"
-#endif

#ifdef CONFIG_ACPI_EFI
#include <asm/efi.h>
@@ -53,7 +50,8 @@

#ifdef _IA64
#include <asm/hw_irq.h>
-#endif
+#include <asm/delay.h>
+#endif

#define _COMPONENT ACPI_OS_SERVICES
MODULE_NAME ("os")
@@ -66,7 +64,7 @@

/*****************************************************************************
- * Debugger Stuff
+ * Function Binding
*****************************************************************************/

#ifdef CONFIG_ACPI_KERNEL_CONFIG
@@ -78,26 +76,24 @@
acpi_os_callocate_rt,
acpi_os_free_rt,
acpi_os_queue_for_execution_rt,
- acpi_os_read_pci_cfg_byte_rt,
- acpi_os_read_pci_cfg_word_rt,
- acpi_os_read_pci_cfg_dword_rt,
- acpi_os_write_pci_cfg_byte_rt,
- acpi_os_write_pci_cfg_word_rt,
- acpi_os_write_pci_cfg_dword_rt
+ acpi_os_read_pci_configuration_rt,
+ acpi_os_write_pci_configuration_rt,
+ acpi_os_stall_rt
};
#else
#define acpi_os_allocate_rt acpi_os_allocate
#define acpi_os_callocate_rt acpi_os_callocate
#define acpi_os_free_rt acpi_os_free
#define acpi_os_queue_for_execution_rt acpi_os_queue_for_execution
-#define acpi_os_read_pci_cfg_byte_rt acpi_os_read_pci_cfg_byte
-#define acpi_os_read_pci_cfg_word_rt acpi_os_read_pci_cfg_word
-#define acpi_os_read_pci_cfg_dword_rt acpi_os_read_pci_cfg_dword
-#define acpi_os_write_pci_cfg_byte_rt acpi_os_write_pci_cfg_byte
-#define acpi_os_write_pci_cfg_word_rt acpi_os_write_pci_cfg_word
-#define acpi_os_write_pci_cfg_dword_rt acpi_os_write_pci_cfg_dword
+#define acpi_os_read_pci_configuration_rt acpi_os_read_pci_configuration
+#define acpi_os_write_pci_configuration_rt acpi_os_write_pci_configuration
+#define acpi_os_stall_rt acpi_os_stall
#endif

+/*****************************************************************************
+ * Debugger Stuff
+ *****************************************************************************/
+
#ifdef ENABLE_DEBUGGER

#include <linux/kdb.h>
@@ -267,12 +263,105 @@
(*acpi_irq_handler)(acpi_irq_context);
}

+#ifdef CONFIG_ACPI_KERNEL_CONFIG
+struct irqaction acpiirqaction;
+/*
+ * codes from request_irq and free_irq.
+ */
acpi_status
acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context)
{
-#ifdef _IA64
+ struct irqaction *act;
+ int retval;
+
+ if (irq >= NR_IRQS) {
+ printk("ACPI: install SCI handler fail: invalid irq%d\n", irq);
+ return AE_ERROR;
+ }
+
+ if (!handler) {
+ printk("ACPI: install SCI handler fail: invalid handler\n");
+ return AE_ERROR;
+ }
+
+ act = & acpiirqaction;
+
irq = isa_irq_to_vector(irq);
-#endif /*_IA64*/
+ acpi_irq_irq = irq;
+ acpi_irq_handler = handler;
+ acpi_irq_context = context;
+
+ act->handler = acpi_irq;
+ act->flags = SA_INTERRUPT | SA_SHIRQ;
+ act->mask = 0;
+ act->name = "acpi";
+ act->next = NULL;
+ act->dev_id = acpi_irq;
+
+ retval = setup_irq(irq, act);
+ if (retval) {
+ printk("ACPI: install SCI handler fail: setup_irq\n");
+ acpi_irq_handler = NULL;
+ return AE_ERROR;
+ }
+ printk("ACPI: install SCI %d handler pass\n", irq);
+
+ return AE_OK;
+}
+
+acpi_status
+acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler)
+{
+ irq_desc_t *desc;
+ struct irqaction **p;
+ unsigned long flags;
+
+ if (!acpi_irq_handler)
+ return AE_OK;
+
+ irq = isa_irq_to_vector(irq);
+ if (irq != acpi_irq_irq) return AE_ERROR;
+
+ acpi_irq_handler = NULL;
+
+ desc = irq_desc(irq);
+ spin_lock_irqsave(&desc->lock,flags);
+ p = &desc->action;
+ for (;;) {
+ struct irqaction * action = *p;
+ if (action) {
+ struct irqaction **pp = p;
+ p = &action->next;
+ if (action->dev_id != acpi_irq)
+ continue;
+
+ /* Found it - now remove it from the list of entries */
+ *pp = action->next;
+ if (!desc->action) {
+ desc->status |= IRQ_DISABLED;
+ desc->handler->shutdown(irq);
+ }
+ spin_unlock_irqrestore(&desc->lock,flags);
+
+#ifdef CONFIG_SMP
+ /* Wait to make sure it's not being used on another CPU */
+ while (desc->status & IRQ_INPROGRESS)
+ barrier();
+#endif
+ return AE_OK;
+ }
+ printk("ACPI: Trying to free free IRQ%d\n",irq);
+ spin_unlock_irqrestore(&desc->lock,flags);
+ return AE_OK;
+ }
+
+ return AE_OK;
+}
+
+#else
+acpi_status
+acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context)
+{
acpi_irq_irq = irq;
acpi_irq_handler = handler;
acpi_irq_context = context;
@@ -315,7 +404,7 @@
}

void
-acpi_os_stall(u32 us)
+acpi_os_stall_rt(u32 us)
{
if (us > 10000) {
mdelay(us / 1000);
@@ -357,7 +446,7 @@
acpi_status
acpi_os_write_port(
ACPI_IO_ADDRESS port,
- u32 value,
+ NATIVE_UINT value,
u32 width)
{
switch (width)
@@ -410,7 +499,7 @@
acpi_status
acpi_os_write_memory(
ACPI_PHYSICAL_ADDRESS phys_addr,
- u32 value,
+ NATIVE_UINT value,
u32 width)
{
switch (width)
@@ -470,27 +559,6 @@
return (result ? AE_ERROR : AE_OK);
}

-#ifdef CONFIG_ACPI_KERNEL_CONFIG
-/*
- * Queue for interpreter thread
- */
-
-ACPI_STATUS
-acpi_os_queue_for_execution_rt(
- u32 priority,
- OSD_EXECUTION_CALLBACK callback,
- void *context)
-{
-# ifndef CONFIG_ACPI_KERNEL_CONFIG_ONLY
- if (acpi_run(callback, context))
- return AE_ERROR;
-# else
- (*callback)(context);
-# endif
- return AE_OK;
-}
-#endif
-
acpi_status
acpi_os_write_pci_configuration (
acpi_pci_id *pci_id,
@@ -524,7 +592,7 @@
#else /*CONFIG_ACPI_PCI*/

acpi_status
-acpi_os_read_pci_configuration (
+acpi_os_read_pci_configuration_rt (
acpi_pci_id *pci_id,
u32 reg,
void *value,
@@ -558,10 +626,10 @@
}

acpi_status
-acpi_os_write_pci_configuration (
+acpi_os_write_pci_configuration_rt (
acpi_pci_id *pci_id,
u32 reg,
- u32 value,
+ NATIVE_UINT value,
u32 width)
{
int devfn = PCI_DEVFN(pci_id->device, pci_id->function);
@@ -676,6 +744,22 @@
acpi_os_free(dpc);
}
}
+
+#ifdef CONFIG_ACPI_KERNEL_CONFIG
+/*
+ * Queue for interpreter thread
+ */
+
+acpi_status
+acpi_os_queue_for_execution_rt(
+ u32 priority,
+ OSD_EXECUTION_CALLBACK callback,
+ void *context)
+{
+ (*callback)(context);
+ return AE_OK;
+}
+#endif

acpi_status
acpi_os_queue_for_execution(
diff -urN linux-davidm/drivers/acpi/osconf.c linux-2.4.10-lia/drivers/acpi/osconf.c
--- linux-davidm/drivers/acpi/osconf.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/acpi/osconf.c Mon Sep 24 22:00:48 2001
@@ -16,6 +16,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/sal.h>
+#include <asm/delay.h>

#include "acpi.h"
#include "osconf.h"
@@ -24,34 +25,22 @@
static void * __init acpi_os_allocate_bt(u32 size);
static void * __init acpi_os_callocate_bt(u32 size);
static void __init acpi_os_free_bt(void *ptr);
+static void __init acpi_os_stall_bt(u32 us);

-static ACPI_STATUS __init
+static acpi_status __init
acpi_os_queue_for_execution_bt(
u32 priority,
OSD_EXECUTION_CALLBACK callback,
void *context
);

-static ACPI_STATUS __init
-acpi_os_read_pci_cfg_byte_bt( u32 segbus, u32 func, u32 addr, u8 * val);
+static acpi_status __init
+acpi_os_read_pci_configuration_bt( acpi_pci_id *pci_id, u32 reg, void *value, u32 width);

-static ACPI_STATUS __init
-acpi_os_read_pci_cfg_word_bt( u32 segbus, u32 func, u32 addr, u16 * val);
+static acpi_status __init
+acpi_os_write_pci_configuration_bt( acpi_pci_id *pci_id, u32 reg, NATIVE_UINT value, u32 width);

-static ACPI_STATUS __init
-acpi_os_read_pci_cfg_dword_bt( u32 segbus, u32 func, u32 addr, u32 * val);

-static ACPI_STATUS __init
-acpi_os_write_pci_cfg_byte_bt( u32 segbus, u32 func, u32 addr, u8 val);
-
-static ACPI_STATUS __init
-acpi_os_write_pci_cfg_word_bt( u32 segbus, u32 func, u32 addr, u16 val);
-
-static ACPI_STATUS __init
-acpi_os_write_pci_cfg_dword_bt( u32 segbus, u32 func, u32 addr, u32 val);
-
-
-static struct acpi_osd *acpi_osd;
extern struct acpi_osd acpi_osd_rt;
static struct acpi_osd acpi_osd_bt __initdata = {
/* these are boottime osd entries that differ from runtime entries */
@@ -59,13 +48,11 @@
acpi_os_callocate_bt,
acpi_os_free_bt,
acpi_os_queue_for_execution_bt,
- acpi_os_read_pci_cfg_byte_bt,
- acpi_os_read_pci_cfg_word_bt,
- acpi_os_read_pci_cfg_dword_bt,
- acpi_os_write_pci_cfg_byte_bt,
- acpi_os_write_pci_cfg_word_bt,
- acpi_os_write_pci_cfg_dword_bt
+ acpi_os_read_pci_configuration_bt,
+ acpi_os_write_pci_configuration_bt,
+ acpi_os_stall_bt
};
+static struct acpi_osd *acpi_osd = &acpi_osd_rt;

#ifdef CONFIG_ACPI_KERNEL_CONFIG_BM_PROFILE
static void __init
@@ -110,48 +97,27 @@
return;
}

-
-ACPI_STATUS
-acpi_os_read_pci_cfg_byte( u32 segbus, u32 func, u32 addr, u8 * val)
-{
- return acpi_osd->read_pci_cfg_byte(segbus, func, addr, val);
-}
-
-
-ACPI_STATUS
-acpi_os_read_pci_cfg_word( u32 segbus, u32 func, u32 addr, u16 * val)
-{
- return acpi_osd->read_pci_cfg_word(segbus, func, addr, val);
-}
-
-
-ACPI_STATUS
-acpi_os_read_pci_cfg_dword( u32 segbus, u32 func, u32 addr, u32 * val)
+void
+acpi_os_stall(u32 us)
{
- return acpi_osd->read_pci_cfg_dword(segbus, func, addr, val);
+ acpi_osd->stall(us);
+ return;
}

-
-ACPI_STATUS
-acpi_os_write_pci_cfg_byte( u32 segbus, u32 func, u32 addr, u8 val)
+acpi_status
+acpi_os_read_pci_configuration( acpi_pci_id *pci_id, u32 reg, void *value, u32 width)
{
- return acpi_osd->write_pci_cfg_byte(segbus, func, addr, val);
+ return acpi_osd->read_pci_configuration(pci_id, reg, value, width);
}

-ACPI_STATUS
-acpi_os_write_pci_cfg_word( u32 segbus, u32 func, u32 addr, u16 val)
+acpi_status
+acpi_os_write_pci_configuration( acpi_pci_id *pci_id, u32 reg, NATIVE_UINT value, u32 width)
{
- return acpi_osd->write_pci_cfg_word(segbus, func, addr, val);
+ return acpi_osd->write_pci_configuration(pci_id, reg, value, width);
}

-ACPI_STATUS
-acpi_os_write_pci_cfg_dword( u32 segbus, u32 func, u32 addr, u32 val)
-{
- return acpi_osd->write_pci_cfg_dword(segbus, func, addr, val);
-}
-
#ifdef CONFIG_ACPI_KERNEL_CONFIG_BM_PROFILE
/*
* Let's profile bootmem usage to see how much we consume. J.I.
@@ -230,7 +196,17 @@
}

-static ACPI_STATUS __init
+static void __init
+acpi_os_stall_bt(u32 us)
+{
+ unsigned long start = ia64_get_itc();
+ unsigned long cycles = us*733; /* XXX: 733 or 800 */
+ while (ia64_get_itc() - start < cycles)
+ /* skip */;
+}
+
+
+static acpi_status __init
acpi_os_queue_for_execution_bt(
u32 priority,
OSD_EXECUTION_CALLBACK callback,
@@ -244,78 +220,67 @@
}

-static ACPI_STATUS __init
-acpi_os_read_pci_cfg_byte_bt( u32 segbus, u32 func, u32 addr, u8 * val)
+static acpi_status __init
+acpi_os_read_pci_configuration_bt (
+ acpi_pci_id *pci_id,
+ u32 reg,
+ void *value,
+ u32 width)
{
unsigned int devfn;
s64 status;
u64 lval;

- devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 1, &lval);
- *val = lval;
-
- return status;
-}
-
-
-static ACPI_STATUS __init
-acpi_os_read_pci_cfg_word_bt( u32 segbus, u32 func, u32 addr, u16 * val)
-{
- unsigned int devfn;
- s64 status;
- u64 lval;
+ devfn = PCI_DEVFN(pci_id->device, pci_id->function);

- devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 2, &lval);
- *val = lval;
+ switch (width)
+ {
+ case 8:
+ status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS((pci_id->bus), devfn, reg), 1, &lval);
+ *(u8*)value = (u8)lval;
+ break;
+ case 16:
+ status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS((pci_id->bus), devfn, reg), 2, &lval);
+ *(u16*)value = (u16)lval;
+ break;
+ case 32:
+ status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS((pci_id->bus), devfn, reg), 4, &lval);
+ *(u32*)value = (u32)lval;
+ break;
+ default:
+ BUG();
+ }

return status;
}

-static ACPI_STATUS __init
-acpi_os_read_pci_cfg_dword_bt( u32 segbus, u32 func, u32 addr, u32 * val)
+static acpi_status __init
+acpi_os_write_pci_configuration_bt (
+ acpi_pci_id *pci_id,
+ u32 reg,
+ NATIVE_UINT value,
+ u32 width)
{
unsigned int devfn;
s64 status;
- u64 lval;
-
- devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 4, &lval);
- *val = lval;
-
- return status;
-}
-
-
-static ACPI_STATUS __init
-acpi_os_write_pci_cfg_byte_bt( u32 segbus, u32 func, u32 addr, u8 val)
-{
- unsigned int devfn;
-
- devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 1, val);
-}

+ devfn = PCI_DEVFN(pci_id->device, pci_id->function);

-static ACPI_STATUS __init
-acpi_os_write_pci_cfg_word_bt( u32 segbus, u32 func, u32 addr, u16 val)
-{
- unsigned int devfn;
-
- devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 2, val);
-}
-
-
-static ACPI_STATUS __init
-acpi_os_write_pci_cfg_dword_bt( u32 segbus, u32 func, u32 addr, u32 val)
-{
- unsigned int devfn;
+ switch (width)
+ {
+ case 8:
+ status = ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS((pci_id->bus), devfn, reg), 1, value);
+ break;
+ case 16:
+ status = ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS((pci_id->bus), devfn, reg), 2, value);
+ break;
+ case 32:
+ status = ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS((pci_id->bus), devfn, reg), 4, value);
+ break;
+ default:
+ BUG();
+ }

- devfn = PCI_DEVFN((func >> 16) & 0xffff, func & 0xffff);
- return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS((segbus & 0xffff), devfn, addr), 4, val);
+ return status;
}
-
-
diff -urN linux-davidm/drivers/acpi/osconf.h linux-2.4.10-lia/drivers/acpi/osconf.h
--- linux-davidm/drivers/acpi/osconf.h Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/acpi/osconf.h Mon Sep 24 22:01:49 2001
@@ -10,13 +10,10 @@
void * (*allocate)(u32 size);
void * (*callocate)(u32 size);
void (*free)(void *ptr);
- ACPI_STATUS (*queue_for_exec)(u32 pri, OSD_EXECUTION_CALLBACK cb, void *context);
- ACPI_STATUS (*read_pci_cfg_byte)(u32 bus, u32 func, u32 addr, u8 *val);
- ACPI_STATUS (*read_pci_cfg_word)(u32 bus, u32 func, u32 addr, u16 *val);
- ACPI_STATUS (*read_pci_cfg_dword)(u32 bus, u32 func, u32 addr, u32 *val);
- ACPI_STATUS (*write_pci_cfg_byte)(u32 bus, u32 func, u32 addr, u8 val);
- ACPI_STATUS (*write_pci_cfg_word)(u32 bus, u32 func, u32 addr, u16 val);
- ACPI_STATUS (*write_pci_cfg_dword)(u32 bus, u32 func, u32 addr, u32 val);
+ acpi_status (*queue_for_exec)(u32 pri, OSD_EXECUTION_CALLBACK cb, void *context);
+ acpi_status (*read_pci_configuration)(acpi_pci_id *pci_id, u32 reg, void *value, u32 width);
+ acpi_status (*write_pci_configuration)(acpi_pci_id *pci_id, u32 reg, NATIVE_UINT value, u32 width);
+ void (*stall)(u32 us);
};

@@ -31,54 +28,30 @@
void * acpi_os_allocate(u32 size);
void * acpi_os_callocate(u32 size);
void acpi_os_free(void *ptr);
+void acpi_os_stall(u32 us);

+acpi_status
+acpi_os_read_pci_configuration( acpi_pci_id *pci_id, u32 reg, void *value, u32 width );

-ACPI_STATUS
-acpi_os_read_pci_cfg_byte( u32 segbus, u32 func, u32 addr, u8 * val);
-
-ACPI_STATUS
-acpi_os_read_pci_cfg_word( u32 segbus, u32 func, u32 addr, u16 * val);
-
-ACPI_STATUS
-acpi_os_read_pci_cfg_dword( u32 segbus, u32 func, u32 addr, u32 * val);
-
-ACPI_STATUS
-acpi_os_write_pci_cfg_byte( u32 segbus, u32 func, u32 addr, u8 val);
-
-ACPI_STATUS
-acpi_os_write_pci_cfg_word( u32 segbus, u32 func, u32 addr, u16 val);
-
-ACPI_STATUS
-acpi_os_write_pci_cfg_dword( u32 segbus, u32 func, u32 addr, u32 val);
+acpi_status
+acpi_os_write_pci_configuration( acpi_pci_id *pci_id, u32 reg, NATIVE_UINT value, u32 width );

/* acpi_osd_rt functions */
extern void * acpi_os_allocate_rt(u32 size);
extern void * acpi_os_callocate_rt(u32 size);
extern void acpi_os_free_rt(void *ptr);
+extern void acpi_os_stall_rt(u32 us);

-extern ACPI_STATUS
+extern acpi_status
acpi_os_queue_for_execution_rt(
u32 priority,
OSD_EXECUTION_CALLBACK callback,
void *context
);

-extern ACPI_STATUS
-acpi_os_read_pci_cfg_byte_rt( u32 segbus, u32 func, u32 addr, u8 * val);
-
-extern ACPI_STATUS
-acpi_os_read_pci_cfg_word_rt( u32 segbus, u32 func, u32 addr, u16 * val);
-
-extern ACPI_STATUS
-acpi_os_read_pci_cfg_dword_rt( u32 segbus, u32 func, u32 addr, u32 * val);
-
-extern ACPI_STATUS
-acpi_os_write_pci_cfg_byte_rt( u32 segbus, u32 func, u32 addr, u8 val);
-
-extern ACPI_STATUS
-acpi_os_write_pci_cfg_word_rt( u32 segbus, u32 func, u32 addr, u16 val);
-
-extern ACPI_STATUS
-acpi_os_write_pci_cfg_dword_rt( u32 segbus, u32 func, u32 addr, u32 val);
+extern acpi_status
+acpi_os_read_pci_configuration_rt( acpi_pci_id *pci_id, u32 reg, void *value, u32 width );

+extern acpi_status
+acpi_os_write_pci_configuration_rt( acpi_pci_id *pci_id, u32 reg, NATIVE_UINT value, u32 width );
diff -urN linux-davidm/drivers/acpi/ospm/include/ec.h linux-2.4.10-lia/drivers/acpi/ospm/include/ec.h
--- linux-davidm/drivers/acpi/ospm/include/ec.h Mon Sep 24 15:06:44 2001
+++ linux-2.4.10-lia/drivers/acpi/ospm/include/ec.h Mon Sep 24 22:03:30 2001
@@ -167,14 +167,14 @@
acpi_status
ec_io_read (
EC_CONTEXT *ec,
- u32 io_port,
+ ACPI_IO_ADDRESS io_port,
u8 *data,
EC_EVENT wait_event);

acpi_status
ec_io_write (
EC_CONTEXT *ec,
- u32 io_port,
+ ACPI_IO_ADDRESS io_port,
u8 data,
EC_EVENT wait_event);

diff -urN linux-davidm/drivers/acpi/ospm/system/sm_osl.c linux-2.4.10-lia/drivers/acpi/ospm/system/sm_osl.c
--- linux-davidm/drivers/acpi/ospm/system/sm_osl.c Mon Sep 24 15:06:44 2001
+++ linux-2.4.10-lia/drivers/acpi/ospm/system/sm_osl.c Mon Sep 24 22:03:42 2001
@@ -33,7 +33,9 @@
#include <asm/uaccess.h>
#include <linux/acpi.h>
#include <asm/io.h>
+#ifndef __ia64__
#include <linux/mc146818rtc.h>
+#endif
#include <linux/delay.h>

#include <acpi.h>
@@ -278,6 +280,7 @@
int *eof,
void *context)
{
+#ifndef _IA64
char *str = page;
int len;
u32 sec,min,hr;
@@ -351,6 +354,9 @@
*start = page;

return len;
+#else
+ return 0;
+#endif
}

static int get_date_field(char **str, u32 *value)
@@ -381,6 +387,7 @@
unsigned long count,
void *data)
{
+#ifndef _IA64
char buf[30];
char *str = buf;
u32 sec,min,hr;
@@ -520,6 +527,9 @@
error = 0;
out:
return error ? error : count;
+#else
+ return 0;
+#endif
}

static int
diff -urN linux-davidm/drivers/char/agp/agpgart_be.c linux-2.4.10-lia/drivers/char/agp/agpgart_be.c
--- linux-davidm/drivers/char/agp/agpgart_be.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/char/agp/agpgart_be.c Mon Sep 24 16:11:04 2001
@@ -466,9 +466,9 @@
/*
* Driver routines - start
* Currently this module supports the following chipsets:
- * i810, i815, 440lx, 440bx, 440gx, i840, i850, via vp3, via mvp3,
- * via kx133, via kt133, amd irongate, amd 761, amd 762, ALi M1541,
- * and generic support for the SiS chipsets.
+ * i810, 440lx, 440bx, 440gx, 460gx, i840, i850, via vp3, via mvp3, via kx133,
+ * via kt133, amd irongate, ALi M1541, and generic support for the SiS
+ * chipsets.
*/

/* Generic Agp routines - Start */
@@ -1200,6 +1200,633 @@

#endif /* CONFIG_AGP_I810 */

+#ifdef CONFIG_AGP_I460
+
+/* BIOS configures the chipset so that one of two apbase registers are used */
+static u8 intel_i460_dynamic_apbase = 0x10;
+
+/* 460 supports multiple GART page sizes, so GART pageshift is dynamic */
+static u8 intel_i460_pageshift = 12;
+
+/* Keep track of which is larger, chipset or kernel page size. */
+static u32 intel_i460_cpk = 1;
+
+/* Structure for tracking partial use of 4MB GART pages */
+static u32 **i460_pg_detail = NULL;
+static u32 *i460_pg_count = NULL;
+
+#define I460_CPAGES_PER_KPAGE (PAGE_SIZE >> intel_i460_pageshift)
+#define I460_KPAGES_PER_CPAGE ((1 << intel_i460_pageshift) >> PAGE_SHIFT)
+
+#define I460_SRAM_IO_DISABLE (1 << 4)
+#define I460_BAPBASE_ENABLE (1 << 3)
+#define I460_AGPSIZ_MASK 0x7
+#define I460_4M_PS (1 << 1)
+
+#define log2(x) ffz(~(x))
+
+static int intel_i460_fetch_size(void)
+{
+ int i;
+ u8 temp;
+ aper_size_info_8 *values;
+
+ /* Determine the GART page size */
+ pci_read_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, &temp);
+ intel_i460_pageshift = (temp & I460_4M_PS) ? 22 : 12;
+
+ values = A_SIZE_8(agp_bridge.aperture_sizes);
+
+ pci_read_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ, &temp);
+
+ /* Exit now if the IO drivers for the GART SRAMS are turned off */
+ if(temp & I460_SRAM_IO_DISABLE) {
+ printk("[agpgart] GART SRAMS disabled on 460GX chipset\n");
+ printk("[agpgart] AGPGART operation not possible\n");
+ return 0;
+ }
+
+ /* Make sure we don't try to create an 2 ^ 23 entry GATT */
+ if((intel_i460_pageshift = 0) && ((temp & I460_AGPSIZ_MASK) = 4)) {
+ printk("[agpgart] We can't have a 32GB aperture with 4KB"
+ " GART pages\n");
+ return 0;
+ }
+
+ /* Determine the proper APBASE register */
+ if(temp & I460_BAPBASE_ENABLE)
+ intel_i460_dynamic_apbase = INTEL_I460_BAPBASE;
+ else intel_i460_dynamic_apbase = INTEL_I460_APBASE;
+
+ for (i = 0; i < agp_bridge.num_aperture_sizes; i++) {
+
+ /*
+ * Dynamically calculate the proper num_entries and page_order
+ * values for the define aperture sizes. Take care not to
+ * shift off the end of values[i].size.
+ */
+ values[i].num_entries = (values[i].size << 8) >>
+ (intel_i460_pageshift - 12);
+ values[i].page_order = log2((sizeof(u32)*values[i].num_entries)
+ >> PAGE_SHIFT);
+ }
+
+ for (i = 0; i < agp_bridge.num_aperture_sizes; i++) {
+ /* Neglect control bits when matching up size_value */
+ if ((temp & I460_AGPSIZ_MASK) = values[i].size_value) {
+ agp_bridge.previous_size + agp_bridge.current_size = (void *) (values + i);
+ agp_bridge.aperture_size_idx = i;
+ return values[i].size;
+ }
+ }
+
+ return 0;
+}
+
+/* There isn't anything to do here since 460 has no GART TLB. */
+static void intel_i460_tlb_flush(agp_memory * mem)
+{
+ return;
+}
+
+/*
+ * This utility function is needed to prevent corruption of the control bits
+ * which are stored along with the aperture size in 460's AGPSIZ register
+ */
+static void intel_i460_write_agpsiz(u8 size_value)
+{
+ u8 temp;
+
+ pci_read_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ, &temp);
+ pci_write_config_byte(agp_bridge.dev, INTEL_I460_AGPSIZ,
+ ((temp & ~I460_AGPSIZ_MASK) | size_value));
+}
+
+static void intel_i460_cleanup(void)
+{
+ aper_size_info_8 *previous_size;
+
+ previous_size = A_SIZE_8(agp_bridge.previous_size);
+ intel_i460_write_agpsiz(previous_size->size_value);
+
+ if(intel_i460_cpk = 0)
+ {
+ vfree(i460_pg_detail);
+ vfree(i460_pg_count);
+ }
+}
+
+
+/* Control bits for Out-Of-GART coherency and Burst Write Combining */
+#define I460_GXBCTL_OOG (1UL << 0)
+#define I460_GXBCTL_BWC (1UL << 2)
+
+static int intel_i460_configure(void)
+{
+ union {
+ u32 small[2];
+ u64 large;
+ } temp;
+ u8 scratch;
+ int i;
+
+ aper_size_info_8 *current_size;
+
+ temp.large = 0;
+
+ current_size = A_SIZE_8(agp_bridge.current_size);
+ intel_i460_write_agpsiz(current_size->size_value);
+
+ /*
+ * Do the necessary rigmarole to read all eight bytes of APBASE.
+ * This has to be done since the AGP aperture can be above 4GB on
+ * 460 based systems.
+ */
+ pci_read_config_dword(agp_bridge.dev, intel_i460_dynamic_apbase,
+ &(temp.small[0]));
+ pci_read_config_dword(agp_bridge.dev, intel_i460_dynamic_apbase + 4,
+ &(temp.small[1]));
+
+ /* Clear BAR control bits */
+ agp_bridge.gart_bus_addr = temp.large & ~((1UL << 3) - 1);
+
+ pci_read_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL, &scratch);
+ pci_write_config_byte(agp_bridge.dev, INTEL_I460_GXBCTL,
+ (scratch & 0x02) | I460_GXBCTL_OOG | I460_GXBCTL_BWC);
+
+ /*
+ * Initialize partial allocation trackers if a GART page is bigger than
+ * a kernel page.
+ */
+ if(I460_CPAGES_PER_KPAGE >= 1) {
+ intel_i460_cpk = 1;
+ } else {
+ intel_i460_cpk = 0;
+
+ i460_pg_detail = (void *) vmalloc(sizeof(*i460_pg_detail) *
+ current_size->num_entries);
+ i460_pg_count = (void *) vmalloc(sizeof(*i460_pg_count) *
+ current_size->num_entries);
+
+ for (i = 0; i < current_size->num_entries; i++) {
+ i460_pg_count[i] = 0;
+ i460_pg_detail[i] = NULL;
+ }
+ }
+
+ return 0;
+}
+
+static int intel_i460_create_gatt_table(void) {
+
+ char *table;
+ int i;
+ int page_order;
+ int num_entries;
+ void *temp;
+ unsigned int read_back;
+
+ /*
+ * Load up the fixed address of the GART SRAMS which hold our
+ * GATT table.
+ */
+ table = (char *) __va(INTEL_I460_ATTBASE);
+
+ temp = agp_bridge.current_size;
+ page_order = A_SIZE_8(temp)->page_order;
+ num_entries = A_SIZE_8(temp)->num_entries;
+
+ agp_bridge.gatt_table_real = (u32 *) table;
+ agp_bridge.gatt_table = ioremap_nocache(virt_to_phys(table),
+ (PAGE_SIZE * (1 << page_order)));
+ agp_bridge.gatt_bus_addr = virt_to_phys(agp_bridge.gatt_table_real);
+
+ for (i = 0; i < num_entries; i++) {
+ agp_bridge.gatt_table[i] = 0;
+ }
+
+ /*
+ * The 460 spec says we have to read the last location written to
+ * make sure that all writes have taken effect
+ */
+ read_back = agp_bridge.gatt_table[i - 1];
+
+ return 0;
+}
+
+static int intel_i460_free_gatt_table(void)
+{
+ int num_entries;
+ int i;
+ void *temp;
+ unsigned int read_back;
+
+ temp = agp_bridge.current_size;
+
+ num_entries = A_SIZE_8(temp)->num_entries;
+
+ for (i = 0; i < num_entries; i++) {
+ agp_bridge.gatt_table[i] = 0;
+ }
+
+ /*
+ * The 460 spec says we have to read the last location written to
+ * make sure that all writes have taken effect
+ */
+ read_back = agp_bridge.gatt_table[i - 1];
+
+ iounmap(agp_bridge.gatt_table);
+
+ return 0;
+}
+
+/* These functions are called when PAGE_SIZE exceeds the GART page size */
+
+static int intel_i460_insert_memory_cpk(agp_memory * mem,
+ off_t pg_start, int type)
+{
+ int i, j, k, num_entries;
+ void *temp;
+ unsigned int hold;
+ unsigned int read_back;
+
+ /*
+ * The rest of the kernel will compute page offsets in terms of
+ * PAGE_SIZE.
+ */
+ pg_start = I460_CPAGES_PER_KPAGE * pg_start;
+
+ temp = agp_bridge.current_size;
+ num_entries = A_SIZE_8(temp)->num_entries;
+
+ if((pg_start + I460_CPAGES_PER_KPAGE * mem->page_count) > num_entries) {
+ printk("[agpgart] Looks like we're out of AGP memory\n");
+ return -EINVAL;
+ }
+
+ j = pg_start;
+ while (j < (pg_start + I460_CPAGES_PER_KPAGE * mem->page_count)) {
+ if (!PGE_EMPTY(agp_bridge.gatt_table[j])) {
+ return -EBUSY;
+ }
+ j++;
+ }
+
+ if (mem->is_flushed = FALSE) {
+ CACHE_FLUSH();
+ mem->is_flushed = TRUE;
+ }
+
+ for (i = 0, j = pg_start; i < mem->page_count; i++) {
+
+ hold = (unsigned int) (mem->memory[i]);
+
+ for (k = 0; k < I460_CPAGES_PER_KPAGE; k++, j++, hold++)
+ agp_bridge.gatt_table[j] = hold;
+ }
+
+ /*
+ * The 460 spec says we have to read the last location written to
+ * make sure that all writes have taken effect
+ */
+ read_back = agp_bridge.gatt_table[j - 1];
+
+ return 0;
+}
+
+static int intel_i460_remove_memory_cpk(agp_memory * mem, off_t pg_start,
+ int type)
+{
+ int i;
+ unsigned int read_back;
+
+ pg_start = I460_CPAGES_PER_KPAGE * pg_start;
+
+ for (i = pg_start; i < (pg_start + I460_CPAGES_PER_KPAGE *
+ mem->page_count); i++)
+ agp_bridge.gatt_table[i] = 0;
+
+ /*
+ * The 460 spec says we have to read the last location written to
+ * make sure that all writes have taken effect
+ */
+ read_back = agp_bridge.gatt_table[i - 1];
+
+ return 0;
+}
+
+/*
+ * These functions are called when the GART page size exceeds PAGE_SIZE.
+ *
+ * This situation is interesting since AGP memory allocations that are
+ * smaller than a single GART page are possible. The structures i460_pg_count
+ * and i460_pg_detail track partial allocation of the large GART pages to
+ * work around this issue.
+ *
+ * i460_pg_count[pg_num] tracks the number of kernel pages in use within
+ * GART page pg_num. i460_pg_detail[pg_num] is an array containing a
+ * psuedo-GART entry for each of the aforementioned kernel pages. The whole
+ * of i460_pg_detail is equivalent to a giant GATT with page size equal to
+ * that of the kernel.
+ */
+
+static void *intel_i460_alloc_large_page(int pg_num)
+{
+ int i;
+ void *bp, *bp_end;
+ struct page *page;
+
+ i460_pg_detail[pg_num] = (void *) vmalloc(sizeof(u32) *
+ I460_KPAGES_PER_CPAGE);
+ if(i460_pg_detail[pg_num] = NULL) {
+ printk("[agpgart] Out of memory, we're in trouble...\n");
+ return NULL;
+ }
+
+ for(i = 0; i < I460_KPAGES_PER_CPAGE; i++)
+ i460_pg_detail[pg_num][i] = 0;
+
+ bp = (void *) __get_free_pages(GFP_KERNEL,
+ intel_i460_pageshift - PAGE_SHIFT);
+ if(bp = NULL) {
+ printk("[agpgart] Couldn't alloc 4M GART page...\n");
+ return NULL;
+ }
+
+ bp_end = bp + ((PAGE_SIZE *
+ (1 << (intel_i460_pageshift - PAGE_SHIFT))) - 1);
+
+ for (page = virt_to_page(bp); page <= virt_to_page(bp_end); page++)
+ {
+ atomic_inc(&page->count);
+ set_bit(PG_locked, &page->flags);
+ atomic_inc(&agp_bridge.current_memory_agp);
+ }
+
+ return bp;
+}
+
+static void intel_i460_free_large_page(int pg_num, unsigned long addr)
+{
+ struct page *page;
+ void *bp, *bp_end;
+
+ bp = (void *) __va(addr);
+ bp_end = bp + (PAGE_SIZE *
+ (1 << (intel_i460_pageshift - PAGE_SHIFT)));
+
+ vfree(i460_pg_detail[pg_num]);
+ i460_pg_detail[pg_num] = NULL;
+
+ for (page = virt_to_page(bp); page < virt_to_page(bp_end); page++)
+ {
+ atomic_dec(&page->count);
+ clear_bit(PG_locked, &page->flags);
+ wake_up(&page->wait);
+ atomic_dec(&agp_bridge.current_memory_agp);
+ }
+
+ free_pages((unsigned long) bp, intel_i460_pageshift - PAGE_SHIFT);
+}
+
+static int intel_i460_insert_memory_kpc(agp_memory * mem,
+ off_t pg_start, int type)
+{
+ int i, pg, start_pg, end_pg, start_offset, end_offset, idx;
+ int num_entries;
+ void *temp;
+ unsigned int read_back;
+
+ temp = agp_bridge.current_size;
+ num_entries = A_SIZE_8(temp)->num_entries;
+
+ /* Figure out what pg_start means in terms of our large GART pages */
+ start_pg = pg_start / I460_KPAGES_PER_CPAGE;
+ start_offset = pg_start % I460_KPAGES_PER_CPAGE;
+ end_pg = (pg_start + mem->page_count - 1) /
+ I460_KPAGES_PER_CPAGE;
+ end_offset = (pg_start + mem->page_count - 1) %
+ I460_KPAGES_PER_CPAGE;
+
+ if(end_pg > num_entries)
+ {
+ printk("[agpgart] Looks like we're out of AGP memory\n");
+ return -EINVAL;
+ }
+
+ /* Check if the requested region of the aperture is free */
+ for(pg = start_pg; pg <= end_pg; pg++)
+ {
+ /* Allocate new GART pages if necessary */
+ if(i460_pg_detail[pg] = NULL) {
+ temp = intel_i460_alloc_large_page(pg);
+ if(temp = NULL)
+ return -ENOMEM;
+ agp_bridge.gatt_table[pg] = agp_bridge.mask_memory(
+ (unsigned long) temp, 0);
+ read_back = agp_bridge.gatt_table[pg];
+ }
+
+ for(idx = ((pg = start_pg) ? start_offset : 0);
+ idx < ((pg = end_pg) ? (end_offset + 1)
+ : I460_KPAGES_PER_CPAGE);
+ idx++)
+ {
+ if(i460_pg_detail[pg][idx] != 0)
+ return -EBUSY;
+ }
+ }
+
+ if (mem->is_flushed = FALSE) {
+ CACHE_FLUSH();
+ mem->is_flushed = TRUE;
+ }
+
+ for(pg = start_pg, i = 0; pg <= end_pg; pg++)
+ {
+ for(idx = ((pg = start_pg) ? start_offset : 0);
+ idx < ((pg = end_pg) ? (end_offset + 1)
+ : I460_KPAGES_PER_CPAGE);
+ idx++, i++)
+ {
+ i460_pg_detail[pg][idx] = agp_bridge.gatt_table[pg] +
+ ((idx * PAGE_SIZE) >> 12);
+ i460_pg_count[pg]++;
+
+ /* Finally we fill in mem->memory... */
+ mem->memory[i] = ((unsigned long) (0xffffff &
+ i460_pg_detail[pg][idx])) << 12;
+ }
+ }
+
+ return 0;
+}
+
+static int intel_i460_remove_memory_kpc(agp_memory * mem,
+ off_t pg_start, int type)
+{
+ int i, pg, start_pg, end_pg, start_offset, end_offset, idx;
+ int num_entries;
+ void *temp;
+ unsigned int read_back;
+ unsigned long addr;
+
+ temp = agp_bridge.current_size;
+ num_entries = A_SIZE_8(temp)->num_entries;
+
+ /* Figure out what pg_start means in terms of our large GART pages */
+ start_pg = pg_start / I460_KPAGES_PER_CPAGE;
+ start_offset = pg_start % I460_KPAGES_PER_CPAGE;
+ end_pg = (pg_start + mem->page_count - 1) /
+ I460_KPAGES_PER_CPAGE;
+ end_offset = (pg_start + mem->page_count - 1) %
+ I460_KPAGES_PER_CPAGE;
+
+ for(i = 0, pg = start_pg; pg <= end_pg; pg++)
+ {
+ for(idx = ((pg = start_pg) ? start_offset : 0);
+ idx < ((pg = end_pg) ? (end_offset + 1)
+ : I460_KPAGES_PER_CPAGE);
+ idx++, i++)
+ {
+ mem->memory[i] = 0;
+ i460_pg_detail[pg][idx] = 0;
+ i460_pg_count[pg]--;
+ }
+
+ /* Free GART pages if they are unused */
+ if(i460_pg_count[pg] = 0) {
+ addr = (0xffffffUL & (unsigned long)
+ (agp_bridge.gatt_table[pg])) << 12;
+
+ agp_bridge.gatt_table[pg] = 0;
+ read_back = agp_bridge.gatt_table[pg];
+
+ intel_i460_free_large_page(pg, addr);
+ }
+ }
+
+ return 0;
+}
+
+/* Dummy routines to call the approriate {cpk,kpc} function */
+
+static int intel_i460_insert_memory(agp_memory * mem,
+ off_t pg_start, int type)
+{
+ if(intel_i460_cpk)
+ return intel_i460_insert_memory_cpk(mem, pg_start, type);
+ else
+ return intel_i460_insert_memory_kpc(mem, pg_start, type);
+}
+
+static int intel_i460_remove_memory(agp_memory * mem,
+ off_t pg_start, int type)
+{
+ if(intel_i460_cpk)
+ return intel_i460_remove_memory_cpk(mem, pg_start, type);
+ else
+ return intel_i460_remove_memory_kpc(mem, pg_start, type);
+}
+
+/*
+ * If the kernel page size is smaller that the chipset page size, we don't
+ * want to allocate memory until we know where it is to be bound in the
+ * aperture (a multi-kernel-page alloc might fit inside of an already
+ * allocated GART page). Consequently, don't allocate or free anything
+ * if i460_cpk (meaning chipset pages per kernel page) isn't set.
+ *
+ * Let's just hope nobody counts on the allocated AGP memory being there
+ * before bind time (I don't think current drivers do)...
+ */
+static unsigned long intel_i460_alloc_page(void)
+{
+ if(intel_i460_cpk)
+ return agp_generic_alloc_page();
+
+ /* Returning NULL would cause problems */
+ return ((unsigned long) ~0UL);
+}
+
+static void intel_i460_destroy_page(unsigned long page)
+{
+ if(intel_i460_cpk)
+ agp_generic_destroy_page(page);
+}
+
+static gatt_mask intel_i460_masks[] +{
+ {
+ INTEL_I460_GATT_VALID,
+ 0
+ }
+};
+
+static unsigned long intel_i460_mask_memory(unsigned long addr, int type)
+{
+ /* Make sure the returned address is a valid GATT entry */
+ return (agp_bridge.masks[0].mask | (((addr &
+ ~((1 << intel_i460_pageshift) - 1)) & 0xffffff000) >> 12));
+}
+
+static unsigned long intel_i460_unmask_memory(unsigned long addr)
+{
+ /* Turn a GATT entry into a physical address */
+ return ((addr & 0xffffff) << 12);
+}
+
+static aper_size_info_8 intel_i460_sizes[3] +{
+ /*
+ * The 32GB aperture is only available with a 4M GART page size.
+ * Due to the dynamic GART page size, we can't figure out page_order
+ * or num_entries until runtime.
+ */
+ {32768, 0, 0, 4},
+ {1024, 0, 0, 2},
+ {256, 0, 0, 1}
+};
+
+static int __init intel_i460_setup (struct pci_dev *pdev)
+{
+
+ agp_bridge.masks = intel_i460_masks;
+ agp_bridge.num_of_masks = 1;
+ agp_bridge.aperture_sizes = (void *) intel_i460_sizes;
+ agp_bridge.size_type = U8_APER_SIZE;
+ agp_bridge.num_aperture_sizes = 3;
+ agp_bridge.dev_private_data = NULL;
+ agp_bridge.needs_scratch_page = FALSE;
+ agp_bridge.configure = intel_i460_configure;
+ agp_bridge.fetch_size = intel_i460_fetch_size;
+ agp_bridge.cleanup = intel_i460_cleanup;
+ agp_bridge.tlb_flush = intel_i460_tlb_flush;
+ agp_bridge.mask_memory = intel_i460_mask_memory;
+ agp_bridge.unmask_memory = intel_i460_unmask_memory;
+ agp_bridge.agp_enable = agp_generic_agp_enable;
+ agp_bridge.cache_flush = global_cache_flush;
+ agp_bridge.create_gatt_table = intel_i460_create_gatt_table;
+ agp_bridge.free_gatt_table = intel_i460_free_gatt_table;
+ agp_bridge.insert_memory = intel_i460_insert_memory;
+ agp_bridge.remove_memory = intel_i460_remove_memory;
+ agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
+ agp_bridge.free_by_type = agp_generic_free_by_type;
+ agp_bridge.agp_alloc_page = intel_i460_alloc_page;
+ agp_bridge.agp_destroy_page = intel_i460_destroy_page;
+#if 0
+ agp_bridge.suspend = ??;
+ agp_bridge.resume = ??;
+#endif
+ agp_bridge.cant_use_aperture = 1;
+
+ return 0;
+
+ (void) pdev; /* unused */
+}
+
+#endif /* CONFIG_AGP_I460 */
+
#ifdef CONFIG_AGP_INTEL

static int intel_fetch_size(void)
@@ -1415,7 +2042,6 @@
agp_bridge.tlb_flush = intel_tlbflush;
agp_bridge.mask_memory = intel_mask_memory;
agp_bridge.unmask_memory = agp_generic_unmask_memory;
- agp_bridge.unmask_memory = agp_generic_unmask_memory;
agp_bridge.agp_enable = agp_generic_agp_enable;
agp_bridge.cache_flush = global_cache_flush;
agp_bridge.create_gatt_table = agp_generic_create_gatt_table;
@@ -1449,6 +2075,7 @@
agp_bridge.cleanup = intel_cleanup;
agp_bridge.tlb_flush = intel_tlbflush;
agp_bridge.mask_memory = intel_mask_memory;
+ agp_bridge.unmask_memory = agp_generic_unmask_memory;
agp_bridge.agp_enable = agp_generic_agp_enable;
agp_bridge.cache_flush = global_cache_flush;
agp_bridge.create_gatt_table = agp_generic_create_gatt_table;
diff -urN linux-davidm/drivers/char/drm/ati_pcigart.h linux-2.4.10-lia/drivers/char/drm/ati_pcigart.h
--- linux-davidm/drivers/char/drm/ati_pcigart.h Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/char/drm/ati_pcigart.h Mon Sep 24 15:57:21 2001
@@ -106,6 +106,7 @@
goto done;
}

+#if defined(__alpha__) && (LINUX_VERSION_CODE >= 0x020400)
if ( !dev->pdev ) {
DRM_ERROR( "PCI device unknown!\n" );
goto done;
@@ -120,6 +121,9 @@
address = 0;
goto done;
}
+#else
+ bus_address = virt_to_bus( (void *)address );
+#endif

pci_gart = (u32 *)address;

@@ -129,6 +133,7 @@
memset( pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32) );

for ( i = 0 ; i < pages ; i++ ) {
+#if defined(__alpha__) && (LINUX_VERSION_CODE >= 0x020400)
/* we need to support large memory configurations */
entry->busaddr[i] = pci_map_single(dev->pdev,
page_address( entry->pagelist[i] ),
@@ -142,7 +147,9 @@
goto done;
}
page_base = (u32) entry->busaddr[i];
-
+#else
+ page_base = page_to_bus( entry->pagelist[i] );
+#endif
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
*pci_gart++ = cpu_to_le32( page_base );
page_base += ATI_PCIGART_PAGE_SIZE;
@@ -167,6 +174,7 @@
unsigned long addr,
dma_addr_t bus_addr)
{
+#if defined(__alpha__) && (LINUX_VERSION_CODE >= 0x020400)
drm_sg_mem_t *entry = dev->sg;
unsigned long pages;
int i;
@@ -191,6 +199,8 @@
PAGE_SIZE, PCI_DMA_TODEVICE);
}
}
+
+#endif

if ( addr ) {
DRM(ati_free_pcigart_table)( addr );
diff -urN linux-davidm/drivers/char/drm/drmP.h linux-2.4.10-lia/drivers/char/drm/drmP.h
--- linux-davidm/drivers/char/drm/drmP.h Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/char/drm/drmP.h Mon Sep 24 16:13:22 2001
@@ -87,17 +87,6 @@
#define pci_unmap_single(hwdev, dma_addr, size, direction)
#endif

-/* page_to_bus for earlier kernels, not optimal in all cases */
-#ifndef page_to_bus
-#define page_to_bus(page) ((unsigned int)(virt_to_bus(page_address(page))))
-#endif
-
-/* We just use virt_to_bus for pci_map_single on older kernels */
-#if LINUX_VERSION_CODE < 0x020400
-#define pci_map_single(hwdev, ptr, size, direction) virt_to_bus(ptr)
-#define pci_unmap_single(hwdev, dma_addr, size, direction)
-#endif
-
/* DRM template customization defaults
*/
#ifndef __HAVE_AGP
@@ -377,14 +366,13 @@
if (len > DRM_PROC_LIMIT) { ret; *eof = 1; return len - offset; }

/* Mapping helper macros */
-#define DRM_IOREMAP(map, dev) \
+#define DRM_IOREMAP(map) \
(map)->handle = DRM(ioremap)( (map)->offset, (map)->size, (dev) )

-#define DRM_IOREMAPFREE(map, dev) \
+#define DRM_IOREMAPFREE(map) \
do { \
if ( (map)->handle && (map)->size ) \
- DRM(ioremapfree)( (map)->handle, \
- (map)->size, (dev) ); \
+ DRM(ioremapfree)( (map)->handle, (map)->size, (dev) ); \
} while (0)

#define DRM_FIND_MAP(_map, _o) \
@@ -838,10 +826,8 @@
extern unsigned long DRM(alloc_pages)(int order, int area);
extern void DRM(free_pages)(unsigned long address, int order,
int area);
-extern void *DRM(ioremap)(unsigned long offset,
- unsigned long size, drm_device_t *dev);
-extern void DRM(ioremapfree)(void *pt,
- unsigned long size, drm_device_t *dev);
+extern void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev);
+extern void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev);

#if __REALLY_HAVE_AGP
extern agp_memory *DRM(alloc_agp)(int pages, u32 type);
diff -urN linux-davidm/drivers/char/drm/drm_memory.h linux-2.4.10-lia/drivers/char/drm/drm_memory.h
--- linux-davidm/drivers/char/drm/drm_memory.h Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/char/drm/drm_memory.h Wed Aug 22 11:05:01 2001
@@ -309,6 +309,11 @@
void *DRM(ioremap)(unsigned long offset, unsigned long size, drm_device_t *dev)
{
void *pt;
+#if __REALLY_HAVE_AGP
+ drm_map_t *map = NULL;
+ drm_map_list_t *r_list;
+ struct list_head *list;
+#endif

if (!size) {
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
@@ -316,52 +321,51 @@
return NULL;
}

- if(dev->agp->cant_use_aperture = 0) {
+#if __REALLY_HAVE_AGP
+ if(dev->agp->cant_use_aperture = 0)
goto standard_ioremap;
- } else {
- drm_map_t *map = NULL;
- drm_map_list_t *r_list;
- struct list_head *list, *head;
-
- list_for_each(list, &dev->maplist->head) {
- r_list = (drm_map_list_t *)list;
- map = r_list->map;
- if (!map) continue;
- if (map->offset <= offset &&
- (map->offset + map->size) >= (offset + size))
+
+ list_for_each(list, &dev->maplist->head) {
+ r_list = (drm_map_list_t *)list;
+ map = r_list->map;
+ if (!map) continue;
+ if (map->offset <= offset &&
+ (map->offset + map->size) >= (offset + size))
+ break;
+ }
+
+ if(map && map->type = _DRM_AGP) {
+ struct drm_agp_mem *agpmem;
+
+ for(agpmem = dev->agp->memory; agpmem;
+ agpmem = agpmem->next) {
+ if(agpmem->bound <= offset &&
+ (agpmem->bound + (agpmem->pages
+ << PAGE_SHIFT)) >= (offset + size))
break;
}
-
- if(map && map->type = _DRM_AGP) {
- struct drm_agp_mem *agpmem;
-
- for(agpmem = dev->agp->memory; agpmem;
- agpmem = agpmem->next) {
- if(agpmem->bound <= offset &&
- (agpmem->bound + (agpmem->pages
- << PAGE_SHIFT)) >= (offset + size))
- break;
- }
-
- if(agpmem = NULL)
- goto standard_ioremap;
-
- pt = agpmem->memory->vmptr + (offset - agpmem->bound);
- goto ioremap_success;
- } else {
- goto standard_ioremap;
- }
+
+ if(agpmem = NULL)
+ goto ioremap_failure;
+
+ pt = agpmem->memory->vmptr + (offset - agpmem->bound);
+ goto ioremap_success;
}

standard_ioremap:
+#endif
if (!(pt = ioremap(offset, size))) {
+#if __REALLY_HAVE_AGP
+ioremap_failure:
+#endif
spin_lock(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
spin_unlock(&DRM(mem_lock));
return NULL;
}
-
+#if __REALLY_HAVE_AGP
ioremap_success:
+#endif
spin_lock(&DRM(mem_lock));
++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
@@ -377,7 +381,11 @@
if (!pt)
DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
"Attempt to free NULL pointer\n");
+#if __REALLY_HAVE_AGP
else if(dev->agp->cant_use_aperture = 0)
+#else
+ else
+#endif
iounmap(pt);

spin_lock(&DRM(mem_lock));
diff -urN linux-davidm/drivers/char/drm/drm_scatter.h linux-2.4.10-lia/drivers/char/drm/drm_scatter.h
--- linux-davidm/drivers/char/drm/drm_scatter.h Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/char/drm/drm_scatter.h Mon Sep 24 15:25:55 2001
@@ -47,9 +47,11 @@

vfree( entry->virtual );

+#if defined(__alpha__) && (LINUX_VERSION_CODE >= 0x020400)
DRM(free)( entry->busaddr,
entry->pages * sizeof(*entry->busaddr),
DRM_MEM_PAGES );
+#endif
DRM(free)( entry->pagelist,
entry->pages * sizeof(*entry->pagelist),
DRM_MEM_PAGES );
@@ -97,6 +99,7 @@
return -ENOMEM;
}

+#if defined(__alpha__) && (LINUX_VERSION_CODE >= 0x020400)
entry->busaddr = DRM(alloc)( pages * sizeof(*entry->busaddr),
DRM_MEM_PAGES );
if ( !entry->busaddr ) {
@@ -109,12 +112,15 @@
return -ENOMEM;
}
memset( (void *)entry->busaddr, 0, pages * sizeof(*entry->busaddr) );
+#endif

entry->virtual = vmalloc_32( pages << PAGE_SHIFT );
if ( !entry->virtual ) {
+#if defined(__alpha__) && (LINUX_VERSION_CODE >= 0x020400)
DRM(free)( entry->busaddr,
entry->pages * sizeof(*entry->busaddr),
DRM_MEM_PAGES );
+#endif
DRM(free)( entry->pagelist,
entry->pages * sizeof(*entry->pagelist),
DRM_MEM_PAGES );
diff -urN linux-davidm/drivers/char/drm/drm_vm.h linux-2.4.10-lia/drivers/char/drm/drm_vm.h
--- linux-davidm/drivers/char/drm/drm_vm.h Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/char/drm/drm_vm.h Mon Sep 24 16:16:20 2001
@@ -89,7 +89,7 @@

if (map && map->type = _DRM_AGP) {
unsigned long offset = address - vma->vm_start;
- unsigned long baddr = VM_OFFSET(vma) + offset;
+ unsigned long baddr = VM_OFFSET(vma) + offset, paddr;
struct drm_agp_mem *agpmem;
struct page *page;

@@ -115,8 +115,19 @@
* Get the page, inc the use count, and return it
*/
offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
- agpmem->memory->memory[offset] &= dev->agp->page_mask;
- page = virt_to_page(__va(agpmem->memory->memory[offset]));
+
+ /*
+ * This is bad. What we really want to do here is unmask
+ * the GART table entry held in the agp_memory structure.
+ * There isn't a convenient way to call agp_bridge.unmask_
+ * memory from here, so hard code it for now.
+ */
+#if defined(__ia64__)
+ paddr = (agpmem->memory->memory[offset] & 0xffffff) << 12;
+#else
+ paddr = agpmem->memory->memory[offset] & dev->agp->page_mask;
+#endif
+ page = virt_to_page(__va(paddr));
get_page(page);

DRM_DEBUG("baddr = 0x%lx page = 0x%p, offset = 0x%lx\n",
@@ -503,15 +514,21 @@

switch (map->type) {
case _DRM_AGP:
-#if defined(__alpha__)
- /*
- * On Alpha we can't talk to bus dma address from the
- * CPU, so for memory of type DRM_AGP, we'll deal with
- * sorting out the real physical pages and mappings
- * in nopage()
- */
- vma->vm_ops = &DRM(vm_ops);
- break;
+#if __REALLY_HAVE_AGP
+ if(dev->agp->cant_use_aperture = 1) {
+ /*
+ * On some systems we can't talk to bus dma address from
+ * the CPU, so for memory of type DRM_AGP, we'll deal
+ * with sorting out the real physical pages and mappings
+ * in nopage()
+ */
+ vma->vm_ops = &DRM(vm_ops);
+#if defined(__ia64__)
+ if (map->type != _DRM_AGP)
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+#endif
+ goto mapswitch_out;
+ }
#endif
/* fall through to _DRM_FRAME_BUFFER... */
case _DRM_FRAME_BUFFER:
@@ -565,6 +582,9 @@
default:
return -EINVAL; /* This should never happen. */
}
+#if __REALLY_HAVE_AGP
+mapswitch_out:
+#endif
vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */

#if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
diff -urN linux-davidm/drivers/char/drm/r128_cce.c linux-2.4.10-lia/drivers/char/drm/r128_cce.c
--- linux-davidm/drivers/char/drm/r128_cce.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/char/drm/r128_cce.c Mon Sep 24 15:25:55 2001
@@ -384,11 +384,20 @@
tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
page_ofs = tmp_ofs >> PAGE_SHIFT;

+#if defined(__alpha__) && (LINUX_VERSION_CODE >= 0x020400)
R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
entry->busaddr[page_ofs]);
DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n",
entry->busaddr[page_ofs],
entry->handle + tmp_ofs );
+#else
+ R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR,
+ page_to_bus(entry->pagelist[page_ofs]));
+
+ DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n",
+ page_to_bus(entry->pagelist[page_ofs]),
+ entry->handle + tmp_ofs );
+#endif
}

/* Set watermark control */
@@ -658,9 +667,9 @@
drm_r128_private_t *dev_priv = dev->dev_private;

if ( !dev_priv->is_pci ) {
- DRM_IOREMAPFREE( dev_priv->cce_ring );
- DRM_IOREMAPFREE( dev_priv->ring_rptr );
- DRM_IOREMAPFREE( dev_priv->buffers );
+ DRM_IOREMAPFREE( dev_priv->cce_ring, dev );
+ DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
+ DRM_IOREMAPFREE( dev_priv->buffers, dev );
} else {
if (!DRM(ati_pcigart_cleanup)( dev,
dev_priv->phys_pci_gart,
@@ -668,6 +677,21 @@
DRM_ERROR( "failed to cleanup PCI GART!\n" );
}

+#if defined(CONFIG_AGP_I460) && defined(__ia64__)
+ /*
+ * Free the page we grabbed for RPTR_ADDR
+ */
+ if( dev->agp->agp_info.chipset = INTEL_460GX ) {
+ unsigned long alt_rh_off + (unsigned long) dev_priv->ring.head;
+
+ atomic_dec(&virt_to_page(alt_rh_off)->count);
+ clear_bit(PG_locked, &virt_to_page(alt_rh_off)->flags);
+ wake_up(&virt_to_page(alt_rh_off)->wait);
+ free_page(alt_rh_off);
+ }
+#endif
+
DRM(free)( dev->dev_private, sizeof(drm_r128_private_t),
DRM_MEM_DRIVER );
dev->dev_private = NULL;
diff -urN linux-davidm/drivers/char/drm/radeon_cp.c linux-2.4.10-lia/drivers/char/drm/radeon_cp.c
--- linux-davidm/drivers/char/drm/radeon_cp.c Mon Sep 24 22:31:43 2001
+++ linux-2.4.10-lia/drivers/char/drm/radeon_cp.c Mon Sep 24 15:25:55 2001
@@ -640,11 +640,19 @@
tmp_ofs = dev_priv->ring_rptr->offset - dev->sg->handle;
page_ofs = tmp_ofs >> PAGE_SHIFT;

+#if defined(__alpha__) && (LINUX_VERSION_CODE >= 0x020400)
RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
entry->busaddr[page_ofs]);
DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n",
entry->busaddr[page_ofs],
entry->handle + tmp_ofs );
+#else
+ RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
+ entry->busaddr[page_ofs]);
+ DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n",
+ entry->busaddr[page_ofs],
+ entry->handle + tmp_ofs );
+#endif
}

/* Set ring buffer size */
@@ -1002,9 +1010,9 @@
drm_radeon_private_t *dev_priv = dev->dev_private;

if ( !dev_priv->is_pci ) {
- DRM_IOREMAPFREE( dev_priv->cp_ring );
- DRM_IOREMAPFREE( dev_priv->ring_rptr );
- DRM_IOREMAPFREE( dev_priv->buffers );
+ DRM_IOREMAPFREE( dev_priv->cp_ring, dev );
+ DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
+ DRM_IOREMAPFREE( dev_priv->buffers, dev );
} else {
if (!DRM(ati_pcigart_cleanup)( dev,
dev_priv->phys_pci_gart,
@@ -1012,6 +1020,21 @@
DRM_ERROR( "failed to cleanup PCI GART!\n" );
}

+#if defined(CONFIG_AGP_I460) && defined(__ia64__)
+ /*
+ * Free the page we grabbed for RPTR_ADDR
+ */
+ if( dev->agp->agp_info.chipset = INTEL_460GX ) {
+ unsigned long alt_rh_off + (unsigned long) dev_priv->ring.head;
+
+ atomic_dec(&virt_to_page(alt_rh_off)->count);
+ clear_bit(PG_locked, &virt_to_page(alt_rh_off)->flags);
+ wake_up(&virt_to_page(alt_rh_off)->wait);
+ free_page(alt_rh_off);
+ }
+#endif
+
DRM(free)( dev->dev_private, sizeof(drm_radeon_private_t),
DRM_MEM_DRIVER );
dev->dev_private = NULL;
diff -urN linux-davidm/fs/exec.c linux-2.4.10-lia/fs/exec.c
--- linux-davidm/fs/exec.c Mon Sep 24 22:31:44 2001
+++ linux-2.4.10-lia/fs/exec.c Mon Sep 24 22:04:08 2001
@@ -176,7 +176,7 @@
}

/*
- * 'copy_strings()' copies argument/envelope strings from user
+ * 'copy_strings()' copies argument/environment strings from user
* memory to free pages in kernel mem. These are in a format ready
* to be put directly into the top of new user memory.
*/
diff -urN linux-davidm/fs/inode.c linux-2.4.10-lia/fs/inode.c
--- linux-davidm/fs/inode.c Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/fs/inode.c Mon Sep 24 21:29:26 2001
@@ -16,7 +16,6 @@
#include <linux/swap.h>
#include <linux/swapctl.h>
#include <linux/prefetch.h>
-#include <linux/locks.h>

/*
* New inode.c implementation.
@@ -836,7 +835,7 @@
{
struct inode * inode;

- prefetch_spin_lock(&inode_lock);
+ spin_lock_prefetch(&inode_lock);

inode = alloc_inode();
if (inode) {
diff -urN linux-davidm/fs/namei.c linux-2.4.10-lia/fs/namei.c
--- linux-davidm/fs/namei.c Mon Sep 24 15:08:16 2001
+++ linux-2.4.10-lia/fs/namei.c Mon Sep 24 22:04:25 2001
@@ -629,10 +629,14 @@
static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
{
if (path_walk(name, nd))
- return 0;
+ return 0; /* something went wrong... */

- if (!nd->dentry->d_inode) {
+ if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) {
struct nameidata nd_root;
+ /*
+ * NAME was not found in alternate root or it's a directory. Try to find
+ * it in the normal root:
+ */
nd_root.last_type = LAST_ROOT;
nd_root.flags = nd->flags;
read_lock(&current->fs->lock);
@@ -642,12 +646,14 @@
if (path_walk(name, &nd_root))
return 1;
if (nd_root.dentry->d_inode) {
+ /* file exists in normal root filesystem: */
path_release(nd);
nd->dentry = nd_root.dentry;
nd->mnt = nd_root.mnt;
nd->last = nd_root.last;
return 1;
}
+ /* file doesn't exist */
path_release(&nd_root);
}
return 1;
diff -urN linux-davidm/include/asm-ia64/ia32.h linux-2.4.10-lia/include/asm-ia64/ia32.h
--- linux-davidm/include/asm-ia64/ia32.h Tue Jul 31 10:30:09 2001
+++ linux-2.4.10-lia/include/asm-ia64/ia32.h Mon Sep 24 22:56:58 2001
@@ -33,7 +33,9 @@
typedef __kernel_fsid_t __kernel_fsid_t32;

#define IA32_PAGE_SHIFT 12 /* 4KB pages */
-#define IA32_PAGE_SIZE (1ULL << IA32_PAGE_SHIFT)
+#define IA32_PAGE_SIZE (1UL << IA32_PAGE_SHIFT)
+#define IA32_PAGE_MASK (~(IA32_PAGE_SIZE - 1))
+#define IA32_PAGE_ALIGN(addr) (((addr) + IA32_PAGE_SIZE - 1) & IA32_PAGE_MASK)
#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)

@@ -46,6 +48,9 @@
__kernel_pid_t32 l_pid;
};

+#define F_GETLK64 12
+#define F_SETLK64 13
+#define F_SETLKW64 14

/* sigcontext.h */
/*
@@ -103,13 +108,19 @@
#define _IA32_NSIG_BPW 32
#define _IA32_NSIG_WORDS (_IA32_NSIG / _IA32_NSIG_BPW)

+#define IA32_SET_SA_HANDLER(ka,handler,restorer) \
+ ((ka)->sa.sa_handler = (__sighandler_t) \
+ (((unsigned long)(restorer) << 32) \
+ | ((handler) & 0xffffffff)))
+#define IA32_SA_HANDLER(ka) ((unsigned long) (ka)->sa.sa_handler & 0xffffffff)
+#define IA32_SA_RESTORER(ka) ((unsigned long) (ka)->sa.sa_handler >> 32)
+
typedef struct {
unsigned int sig[_IA32_NSIG_WORDS];
} sigset32_t;

struct sigaction32 {
- unsigned int sa_handler; /* Really a pointer, but need to deal
- with 32 bits */
+ unsigned int sa_handler; /* Really a pointer, but need to deal with 32 bits */
unsigned int sa_flags;
unsigned int sa_restorer; /* Another 32 bit pointer */
sigset32_t sa_mask; /* A 32 bit mask */
@@ -162,6 +173,31 @@
unsigned int __unused5;
};

+struct stat64 {
+ unsigned short st_dev;
+ unsigned char __pad0[10];
+ unsigned int __st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned short st_rdev;
+ unsigned char __pad3[10];
+ unsigned int st_size_lo;
+ unsigned int st_size_hi;
+ unsigned int st_blksize;
+ unsigned int st_blocks; /* Number 512-byte blocks allocated. */
+ unsigned int __pad4; /* future possible st_blocks high bits */
+ unsigned int st_atime;
+ unsigned int __pad5;
+ unsigned int st_mtime;
+ unsigned int __pad6;
+ unsigned int st_ctime;
+ unsigned int __pad7; /* will be high 32 bits of ctime someday */
+ unsigned int st_ino_lo;
+ unsigned int st_ino_hi;
+};
+
struct statfs32 {
int f_type;
int f_bsize;
@@ -252,7 +288,7 @@
#define ELF_ARCH EM_386

#define IA32_PAGE_OFFSET 0xc0000000
-#define IA32_STACK_TOP ((IA32_PAGE_OFFSET/3) * 2)
+#define IA32_STACK_TOP IA32_PAGE_OFFSET

/*
* The system segments (GDT, TSS, LDT) have to be mapped below 4GB so the IA-32 engine can
@@ -377,7 +413,7 @@
*/

#define IA32_FSR_DEFAULT 0x55550000 /* set all tag bits */
-#define IA32_FCR_DEFAULT 0x17800000037fULL /* extended precision, all masks */
+#define IA32_FCR_DEFAULT 0x17800000037fUL /* extended precision, all masks */

#define IA32_PTRACE_GETREGS 12
#define IA32_PTRACE_SETREGS 13
@@ -421,6 +457,7 @@
extern void ia32_init_addr_space (struct pt_regs *regs);
extern int ia32_setup_arg_pages (struct linux_binprm *bprm);
extern int ia32_exception (struct pt_regs *regs, unsigned long isr);
+extern unsigned long ia32_do_mmap (struct file *, unsigned long, unsigned long, int, int, loff_t);

#endif /* !CONFIG_IA32_SUPPORT */

diff -urN linux-davidm/include/asm-ia64/iosapic.h linux-2.4.10-lia/include/asm-ia64/iosapic.h
--- linux-davidm/include/asm-ia64/iosapic.h Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/include/asm-ia64/iosapic.h Mon Sep 24 22:05:11 2001
@@ -53,9 +53,15 @@

extern void __init iosapic_init (unsigned long address, unsigned int base_irq,
int pcat_compat);
+extern int iosapic_register_irq (u32 global_vector, unsigned long polarity,
+ unsigned long edge_triggered, u32 base_irq,
+ char *iosapic_address);
extern void iosapic_register_legacy_irq (unsigned long irq, unsigned long pin,
unsigned long polarity, unsigned long trigger);
-extern int iosapic_register_platform_irq (u32 int_type, u32 global_vector, u32 iosapic_vector, u16 eid, u16 id, unsigned long polarity, unsigned long edge_triggered, u32 base_irq, char *iosapic_address);
+extern int iosapic_register_platform_irq (u32 int_type, u32 global_vector, u32 iosapic_vector,
+ u16 eid, u16 id, unsigned long polarity,
+ unsigned long edge_triggered, u32 base_irq,
+ char *iosapic_address);
extern unsigned int iosapic_version (char *addr);

extern void iosapic_pci_fixup (int);
diff -urN linux-davidm/include/asm-ia64/ipc.h linux-2.4.10-lia/include/asm-ia64/ipc.h
--- linux-davidm/include/asm-ia64/ipc.h Sun Feb 6 18:42:40 2000
+++ linux-2.4.10-lia/include/asm-ia64/ipc.h Wed Dec 31 16:00:00 1969
@@ -1,31 +0,0 @@
-#ifndef __i386_IPC_H__
-#define __i386_IPC_H__
-
-/*
- * These are used to wrap system calls on x86.
- *
- * See arch/i386/kernel/sys_i386.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
diff -urN linux-davidm/include/asm-ia64/keyboard.h linux-2.4.10-lia/include/asm-ia64/keyboard.h
--- linux-davidm/include/asm-ia64/keyboard.h Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/include/asm-ia64/keyboard.h Mon Sep 24 23:00:16 2001
@@ -23,7 +23,6 @@
char raw_mode);
extern char pckbd_unexpected_up(unsigned char keycode);
extern void pckbd_leds(unsigned char leds);
-extern int pckbd_rate(struct kbd_repeat *rep);
extern void pckbd_init_hw(void);
extern unsigned char pckbd_sysrq_xlate[128];

@@ -33,7 +32,6 @@
#define kbd_translate pckbd_translate
#define kbd_unexpected_up pckbd_unexpected_up
#define kbd_leds pckbd_leds
-#define kbd_rate pckbd_rate
#define kbd_init_hw pckbd_init_hw
#define kbd_sysrq_xlate pckbd_sysrq_xlate

diff -urN linux-davidm/include/asm-ia64/machvec.h linux-2.4.10-lia/include/asm-ia64/machvec.h
--- linux-davidm/include/asm-ia64/machvec.h Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/include/asm-ia64/machvec.h Mon Sep 24 22:20:43 2001
@@ -1,11 +1,11 @@
/*
* Machine vector for IA-64.
- *
+ *
* Copyright (C) 1999 Silicon Graphics, Inc.
* Copyright (C) Srinivasa Thirumalachar <sprasad@engr.sgi.com>
* Copyright (C) Vijay Chander <vijay@engr.sgi.com>
* Copyright (C) 1999-2001 Hewlett-Packard Co.
- * Copyright (C) 1999-2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*/
#ifndef _ASM_IA64_MACHVEC_H
#define _ASM_IA64_MACHVEC_H
@@ -28,6 +28,7 @@
typedef void ia64_mv_cmci_handler_t (int, void *, struct pt_regs *);
typedef void ia64_mv_log_print_t (void);
typedef void ia64_mv_send_ipi_t (int, int, int, int);
+typedef void ia64_mv_global_tlb_purge_t (unsigned long, unsigned long, unsigned long);
typedef struct irq_desc *ia64_mv_irq_desc (unsigned int);
typedef u8 ia64_mv_irq_to_vector (u8);
typedef unsigned int ia64_mv_local_vector_to_irq (u8 vector);
@@ -67,6 +68,8 @@
# include <asm/machvec_dig.h>
# elif defined (CONFIG_IA64_SGI_SN1)
# include <asm/machvec_sn1.h>
+# elif defined (CONFIG_IA64_SGI_SN2)
+# include <asm/machvec_sn2.h>
# elif defined (CONFIG_IA64_GENERIC)

# ifdef MACHVEC_PLATFORM_HEADER
@@ -82,6 +85,7 @@
# define platform_log_print ia64_mv.log_print
# define platform_pci_fixup ia64_mv.pci_fixup
# define platform_send_ipi ia64_mv.send_ipi
+# define platform_global_tlb_purge ia64_mv.global_tlb_purge
# define platform_pci_dma_init ia64_mv.dma_init
# define platform_pci_alloc_consistent ia64_mv.alloc_consistent
# define platform_pci_free_consistent ia64_mv.free_consistent
@@ -147,6 +151,7 @@
platform_cmci_handler, \
platform_log_print, \
platform_send_ipi, \
+ platform_global_tlb_purge, \
platform_pci_dma_init, \
platform_pci_alloc_consistent, \
platform_pci_free_consistent, \
@@ -216,6 +221,9 @@
#endif
#ifndef platform_send_ipi
# define platform_send_ipi ia64_send_ipi /* default to architected version */
+#endif
+#ifndef platform_global_tlb_purge
+# define platform_global_tlb_purge ia64_global_tlb_purge /* default to architected version */
#endif
#ifndef platform_pci_dma_init
# define platform_pci_dma_init swiotlb_init
diff -urN linux-davidm/include/asm-ia64/machvec_sn1.h linux-2.4.10-lia/include/asm-ia64/machvec_sn1.h
--- linux-davidm/include/asm-ia64/machvec_sn1.h Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/include/asm-ia64/machvec_sn1.h Mon Sep 24 22:06:06 2001
@@ -5,6 +5,7 @@
extern ia64_mv_irq_init_t sn1_irq_init;
extern ia64_mv_map_nr_t sn1_map_nr;
extern ia64_mv_send_ipi_t sn1_send_IPI;
+extern ia64_mv_global_tlb_purge_t sn1_global_tlb_purge;
extern ia64_mv_pci_fixup_t sn1_pci_fixup;
extern ia64_mv_inb_t sn1_inb;
extern ia64_mv_inw_t sn1_inw;
@@ -34,6 +35,7 @@
#define platform_irq_init sn1_irq_init
#define platform_map_nr sn1_map_nr
#define platform_send_ipi sn1_send_IPI
+#define platform_global_tlb_purge sn1_global_tlb_purge
#define platform_pci_fixup sn1_pci_fixup
#define platform_inb sn1_inb
#define platform_inw sn1_inw
diff -urN linux-davidm/include/asm-ia64/mca.h linux-2.4.10-lia/include/asm-ia64/mca.h
--- linux-davidm/include/asm-ia64/mca.h Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/include/asm-ia64/mca.h Mon Sep 24 22:58:05 2001
@@ -61,8 +61,6 @@
IA64_MCA_RENDEZ_CHECKIN_DONE = 0x1
};

-#define IA64_MAXCPUS 64 /* Need to do something about this */
-
/* Information maintained by the MC infrastructure */
typedef struct ia64_mc_info_s {
u64 imi_mca_handler;
@@ -71,7 +69,7 @@
size_t imi_monarch_init_handler_size;
u64 imi_slave_init_handler;
size_t imi_slave_init_handler_size;
- u8 imi_rendez_checkin[IA64_MAXCPUS];
+ u8 imi_rendez_checkin[NR_CPUS];

} ia64_mc_info_t;

diff -urN linux-davidm/include/asm-ia64/mmu_context.h linux-2.4.10-lia/include/asm-ia64/mmu_context.h
--- linux-davidm/include/asm-ia64/mmu_context.h Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/include/asm-ia64/mmu_context.h Mon Sep 24 23:02:56 2001
@@ -60,7 +60,6 @@
static inline void
get_mmu_context (struct mm_struct *mm)
{
- /* check if our ASN is of an older generation and thus invalid: */
if (mm->context = 0)
get_new_mmu_context(mm);
}
diff -urN linux-davidm/include/asm-ia64/module.h linux-2.4.10-lia/include/asm-ia64/module.h
--- linux-davidm/include/asm-ia64/module.h Mon Sep 24 15:08:24 2001
+++ linux-2.4.10-lia/include/asm-ia64/module.h Mon Sep 24 22:57:00 2001
@@ -14,7 +14,6 @@
#define module_map(x) vmalloc(x)
#define module_unmap(x) ia64_module_unmap(x)
#define module_arch_init(x) ia64_module_init(x)
-#define arch_init_modules(x) do { } while (0)

/*
* This must match in size and layout the data created by
@@ -28,12 +27,23 @@
const char *gp;
};

+static inline void
+arch_init_modules (struct module *kmod)
+{
+ static struct archdata archdata;
+ register char *kernel_gp asm ("gp");
+
+ archdata.gp = kernel_gp;
+ kmod->archdata_start = (const char *) &archdata;
+ kmod->archdata_end = (const char *) (&archdata + 1);
+}
+
/*
* functions to add/remove a modules unwind info when
* it is loaded or unloaded.
*/
static inline int
-ia64_module_init(struct module *mod)
+ia64_module_init (struct module *mod)
{
struct archdata *archdata;

@@ -45,28 +55,23 @@
* Make sure the unwind pointers are sane.
*/

- if (archdata->unw_table)
- {
+ if (archdata->unw_table) {
printk(KERN_ERR "module_arch_init: archdata->unw_table must be zero.\n");
return 1;
}
- if (!mod_bound(archdata->gp, 0, mod))
- {
+ if (!mod_bound(archdata->gp, 0, mod)) {
printk(KERN_ERR "module_arch_init: archdata->gp out of bounds.\n");
return 1;
}
- if (!mod_bound(archdata->unw_start, 0, mod))
- {
+ if (!mod_bound(archdata->unw_start, 0, mod)) {
printk(KERN_ERR "module_arch_init: archdata->unw_start out of bounds.\n");
return 1;
}
- if (!mod_bound(archdata->unw_end, 0, mod))
- {
+ if (!mod_bound(archdata->unw_end, 0, mod)) {
printk(KERN_ERR "module_arch_init: archdata->unw_end out of bounds.\n");
return 1;
}
- if (!mod_bound(archdata->segment_base, 0, mod))
- {
+ if (!mod_bound(archdata->segment_base, 0, mod)) {
printk(KERN_ERR "module_arch_init: archdata->unw_table out of bounds.\n");
return 1;
}
@@ -82,7 +87,7 @@
}

static inline void
-ia64_module_unmap(void * addr)
+ia64_module_unmap (void * addr)
{
struct module *mod = (struct module *) addr;
struct archdata *archdata;
@@ -90,8 +95,7 @@
/*
* Before freeing the module memory remove the unwind table entry
*/
- if (mod_member_present(mod, archdata_start) && mod->archdata_start)
- {
+ if (mod_member_present(mod, archdata_start) && mod->archdata_start) {
archdata = (struct archdata *)(mod->archdata_start);

if (archdata->unw_table != NULL)
diff -urN linux-davidm/include/asm-ia64/msgbuf.h linux-2.4.10-lia/include/asm-ia64/msgbuf.h
--- linux-davidm/include/asm-ia64/msgbuf.h Sun Feb 6 18:42:40 2000
+++ linux-2.4.10-lia/include/asm-ia64/msgbuf.h Mon Sep 24 22:06:49 2001
@@ -1,7 +1,7 @@
#ifndef _ASM_IA64_MSGBUF_H
#define _ASM_IA64_MSGBUF_H

-/*
+/*
* The msqid64_ds structure for IA-64 architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
diff -urN linux-davidm/include/asm-ia64/namei.h linux-2.4.10-lia/include/asm-ia64/namei.h
--- linux-davidm/include/asm-ia64/namei.h Sun Apr 2 15:49:07 2000
+++ linux-2.4.10-lia/include/asm-ia64/namei.h Mon Sep 24 23:01:39 2001
@@ -2,15 +2,24 @@
#define _ASM_IA64_NAMEI_H

/*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*/

-/*
- * This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-#define __emul_prefix() NULL
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+#define EMUL_PREFIX_LINUX_IA32 "emul/ia32-linux/"
+
+static inline char *
+__emul_prefix (void)
+{
+ switch (current->personality) {
+ case PER_LINUX32:
+ return EMUL_PREFIX_LINUX_IA32;
+ default:
+ return NULL;
+ }
+}

#endif /* _ASM_IA64_NAMEI_H */
diff -urN linux-davidm/include/asm-ia64/offsets.h linux-2.4.10-lia/include/asm-ia64/offsets.h
--- linux-davidm/include/asm-ia64/offsets.h Tue Jul 31 10:30:09 2001
+++ linux-2.4.10-lia/include/asm-ia64/offsets.h Mon Sep 24 22:07:13 2001
@@ -8,23 +8,23 @@
*/
#define PT_PTRACED_BIT 0
#define PT_TRACESYS_BIT 1
-#define IA64_TASK_SIZE 3904 /* 0xf40 */
+#define IA64_TASK_SIZE 3920 /* 0xf50 */
#define IA64_PT_REGS_SIZE 400 /* 0x190 */
#define IA64_SWITCH_STACK_SIZE 560 /* 0x230 */
#define IA64_SIGINFO_SIZE 128 /* 0x80 */
#define IA64_CPU_SIZE 16384 /* 0x4000 */
-#define SIGFRAME_SIZE 2832 /* 0xb10 */
+#define SIGFRAME_SIZE 2816 /* 0xb00 */
#define UNW_FRAME_INFO_SIZE 448 /* 0x1c0 */

#define IA64_TASK_PTRACE_OFFSET 48 /* 0x30 */
#define IA64_TASK_SIGPENDING_OFFSET 16 /* 0x10 */
#define IA64_TASK_NEED_RESCHED_OFFSET 40 /* 0x28 */
#define IA64_TASK_PROCESSOR_OFFSET 100 /* 0x64 */
-#define IA64_TASK_THREAD_OFFSET 1456 /* 0x5b0 */
-#define IA64_TASK_THREAD_KSP_OFFSET 1456 /* 0x5b0 */
-#define IA64_TASK_THREAD_SIGMASK_OFFSET 1568 /* 0x620 */
-#define IA64_TASK_PFM_NOTIFY_OFFSET 2088 /* 0x828 */
-#define IA64_TASK_PID_OFFSET 196 /* 0xc4 */
+#define IA64_TASK_THREAD_OFFSET 1472 /* 0x5c0 */
+#define IA64_TASK_THREAD_KSP_OFFSET 1472 /* 0x5c0 */
+#define IA64_TASK_THREAD_SIGMASK_OFFSET 1584 /* 0x630 */
+#define IA64_TASK_PFM_MUST_BLOCK_OFFSET 2104 /* 0x838 */
+#define IA64_TASK_PID_OFFSET 220 /* 0xdc */
#define IA64_TASK_MM_OFFSET 88 /* 0x58 */
#define IA64_PT_REGS_CR_IPSR_OFFSET 0 /* 0x0 */
#define IA64_PT_REGS_CR_IIP_OFFSET 8 /* 0x8 */
@@ -126,12 +126,13 @@
#define IA64_SIGCONTEXT_FR6_OFFSET 560 /* 0x230 */
#define IA64_SIGCONTEXT_PR_OFFSET 128 /* 0x80 */
#define IA64_SIGCONTEXT_R12_OFFSET 296 /* 0x128 */
+#define IA64_SIGCONTEXT_RBS_BASE_OFFSET 2512 /* 0x9d0 */
+#define IA64_SIGCONTEXT_LOADRS_OFFSET 2520 /* 0x9d8 */
#define IA64_SIGFRAME_ARG0_OFFSET 0 /* 0x0 */
#define IA64_SIGFRAME_ARG1_OFFSET 8 /* 0x8 */
#define IA64_SIGFRAME_ARG2_OFFSET 16 /* 0x10 */
-#define IA64_SIGFRAME_RBS_BASE_OFFSET 24 /* 0x18 */
-#define IA64_SIGFRAME_HANDLER_OFFSET 32 /* 0x20 */
-#define IA64_SIGFRAME_SIGCONTEXT_OFFSET 176 /* 0xb0 */
+#define IA64_SIGFRAME_HANDLER_OFFSET 24 /* 0x18 */
+#define IA64_SIGFRAME_SIGCONTEXT_OFFSET 160 /* 0xa0 */
#define IA64_CLONE_VFORK 16384 /* 0x4000 */
#define IA64_CLONE_VM 256 /* 0x100 */
#define IA64_CPU_IRQ_COUNT_OFFSET 0 /* 0x0 */
diff -urN linux-davidm/include/asm-ia64/pal.h linux-2.4.10-lia/include/asm-ia64/pal.h
--- linux-davidm/include/asm-ia64/pal.h Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/include/asm-ia64/pal.h Mon Sep 24 22:07:25 2001
@@ -7,9 +7,9 @@
* This is based on Intel IA-64 Architecture Software Developer's Manual rev 1.0
* chapter 11 IA-64 Processor Abstraction Layer
*
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * David Mosberger-Tang <davidm@hpl.hp.com>
+ * Stephane Eranian <eranian@hpl.hp.com>
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
* Copyright (C) 1999 Srinivasa Prasad Thirumalachar <sprasad@sprasad.engr.sgi.com>
@@ -17,7 +17,7 @@
* 99/10/01 davidm Make sure we pass zero for reserved parameters.
* 00/03/07 davidm Updated pal_cache_flush() to be in sync with PAL v2.6.
* 00/03/23 cfleck Modified processor min-state save area to match updated PAL & SAL info
- * 00/05/24 eranian Updated to latest PAL spec, fix structures bugs, added
+ * 00/05/24 eranian Updated to latest PAL spec, fix structures bugs, added
* 00/05/25 eranian Support for stack calls, and static physical calls
* 00/06/18 eranian Support for stacked physical calls
*/
@@ -91,9 +91,9 @@
#define PAL_STATUS_UNIMPLEMENTED -1 /* Unimplemented procedure */
#define PAL_STATUS_EINVAL -2 /* Invalid argument */
#define PAL_STATUS_ERROR -3 /* Error */
-#define PAL_STATUS_CACHE_INIT_FAIL -4 /* Could not initialize the
+#define PAL_STATUS_CACHE_INIT_FAIL -4 /* Could not initialize the
* specified level and type of
- * cache without sideeffects
+ * cache without sideeffects
* and "restrict" was 1
*/

@@ -189,8 +189,8 @@

#define PAL_CACHE_ATTR_WT 0 /* Write through cache */
#define PAL_CACHE_ATTR_WB 1 /* Write back cache */
-#define PAL_CACHE_ATTR_WT_OR_WB 2 /* Either write thru or write
- * back depending on TLB
+#define PAL_CACHE_ATTR_WT_OR_WB 2 /* Either write thru or write
+ * back depending on TLB
* memory attributes
*/

@@ -211,13 +211,13 @@

tagprot_lsb : 6, /* Least -do- */
tagprot_msb : 6, /* Most Sig. tag address
- * bit that this
+ * bit that this
* protection covers.
*/
prot_bits : 6, /* # of protection bits */
method : 4, /* Protection method */
- t_d : 2; /* Indicates which part
- * of the cache this
+ t_d : 2; /* Indicates which part
+ * of the cache this
* protection encoding
* applies.
*/
@@ -239,7 +239,7 @@
*/
#define PAL_CACHE_PROT_PART_DATA_TAG 3 /* Data+tag protection (data is
* more significant )
- */
+ */
#define PAL_CACHE_PROT_PART_MAX 6

@@ -247,7 +247,7 @@
pal_status_t pcpi_status;
pal_cache_protection_element_t pcp_info[PAL_CACHE_PROT_PART_MAX];
} pal_cache_protection_info_t;
-
+

/* Processor cache protection method encodings */
#define PAL_CACHE_PROT_METHOD_NONE 0 /* No protection */
@@ -262,41 +262,41 @@
struct {
u64 cache_type : 8, /* 7-0 cache type */
level : 8, /* 15-8 level of the
- * cache in the
+ * cache in the
* heirarchy.
*/
way : 8, /* 23-16 way in the set
*/
part : 8, /* 31-24 part of the
- * cache
+ * cache
*/
reserved : 32; /* 63-32 is reserved*/
} pclid_info_read;
struct {
u64 cache_type : 8, /* 7-0 cache type */
level : 8, /* 15-8 level of the
- * cache in the
+ * cache in the
* heirarchy.
*/
way : 8, /* 23-16 way in the set
*/
part : 8, /* 31-24 part of the
- * cache
+ * cache
*/
- mesi : 8, /* 39-32 cache line
+ mesi : 8, /* 39-32 cache line
* state
*/
start : 8, /* 47-40 lsb of data to
* invert
*/
length : 8, /* 55-48 #bits to
- * invert
+ * invert
*/
trigger : 8; /* 63-56 Trigger error
- * by doing a load
- * after the write
- */
-
+ * by doing a load
+ * after the write
+ */
+
} pclid_info_write;
} pal_cache_line_id_u_t;

@@ -319,11 +319,11 @@
#define PAL_CACHE_LINE_ID_PART_TAG 1 /* Tag */
#define PAL_CACHE_LINE_ID_PART_DATA_PROT 2 /* Data protection */
#define PAL_CACHE_LINE_ID_PART_TAG_PROT 3 /* Tag protection */
-#define PAL_CACHE_LINE_ID_PART_DATA_TAG_PROT 4 /* Data+tag
+#define PAL_CACHE_LINE_ID_PART_DATA_TAG_PROT 4 /* Data+tag
* protection
*/
typedef struct pal_cache_line_info_s {
- pal_status_t pcli_status; /* Return status of the read cache line
+ pal_status_t pcli_status; /* Return status of the read cache line
* info call.
*/
u64 pcli_data; /* 64-bit data, tag, protection bits .. */
@@ -351,15 +351,15 @@
#define PAL_MC_INFO_REQ_ADDR 4 /* Requestor address */
#define PAL_MC_INFO_RESP_ADDR 5 /* Responder address */
#define PAL_MC_INFO_TARGET_ADDR 6 /* Target address */
-#define PAL_MC_INFO_IMPL_DEP 7 /* Implementation
- * dependent
+#define PAL_MC_INFO_IMPL_DEP 7 /* Implementation
+ * dependent
*/

typedef struct pal_process_state_info_s {
u64 reserved1 : 2,
rz : 1, /* PAL_CHECK processor
- * rendezvous
+ * rendezvous
* successful.
*/

@@ -370,13 +370,13 @@
* errors occurred
*/

- mn : 1, /* Min. state save
- * area has been
+ mn : 1, /* Min. state save
+ * area has been
* registered with PAL
*/

sy : 1, /* Storage integrity
- * synched
+ * synched
*/

@@ -389,8 +389,8 @@

hd : 1, /* Non-essential hw
* lost (no loss of
- * functionality)
- * causing the
+ * functionality)
+ * causing the
* processor to run in
* degraded mode.
*/
@@ -398,9 +398,9 @@
tl : 1, /* 1 => MC occurred
* after an instr was
* executed but before
- * the trap that
+ * the trap that
* resulted from instr
- * execution was
+ * execution was
* generated.
* (Trap Lost )
*/
@@ -410,7 +410,7 @@
*/

dy : 1, /* Processor dynamic
- * state valid
+ * state valid
*/

@@ -441,10 +441,10 @@
* are valid
*/
gr : 1, /* General registers
- * are valid
+ * are valid
* (excl. banked regs)
*/
- dsize : 16, /* size of dynamic
+ dsize : 16, /* size of dynamic
* state returned
* by the processor
*/
@@ -459,8 +459,8 @@

typedef struct pal_cache_check_info_s {
u64 reserved1 : 16,
- way : 5, /* Way in which the
- * error occurred
+ way : 5, /* Way in which the
+ * error occurred
*/
reserved2 : 1,
mc : 1, /* Machine check corrected */
@@ -469,8 +469,8 @@
*/

wv : 1, /* Way field valid */
- op : 3, /* Type of cache
- * operation that
+ op : 3, /* Type of cache
+ * operation that
* caused the machine
* check.
*/
@@ -493,7 +493,7 @@
typedef struct pal_tlb_check_info_s {

u64 tr_slot : 8, /* Slot# of TR where
- * error occurred
+ * error occurred
*/
reserved2 : 8,
dtr : 1, /* Fail in data TR */
@@ -509,7 +509,7 @@
u64 size : 5, /* Xaction size*/
ib : 1, /* Internal bus error */
eb : 1, /* External bus error */
- cc : 1, /* Error occurred
+ cc : 1, /* Error occurred
* during cache-cache
* transfer.
*/
@@ -518,7 +518,7 @@
tv : 1, /* Targ addr valid */
rp : 1, /* Resp addr valid */
rq : 1, /* Req addr valid */
- bsi : 8, /* Bus error status
+ bsi : 8, /* Bus error status
* info
*/
mc : 1, /* Machine check corrected */
@@ -601,8 +601,8 @@
#define pmci_bus_external_error pme_bus.eb
#define pmci_bus_mc pme_bus.mc

-/*
- * NOTE: this min_state_save area struct only includes the 1KB
+/*
+ * NOTE: this min_state_save area struct only includes the 1KB
* architectural state save area. The other 3 KB is scratch space
* for PAL.
*/
@@ -703,12 +703,12 @@
u64 pbf_disable_bus_addr_err_signal : 1;
u64 pbf_disable_bus_data_err_check : 1;
} pal_bus_features_s;
-} pal_bus_features_u_t;
+} pal_bus_features_u_t;

extern void pal_bus_features_print (u64);

/* Provide information about configurable processor bus features */
-static inline s64
+static inline s64
ia64_pal_bus_get_features (pal_bus_features_u_t *features_avail,
pal_bus_features_u_t *features_status,
pal_bus_features_u_t *features_control)
@@ -721,13 +721,13 @@
features_status->pal_bus_features_val = iprv.v1;
if (features_control)
features_control->pal_bus_features_val = iprv.v2;
- return iprv.status;
+ return iprv.status;
}

/* Enables/disables specific processor bus features */
-static inline s64
-ia64_pal_bus_set_features (pal_bus_features_u_t feature_select)
-{
+static inline s64
+ia64_pal_bus_set_features (pal_bus_features_u_t feature_select)
+{
struct ia64_pal_retval iprv;
PAL_CALL_PHYS(iprv, PAL_BUS_SET_FEATURES, feature_select.pal_bus_features_val, 0, 0);
return iprv.status;
@@ -739,7 +739,7 @@
{
struct ia64_pal_retval iprv;

- PAL_CALL(iprv, PAL_CACHE_INFO, cache_level, cache_type, 0);
+ PAL_CALL(iprv, PAL_CACHE_INFO, cache_level, cache_type, 0);

if (iprv.status = 0) {
conf->pcci_status = iprv.status;
@@ -747,7 +747,7 @@
conf->pcci_info_2.pcci2_data = iprv.v1;
conf->pcci_reserved = iprv.v2;
}
- return iprv.status;
+ return iprv.status;

}

@@ -757,7 +757,7 @@
{
struct ia64_pal_retval iprv;

- PAL_CALL(iprv, PAL_CACHE_PROT_INFO, cache_level, cache_type, 0);
+ PAL_CALL(iprv, PAL_CACHE_PROT_INFO, cache_level, cache_type, 0);

if (iprv.status = 0) {
prot->pcpi_status = iprv.status;
@@ -768,106 +768,106 @@
prot->pcp_info[4].pcpi_data = iprv.v2 & 0xffffffff;
prot->pcp_info[5].pcpi_data = iprv.v2 >> 32;
}
- return iprv.status;
+ return iprv.status;
}
-
+
/*
* Flush the processor instruction or data caches. *PROGRESS must be
* initialized to zero before calling this for the first time..
*/
-static inline s64
-ia64_pal_cache_flush (u64 cache_type, u64 invalidate, u64 *progress)
-{
+static inline s64
+ia64_pal_cache_flush (u64 cache_type, u64 invalidate, u64 *progress)
+{
struct ia64_pal_retval iprv;
- PAL_CALL_IC_OFF(iprv, PAL_CACHE_FLUSH, cache_type, invalidate, *progress);
+ PAL_CALL_IC_OFF(iprv, PAL_CACHE_FLUSH, cache_type, invalidate, *progress);
*progress = iprv.v1;
- return iprv.status;
+ return iprv.status;
}

/* Initialize the processor controlled caches */
-static inline s64
-ia64_pal_cache_init (u64 level, u64 cache_type, u64 restrict)
-{
+static inline s64
+ia64_pal_cache_init (u64 level, u64 cache_type, u64 restrict)
+{
struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_CACHE_INIT, level, cache_type, restrict);
- return iprv.status;
+ PAL_CALL(iprv, PAL_CACHE_INIT, level, cache_type, restrict);
+ return iprv.status;
}

-/* Initialize the tags and data of a data or unified cache line of
- * processor controlled cache to known values without the availability
+/* Initialize the tags and data of a data or unified cache line of
+ * processor controlled cache to known values without the availability
* of backing memory.
*/
-static inline s64
-ia64_pal_cache_line_init (u64 physical_addr, u64 data_value)
-{
+static inline s64
+ia64_pal_cache_line_init (u64 physical_addr, u64 data_value)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_CACHE_LINE_INIT, physical_addr, data_value, 0);
- return iprv.status;
+ return iprv.status;
}

/* Read the data and tag of a processor controlled cache line for diags */
-static inline s64
-ia64_pal_cache_read (pal_cache_line_id_u_t line_id, u64 physical_addr)
-{
+static inline s64
+ia64_pal_cache_read (pal_cache_line_id_u_t line_id, u64 physical_addr)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_CACHE_READ, line_id.pclid_data, physical_addr, 0);
- return iprv.status;
+ return iprv.status;
}

/* Return summary information about the heirarchy of caches controlled by the processor */
-static inline s64
-ia64_pal_cache_summary (u64 *cache_levels, u64 *unique_caches)
-{
+static inline s64
+ia64_pal_cache_summary (u64 *cache_levels, u64 *unique_caches)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_CACHE_SUMMARY, 0, 0, 0);
if (cache_levels)
*cache_levels = iprv.v0;
if (unique_caches)
*unique_caches = iprv.v1;
- return iprv.status;
+ return iprv.status;
}

/* Write the data and tag of a processor-controlled cache line for diags */
-static inline s64
-ia64_pal_cache_write (pal_cache_line_id_u_t line_id, u64 physical_addr, u64 data)
-{
- struct ia64_pal_retval iprv;
+static inline s64
+ia64_pal_cache_write (pal_cache_line_id_u_t line_id, u64 physical_addr, u64 data)
+{
+ struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_CACHE_WRITE, line_id.pclid_data, physical_addr, data);
- return iprv.status;
+ return iprv.status;
}

/* Return the parameters needed to copy relocatable PAL procedures from ROM to memory */
-static inline s64
+static inline s64
ia64_pal_copy_info (u64 copy_type, u64 num_procs, u64 num_iopics,
- u64 *buffer_size, u64 *buffer_align)
-{
+ u64 *buffer_size, u64 *buffer_align)
+{
struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_COPY_INFO, copy_type, num_procs, num_iopics);
+ PAL_CALL(iprv, PAL_COPY_INFO, copy_type, num_procs, num_iopics);
if (buffer_size)
*buffer_size = iprv.v0;
if (buffer_align)
*buffer_align = iprv.v1;
- return iprv.status;
+ return iprv.status;
}

/* Copy relocatable PAL procedures from ROM to memory */
-static inline s64
-ia64_pal_copy_pal (u64 target_addr, u64 alloc_size, u64 processor, u64 *pal_proc_offset)
-{
+static inline s64
+ia64_pal_copy_pal (u64 target_addr, u64 alloc_size, u64 processor, u64 *pal_proc_offset)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_COPY_PAL, target_addr, alloc_size, processor);
if (pal_proc_offset)
*pal_proc_offset = iprv.v0;
- return iprv.status;
+ return iprv.status;
}

/* Return the number of instruction and data debug register pairs */
-static inline s64
-ia64_pal_debug_info (u64 *inst_regs, u64 *data_regs)
-{
+static inline s64
+ia64_pal_debug_info (u64 *inst_regs, u64 *data_regs)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_DEBUG_INFO, 0, 0, 0);
if (inst_regs)
@@ -875,50 +875,50 @@
if (data_regs)
*data_regs = iprv.v1;

- return iprv.status;
+ return iprv.status;
}

#ifdef TBD
/* Switch from IA64-system environment to IA-32 system environment */
-static inline s64
-ia64_pal_enter_ia32_env (ia32_env1, ia32_env2, ia32_env3)
-{
+static inline s64
+ia64_pal_enter_ia32_env (ia32_env1, ia32_env2, ia32_env3)
+{
struct ia64_pal_retval iprv;
- PAL_CALL(iprv, PAL_ENTER_IA_32_ENV, ia32_env1, ia32_env2, ia32_env3);
- return iprv.status;
+ PAL_CALL(iprv, PAL_ENTER_IA_32_ENV, ia32_env1, ia32_env2, ia32_env3);
+ return iprv.status;
}
#endif

/* Get unique geographical address of this processor on its bus */
-static inline s64
-ia64_pal_fixed_addr (u64 *global_unique_addr)
-{
+static inline s64
+ia64_pal_fixed_addr (u64 *global_unique_addr)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_FIXED_ADDR, 0, 0, 0);
if (global_unique_addr)
*global_unique_addr = iprv.v0;
- return iprv.status;
+ return iprv.status;
}

/* Get base frequency of the platform if generated by the processor */
-static inline s64
-ia64_pal_freq_base (u64 *platform_base_freq)
-{
+static inline s64
+ia64_pal_freq_base (u64 *platform_base_freq)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_FREQ_BASE, 0, 0, 0);
if (platform_base_freq)
*platform_base_freq = iprv.v0;
- return iprv.status;
+ return iprv.status;
}

/*
* Get the ratios for processor frequency, bus frequency and interval timer to
- * to base frequency of the platform
+ * to base frequency of the platform
*/
-static inline s64
+static inline s64
ia64_pal_freq_ratios (struct pal_freq_ratio *proc_ratio, struct pal_freq_ratio *bus_ratio,
- struct pal_freq_ratio *itc_ratio)
-{
+ struct pal_freq_ratio *itc_ratio)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_FREQ_RATIOS, 0, 0, 0);
if (proc_ratio)
@@ -927,20 +927,21 @@
*(u64 *)bus_ratio = iprv.v1;
if (itc_ratio)
*(u64 *)itc_ratio = iprv.v2;
- return iprv.status;
+ return iprv.status;
}

-/* Make the processor enter HALT or one of the implementation dependent low
+/* Make the processor enter HALT or one of the implementation dependent low
* power states where prefetching and execution are suspended and cache and
* TLB coherency is not maintained.
*/
-static inline s64
-ia64_pal_halt (u64 halt_state)
-{
+static inline s64
+ia64_pal_halt (u64 halt_state)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_HALT, halt_state, 0, 0);
- return iprv.status;
+ return iprv.status;
}
+
typedef union pal_power_mgmt_info_u {
u64 ppmi_data;
struct {
@@ -954,87 +955,87 @@
} pal_power_mgmt_info_u_t;

/* Return information about processor's optional power management capabilities. */
-static inline s64
-ia64_pal_halt_info (pal_power_mgmt_info_u_t *power_buf)
-{
+static inline s64
+ia64_pal_halt_info (pal_power_mgmt_info_u_t *power_buf)
+{
struct ia64_pal_retval iprv;
PAL_CALL_STK(iprv, PAL_HALT_INFO, (unsigned long) power_buf, 0, 0);
- return iprv.status;
+ return iprv.status;
}

/* Cause the processor to enter LIGHT HALT state, where prefetching and execution are
* suspended, but cache and TLB coherency is maintained.
*/
-static inline s64
-ia64_pal_halt_light (void)
-{
+static inline s64
+ia64_pal_halt_light (void)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_HALT_LIGHT, 0, 0, 0);
- return iprv.status;
+ return iprv.status;
}

/* Clear all the processor error logging registers and reset the indicator that allows
* the error logging registers to be written. This procedure also checks the pending
* machine check bit and pending INIT bit and reports their states.
*/
-static inline s64
-ia64_pal_mc_clear_log (u64 *pending_vector)
-{
+static inline s64
+ia64_pal_mc_clear_log (u64 *pending_vector)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_MC_CLEAR_LOG, 0, 0, 0);
if (pending_vector)
*pending_vector = iprv.v0;
- return iprv.status;
+ return iprv.status;
}

-/* Ensure that all outstanding transactions in a processor are completed or that any
+/* Ensure that all outstanding transactions in a processor are completed or that any
* MCA due to thes outstanding transaction is taken.
*/
-static inline s64
-ia64_pal_mc_drain (void)
-{
+static inline s64
+ia64_pal_mc_drain (void)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_MC_DRAIN, 0, 0, 0);
- return iprv.status;
+ return iprv.status;
}

/* Return the machine check dynamic processor state */
-static inline s64
-ia64_pal_mc_dynamic_state (u64 offset, u64 *size, u64 *pds)
-{
+static inline s64
+ia64_pal_mc_dynamic_state (u64 offset, u64 *size, u64 *pds)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_MC_DYNAMIC_STATE, offset, 0, 0);
if (size)
*size = iprv.v0;
if (pds)
*pds = iprv.v1;
- return iprv.status;
+ return iprv.status;
}

/* Return processor machine check information */
-static inline s64
-ia64_pal_mc_error_info (u64 info_index, u64 type_index, u64 *size, u64 *error_info)
-{
+static inline s64
+ia64_pal_mc_error_info (u64 info_index, u64 type_index, u64 *size, u64 *error_info)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_MC_ERROR_INFO, info_index, type_index, 0);
if (size)
*size = iprv.v0;
if (error_info)
- *error_info = iprv.v1;
- return iprv.status;
+ *error_info = iprv.v1;
+ return iprv.status;
}

/* Inform PALE_CHECK whether a machine check is expected so that PALE_CHECK willnot
* attempt to correct any expected machine checks.
*/
-static inline s64
-ia64_pal_mc_expected (u64 expected, u64 *previous)
-{
+static inline s64
+ia64_pal_mc_expected (u64 expected, u64 *previous)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_MC_EXPECTED, expected, 0, 0);
if (previous)
*previous = iprv.v0;
- return iprv.status;
+ return iprv.status;
}

/* Register a platform dependent location with PAL to which it can save
@@ -1042,39 +1043,39 @@
* event.
*/
static inline s64
-ia64_pal_mc_register_mem (u64 physical_addr)
-{
+ia64_pal_mc_register_mem (u64 physical_addr)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_MC_REGISTER_MEM, physical_addr, 0, 0);
- return iprv.status;
+ return iprv.status;
}

/* Restore minimal architectural processor state, set CMC interrupt if necessary
* and resume execution
*/
-static inline s64
-ia64_pal_mc_resume (u64 set_cmci, u64 save_ptr)
-{
+static inline s64
+ia64_pal_mc_resume (u64 set_cmci, u64 save_ptr)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_MC_RESUME, set_cmci, save_ptr, 0);
- return iprv.status;
+ return iprv.status;
}

/* Return the memory attributes implemented by the processor */
-static inline s64
-ia64_pal_mem_attrib (u64 *mem_attrib)
-{
+static inline s64
+ia64_pal_mem_attrib (u64 *mem_attrib)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_MEM_ATTRIB, 0, 0, 0);
if (mem_attrib)
*mem_attrib = iprv.v0 & 0xff;
- return iprv.status;
+ return iprv.status;
}

/* Return the amount of memory needed for second phase of processor
* self-test and the required alignment of memory.
*/
-static inline s64
+static inline s64
ia64_pal_mem_for_test (u64 *bytes_needed, u64 *alignment)
{
struct ia64_pal_retval iprv;
@@ -1083,60 +1084,60 @@
*bytes_needed = iprv.v0;
if (alignment)
*alignment = iprv.v1;
- return iprv.status;
+ return iprv.status;
}

typedef union pal_perf_mon_info_u {
u64 ppmi_data;
struct {
u64 generic : 8,
- width : 8,
- cycles : 8,
+ width : 8,
+ cycles : 8,
retired : 8,
reserved : 32;
} pal_perf_mon_info_s;
} pal_perf_mon_info_u_t;
-
+
/* Return the performance monitor information about what can be counted
* and how to configure the monitors to count the desired events.
*/
-static inline s64
-ia64_pal_perf_mon_info (u64 *pm_buffer, pal_perf_mon_info_u_t *pm_info)
-{
+static inline s64
+ia64_pal_perf_mon_info (u64 *pm_buffer, pal_perf_mon_info_u_t *pm_info)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_PERF_MON_INFO, (unsigned long) pm_buffer, 0, 0);
if (pm_info)
pm_info->ppmi_data = iprv.v0;
- return iprv.status;
+ return iprv.status;
}

/* Specifies the physical address of the processor interrupt block
* and I/O port space.
*/
-static inline s64
-ia64_pal_platform_addr (u64 type, u64 physical_addr)
-{
+static inline s64
+ia64_pal_platform_addr (u64 type, u64 physical_addr)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_PLATFORM_ADDR, type, physical_addr, 0);
- return iprv.status;
+ return iprv.status;
}

/* Set the SAL PMI entrypoint in memory */
-static inline s64
-ia64_pal_pmi_entrypoint (u64 sal_pmi_entry_addr)
-{
+static inline s64
+ia64_pal_pmi_entrypoint (u64 sal_pmi_entry_addr)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_PMI_ENTRYPOINT, sal_pmi_entry_addr, 0, 0);
- return iprv.status;
+ return iprv.status;
}

struct pal_features_s;
/* Provide information about configurable processor features */
-static inline s64
-ia64_pal_proc_get_features (u64 *features_avail,
- u64 *features_status,
+static inline s64
+ia64_pal_proc_get_features (u64 *features_avail,
+ u64 *features_status,
u64 *features_control)
-{
+{
struct ia64_pal_retval iprv;
PAL_CALL_PHYS(iprv, PAL_PROC_GET_FEATURES, 0, 0, 0);
if (iprv.status = 0) {
@@ -1144,16 +1145,16 @@
*features_status = iprv.v1;
*features_control = iprv.v2;
}
- return iprv.status;
+ return iprv.status;
}

/* Enable/disable processor dependent features */
-static inline s64
-ia64_pal_proc_set_features (u64 feature_select)
-{
+static inline s64
+ia64_pal_proc_set_features (u64 feature_select)
+{
struct ia64_pal_retval iprv;
PAL_CALL_PHYS(iprv, PAL_PROC_SET_FEATURES, feature_select, 0, 0);
- return iprv.status;
+ return iprv.status;
}

/*
@@ -1162,7 +1163,7 @@
*/
typedef struct ia64_ptce_info_s {
u64 base;
- u32 count[2];
+ u32 count[2];
u32 stride[2];
} ia64_ptce_info_t;

@@ -1189,9 +1190,9 @@
}

/* Return info about implemented application and control registers. */
-static inline s64
-ia64_pal_register_info (u64 info_request, u64 *reg_info_1, u64 *reg_info_2)
-{
+static inline s64
+ia64_pal_register_info (u64 info_request, u64 *reg_info_1, u64 *reg_info_2)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_REGISTER_INFO, info_request, 0, 0);
if (reg_info_1)
@@ -1199,7 +1200,7 @@
if (reg_info_2)
*reg_info_2 = iprv.v1;
return iprv.status;
-}
+}

typedef union pal_hints_u {
u64 ph_data;
@@ -1210,62 +1211,62 @@
} pal_hints_s;
} pal_hints_u_t;

-/* Return information about the register stack and RSE for this processor
+/* Return information about the register stack and RSE for this processor
* implementation.
*/
-static inline s64
+static inline s64
ia64_pal_rse_info (u64 *num_phys_stacked, pal_hints_u_t *hints)
-{
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_RSE_INFO, 0, 0, 0);
if (num_phys_stacked)
*num_phys_stacked = iprv.v0;
if (hints)
hints->ph_data = iprv.v1;
- return iprv.status;
+ return iprv.status;
}

-/* Cause the processor to enter SHUTDOWN state, where prefetching and execution are
+/* Cause the processor to enter SHUTDOWN state, where prefetching and execution are
* suspended, but cause cache and TLB coherency to be maintained.
* This is usually called in IA-32 mode.
*/
-static inline s64
-ia64_pal_shutdown (void)
-{
+static inline s64
+ia64_pal_shutdown (void)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_SHUTDOWN, 0, 0, 0);
- return iprv.status;
+ return iprv.status;
}

/* Perform the second phase of processor self-test. */
-static inline s64
+static inline s64
ia64_pal_test_proc (u64 test_addr, u64 test_size, u64 attributes, u64 *self_test_state)
{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_TEST_PROC, test_addr, test_size, attributes);
if (self_test_state)
*self_test_state = iprv.v0;
- return iprv.status;
+ return iprv.status;
}

typedef union pal_version_u {
u64 pal_version_val;
struct {
- u64 pv_pal_b_rev : 8;
+ u64 pv_pal_b_rev : 8;
u64 pv_pal_b_model : 8;
u64 pv_reserved1 : 8;
u64 pv_pal_vendor : 8;
u64 pv_pal_a_rev : 8;
u64 pv_pal_a_model : 8;
- u64 pv_reserved2 : 16;
+ u64 pv_reserved2 : 16;
} pal_version_s;
} pal_version_u_t;

/* Return PAL version information */
-static inline s64
-ia64_pal_version (pal_version_u_t *pal_min_version, pal_version_u_t *pal_cur_version)
-{
+static inline s64
+ia64_pal_version (pal_version_u_t *pal_min_version, pal_version_u_t *pal_cur_version)
+{
struct ia64_pal_retval iprv;
PAL_CALL_PHYS(iprv, PAL_VERSION, 0, 0, 0);
if (pal_min_version)
@@ -1274,7 +1275,7 @@
if (pal_cur_version)
pal_cur_version->pal_version_val = iprv.v1;

- return iprv.status;
+ return iprv.status;
}

typedef union pal_tc_info_u {
@@ -1288,8 +1289,8 @@
reduce_tr : 1,
reserved : 29;
} pal_tc_info_s;
-} pal_tc_info_u_t;
-
+} pal_tc_info_u_t;
+
#define tc_reduce_tr pal_tc_info_s.reduce_tr
#define tc_unified pal_tc_info_s.unified
#define tc_pf pal_tc_info_s.pf
@@ -1298,10 +1299,10 @@
#define tc_num_sets pal_tc_info_s.num_sets

-/* Return information about the virtual memory characteristics of the processor
+/* Return information about the virtual memory characteristics of the processor
* implementation.
*/
-static inline s64
+static inline s64
ia64_pal_vm_info (u64 tc_level, u64 tc_type, pal_tc_info_u_t *tc_info, u64 *tc_pages)
{
struct ia64_pal_retval iprv;
@@ -1309,14 +1310,14 @@
if (tc_info)
tc_info->pti_val = iprv.v0;
if (tc_pages)
- *tc_pages = iprv.v1;
- return iprv.status;
+ *tc_pages = iprv.v1;
+ return iprv.status;
}

-/* Get page size information about the virtual memory characteristics of the processor
+/* Get page size information about the virtual memory characteristics of the processor
* implementation.
*/
-static inline s64
+static inline s64
ia64_pal_vm_page_size (u64 *tr_pages, u64 *vw_pages)
{
struct ia64_pal_retval iprv;
@@ -1324,8 +1325,8 @@
if (tr_pages)
*tr_pages = iprv.v0;
if (vw_pages)
- *vw_pages = iprv.v1;
- return iprv.status;
+ *vw_pages = iprv.v1;
+ return iprv.status;
}

typedef union pal_vm_info_1_u {
@@ -1348,23 +1349,23 @@
struct {
u64 impl_va_msb : 8,
rid_size : 8,
- reserved : 48;
+ reserved : 48;
} pal_vm_info_2_s;
} pal_vm_info_2_u_t;
-
-/* Get summary information about the virtual memory characteristics of the processor
+
+/* Get summary information about the virtual memory characteristics of the processor
* implementation.
*/
-static inline s64
-ia64_pal_vm_summary (pal_vm_info_1_u_t *vm_info_1, pal_vm_info_2_u_t *vm_info_2)
-{
+static inline s64
+ia64_pal_vm_summary (pal_vm_info_1_u_t *vm_info_1, pal_vm_info_2_u_t *vm_info_2)
+{
struct ia64_pal_retval iprv;
PAL_CALL(iprv, PAL_VM_SUMMARY, 0, 0, 0);
if (vm_info_1)
vm_info_1->pvi1_val = iprv.v0;
if (vm_info_2)
vm_info_2->pvi2_val = iprv.v1;
- return iprv.status;
+ return iprv.status;
}

typedef union pal_itr_valid_u {
@@ -1379,14 +1380,14 @@
} pal_tr_valid_u_t;

/* Read a translation register */
-static inline s64
+static inline s64
ia64_pal_tr_read (u64 reg_num, u64 tr_type, u64 *tr_buffer, pal_tr_valid_u_t *tr_valid)
{
struct ia64_pal_retval iprv;
PAL_CALL_PHYS_STK(iprv, PAL_VM_TR_READ, reg_num, tr_type,(u64)__pa(tr_buffer));
if (tr_valid)
tr_valid->piv_val = iprv.v0;
- return iprv.status;
+ return iprv.status;
}

static inline s64
diff -urN linux-davidm/include/asm-ia64/perfmon.h linux-2.4.10-lia/include/asm-ia64/perfmon.h
--- linux-davidm/include/asm-ia64/perfmon.h Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/include/asm-ia64/perfmon.h Mon Sep 24 22:07:39 2001
@@ -9,7 +9,7 @@
#include <linux/types.h>

/*
- * Structure used to define a context
+ * Request structure used to define a context
*/
typedef struct {
unsigned long smpl_entries; /* how many entries in sampling buffer */
@@ -23,7 +23,7 @@
} pfreq_context_t;

/*
- * Structure used to configure a PMC or PMD
+ * Request structure used to write/read a PMC or PMD
*/
typedef struct {
unsigned long reg_num; /* which register */
@@ -41,11 +41,16 @@
pfreq_reg_t pfr_reg; /* request to configure a PMD/PMC */
} perfmon_req_t;

+#ifdef __KERNEL__
+
extern void pfm_save_regs (struct task_struct *);
extern void pfm_load_regs (struct task_struct *);

-extern int pfm_inherit (struct task_struct *);
+extern int pfm_inherit (struct task_struct *, struct pt_regs *);
extern void pfm_context_exit (struct task_struct *);
extern void pfm_flush_regs (struct task_struct *);
+extern void pfm_cleanup_notifiers (struct task_struct *);
+
+#endif /* __KERNEL__ */

#endif /* _ASM_IA64_PERFMON_H */
diff -urN linux-davidm/include/asm-ia64/pgalloc.h linux-2.4.10-lia/include/asm-ia64/pgalloc.h
--- linux-davidm/include/asm-ia64/pgalloc.h Tue Jul 31 10:30:09 2001
+++ linux-2.4.10-lia/include/asm-ia64/pgalloc.h Mon Sep 24 23:02:56 2001
@@ -9,7 +9,7 @@
* in <asm/page.h> (currently 8192).
*
* Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 2000, Goutham Rao <goutham.rao@intel.com>
*/

@@ -164,11 +164,6 @@
#else
# define flush_tlb_all() __flush_tlb_all()
#endif
-
-/*
- * Serialize usage of ptc.g:
- */
-extern spinlock_t ptcg_lock;

/*
* Flush a specified user mapping
diff -urN linux-davidm/include/asm-ia64/processor.h linux-2.4.10-lia/include/asm-ia64/processor.h
--- linux-davidm/include/asm-ia64/processor.h Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/include/asm-ia64/processor.h Mon Sep 24 22:26:48 2001
@@ -190,6 +190,7 @@
#include <asm/page.h>
#include <asm/rse.h>
#include <asm/unwind.h>
+#include <asm/atomic.h>

/* like above but expressed as bitfields for more efficient access: */
struct ia64_psr {
@@ -332,6 +333,9 @@
__u64 map_base; /* base address for get_unmapped_area() */
__u64 task_size; /* limit for task size */
struct siginfo *siginfo; /* current siginfo struct for ptrace() */
+#if JITTER_BUG
+ __u64 mem;
+#endif

#ifdef CONFIG_IA32_SUPPORT
__u64 eflag; /* IA32 EFLAGS reg */
@@ -353,9 +357,10 @@
#ifdef CONFIG_PERFMON
__u64 pmc[IA64_NUM_PMC_REGS];
__u64 pmd[IA64_NUM_PMD_REGS];
- unsigned long pfm_pend_notify; /* non-zero if we need to notify and block */
+ unsigned long pfm_must_block; /* non-zero if we need to block on overflow */
void *pfm_context; /* pointer to detailed PMU context */
-# define INIT_THREAD_PM {0, }, {0, }, 0, 0,
+ atomic_t pfm_notifiers_check; /* indicate if release_thread much check tasklist */
+# define INIT_THREAD_PM {0, }, {0, }, 0, 0, {0},
#else
# define INIT_THREAD_PM
#endif
@@ -815,9 +820,22 @@

#define THREAD_SIZE IA64_STK_OFFSET
/* NOTE: The task struct and the stacks are allocated together. */
-#define alloc_task_struct() \
+#if JITTER_BUG
+# define alloc_task_struct() \
+({ \
+ unsigned long color, mem = __get_free_pages(GFP_KERNEL, IA64_TASK_STRUCT_LOG_NUM_PAGES); \
+ struct task_struct *p; \
+ color = ia64_fetch_and_add(1, &task_color) % NUM_TASK_COLORS; \
+ p = (struct task_struct *) (mem + color*MAX_JITTER_SIZE/(NUM_TASK_COLORS - 1)); \
+ p->thread.mem = mem; \
+ p; \
+})
+# define free_task_struct(p) free_pages((p)->thread.mem, IA64_TASK_STRUCT_LOG_NUM_PAGES)
+#else
+# define alloc_task_struct() \
((struct task_struct *) __get_free_pages(GFP_KERNEL, IA64_TASK_STRUCT_LOG_NUM_PAGES))
-#define free_task_struct(p) free_pages((unsigned long)(p), IA64_TASK_STRUCT_LOG_NUM_PAGES)
+# define free_task_struct(p) free_pages((unsigned long)(p), IA64_TASK_STRUCT_LOG_NUM_PAGES)
+#endif
#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count)

#define init_task (init_task_union.task)
@@ -970,45 +988,33 @@
return result;
}

-#define ARCH_HAS_PREFETCH
-#define ARCH_HAS_PREFETCHW
-#define ARCH_HAS_SPINLOCK_PREFETCH
-
-#define PREFETCH_STRIDE 256
-
-extern inline void
-prefetch (const void *x)
-{
- __asm__ __volatile__ ("lfetch [%0]" : : "r"(x));
-}
-
-extern inline void
-prefetchw (const void *x)
+static inline __u64
+ia64_tpa (__u64 addr)
{
- __asm__ __volatile__ ("lfetch.excl [%0]" : : "r"(x));
+ __u64 result;
+ asm ("tpa %0=%1" : "=r"(result) : "r"(addr));
+ return result;
}

-#define prefetch_spin_lock(x) prefetchw(x)
-
-
#define ARCH_HAS_PREFETCH
#define ARCH_HAS_PREFETCHW
#define ARCH_HAS_SPINLOCK_PREFETCH
#define PREFETCH_STRIDE 256

-extern inline void prefetch(const void *x)
+extern inline void
+prefetch (const void *x)
{
__asm__ __volatile__ ("lfetch [%0]" : : "r"(x));
}
-
-extern inline void prefetchw(const void *x)
+
+extern inline void
+prefetchw (const void *x)
{
__asm__ __volatile__ ("lfetch.excl [%0]" : : "r"(x));
}

-#define spin_lock_prefetch(x) prefetchw(x)
+#define spin_lock_prefetch(x) prefetchw(x)

-
#endif /* !__ASSEMBLY__ */

#endif /* _ASM_IA64_PROCESSOR_H */
diff -urN linux-davidm/include/asm-ia64/sal.h linux-2.4.10-lia/include/asm-ia64/sal.h
--- linux-davidm/include/asm-ia64/sal.h Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/include/asm-ia64/sal.h Mon Sep 24 22:57:49 2001
@@ -179,10 +179,8 @@
} ia64_sal_ptc_domain_info_t;

typedef struct ia64_sal_ptc_domain_proc_entry {
- u64 reserved : 16;
- u64 eid : 8; /* eid of processor */
u64 id : 8; /* id of processor */
- u64 ignored : 32;
+ u64 eid : 8; /* eid of processor */
} ia64_sal_ptc_domain_proc_entry_t;

diff -urN linux-davidm/include/asm-ia64/semaphore.h linux-2.4.10-lia/include/asm-ia64/semaphore.h
--- linux-davidm/include/asm-ia64/semaphore.h Tue Apr 17 17:19:31 2001
+++ linux-2.4.10-lia/include/asm-ia64/semaphore.h Mon Sep 24 23:02:56 2001
@@ -63,8 +63,6 @@
extern int __down_trylock (struct semaphore * sem);
extern void __up (struct semaphore * sem);

-extern spinlock_t semaphore_wake_lock;
-
/*
* Atomically decrement the semaphore's count. If it goes negative,
* block the calling thread in the TASK_UNINTERRUPTIBLE state.
diff -urN linux-davidm/include/asm-ia64/sembuf.h linux-2.4.10-lia/include/asm-ia64/sembuf.h
--- linux-davidm/include/asm-ia64/sembuf.h Sun Feb 6 18:42:40 2000
+++ linux-2.4.10-lia/include/asm-ia64/sembuf.h Mon Sep 24 22:10:28 2001
@@ -1,7 +1,7 @@
#ifndef _ASM_IA64_SEMBUF_H
#define _ASM_IA64_SEMBUF_H

-/*
+/*
* The semid64_ds structure for IA-64 architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
diff -urN linux-davidm/include/asm-ia64/shmbuf.h linux-2.4.10-lia/include/asm-ia64/shmbuf.h
--- linux-davidm/include/asm-ia64/shmbuf.h Sun Feb 6 18:42:40 2000
+++ linux-2.4.10-lia/include/asm-ia64/shmbuf.h Mon Sep 24 22:10:36 2001
@@ -1,7 +1,7 @@
#ifndef _ASM_IA64_SHMBUF_H
#define _ASM_IA64_SHMBUF_H

-/*
+/*
* The shmid64_ds structure for IA-64 architecture.
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
diff -urN linux-davidm/include/asm-ia64/sigcontext.h linux-2.4.10-lia/include/asm-ia64/sigcontext.h
--- linux-davidm/include/asm-ia64/sigcontext.h Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/include/asm-ia64/sigcontext.h Mon Sep 24 22:10:45 2001
@@ -18,6 +18,19 @@

# ifndef __ASSEMBLY__

+/*
+ * Note on handling of register backing store: sc_ar_bsp contains the address that would
+ * be found in ar.bsp after executing a "cover" instruction the context in which the
+ * signal was raised. If signal delivery required switching to an alternate signal stack
+ * (sc_rbs_base is not NULL), the "dirty" partition (as it would exist after executing the
+ * imaginary "cover" instruction) is backed by the *alternate* signal stack, not the
+ * original one. In this case, sc_rbs_base contains the base address of the new register
+ * backing store. The number of registers in the dirty partition can be calculated as:
+ *
+ * ndirty = ia64_rse_num_regs(sc_rbs_base, sc_rbs_base + (sc_loadrs >> 16))
+ *
+ */
+
struct sigcontext {
unsigned long sc_flags; /* see manifest constants above */
unsigned long sc_nat; /* bit i = 1 iff scratch reg gr[i] is a NaT */
@@ -40,8 +53,10 @@
unsigned long sc_gr[32]; /* general registers (static partition) */
struct ia64_fpreg sc_fr[128]; /* floating-point registers */

- unsigned long sc_rsvd[16]; /* reserved for future use */
+ unsigned long sc_rbs_base; /* NULL or new base of sighandler's rbs */
+ unsigned long sc_loadrs; /* see description above */

+ unsigned long sc_rsvd[14]; /* reserved for future use */
/*
* The mask must come last so we can increase _NSIG_WORDS
* without breaking binary compatibility.
diff -urN linux-davidm/include/asm-ia64/signal.h linux-2.4.10-lia/include/asm-ia64/signal.h
--- linux-davidm/include/asm-ia64/signal.h Tue Jul 31 10:30:09 2001
+++ linux-2.4.10-lia/include/asm-ia64/signal.h Mon Sep 24 22:10:57 2001
@@ -2,8 +2,8 @@
#define _ASM_IA64_SIGNAL_H

/*
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*
* Unfortunately, this file is being included by bits/signal.h in
* glibc-2.x. Hence the #ifdef __KERNEL__ ugliness.
@@ -80,14 +80,24 @@

#define SA_RESTORER 0x04000000

-/*
+/*
* sigaltstack controls
*/
#define SS_ONSTACK 1
#define SS_DISABLE 2

-#define MINSIGSTKSZ 2048
-#define SIGSTKSZ 8192
+/*
+ * The minimum stack size needs to be fairly large because we want to
+ * be sure that an app compiled for today's CPUs will continue to run
+ * on all future CPU models. The CPU model matters because the signal
+ * frame needs to have space for the complete machine state, including
+ * all physical stacked registers. The number of physical stacked
+ * registers is CPU model dependent, but given that the width of
+ * ar.rsc.loadrs is 14 bits, we can assume that they'll never take up
+ * more than 16KB of space.
+ */
+#define MINSIGSTKSZ 131027 /* min. stack size for sigaltstack() */
+#define SIGSTKSZ 262144 /* default stack size for sigaltstack() */

#ifdef __KERNEL__

diff -urN linux-davidm/include/asm-ia64/smp.h linux-2.4.10-lia/include/asm-ia64/smp.h
--- linux-davidm/include/asm-ia64/smp.h Tue Jul 31 10:30:09 2001
+++ linux-2.4.10-lia/include/asm-ia64/smp.h Mon Sep 24 22:26:48 2001
@@ -4,7 +4,7 @@
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
* Copyright (C) 2001 Hewlett-Packard Co
- * Copyright (C) 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * David Mosberger-Tang <davidm@hpl.hp.com>
*/
#ifndef _ASM_IA64_SMP_H
#define _ASM_IA64_SMP_H
@@ -18,6 +18,7 @@
#include <linux/kernel.h>

#include <asm/io.h>
+#include <asm/param.h>
#include <asm/processor.h>
#include <asm/ptrace.h>

@@ -107,7 +108,12 @@
return lid.f.id << 8 | lid.f.eid;
}

-#define NO_PROC_ID (-1)
+#define NO_PROC_ID 0xffffffff /* no processor magic marker */
+
+/*
+ * Extra overhead to move a task from one cpu to another (due to TLB and cache misses).
+ * Expressed in "negative nice value" units (larger number means higher priority/penalty).
+ */
#define PROC_CHANGE_PENALTY 20

extern void __init init_smp_config (void);
diff -urN linux-davidm/include/asm-ia64/smplock.h linux-2.4.10-lia/include/asm-ia64/smplock.h
--- linux-davidm/include/asm-ia64/smplock.h Thu Apr 5 12:51:47 2001
+++ linux-2.4.10-lia/include/asm-ia64/smplock.h Mon Sep 24 23:02:56 2001
@@ -17,7 +17,7 @@
/*
* Release global kernel lock and global interrupt lock
*/
-static __inline__ void
+static __inline__ void
release_kernel_lock(struct task_struct *task, int cpu)
{
if (task->lock_depth >= 0)
@@ -29,7 +29,7 @@
/*
* Re-acquire the kernel lock
*/
-static __inline__ void
+static __inline__ void
reacquire_kernel_lock(struct task_struct *task)
{
if (task->lock_depth >= 0)
@@ -43,14 +43,14 @@
* so we only need to worry about other
* CPU's.
*/
-static __inline__ void
+static __inline__ void
lock_kernel(void)
{
if (!++current->lock_depth)
spin_lock(&kernel_flag);
}

-static __inline__ void
+static __inline__ void
unlock_kernel(void)
{
if (--current->lock_depth < 0)
diff -urN linux-davidm/include/asm-ia64/spinlock.h linux-2.4.10-lia/include/asm-ia64/spinlock.h
--- linux-davidm/include/asm-ia64/spinlock.h Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/include/asm-ia64/spinlock.h Mon Sep 24 22:56:20 2001
@@ -84,7 +84,7 @@
"mov r29 = 1\n" \
";;\n" \
"1:\n" \
- "ld4 r2 = [%0]\n" \
+ "ld4.bias r2 = [%0]\n" \
";;\n" \
"cmp4.eq p0,p7 = r0,r2\n" \
"(p7) br.cond.spnt.few 1b \n" \
diff -urN linux-davidm/include/linux/highmem.h linux-2.4.10-lia/include/linux/highmem.h
--- linux-davidm/include/linux/highmem.h Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/include/linux/highmem.h Mon Sep 24 23:02:56 2001
@@ -46,7 +46,7 @@
static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
{
void *addr = kmap_atomic(page, KM_USER0);
- clear_user_page(addr, vaddr);
+ clear_user_page(addr, vaddr, page);
kunmap_atomic(addr, KM_USER0);
}

@@ -88,7 +88,7 @@

vfrom = kmap_atomic(from, KM_USER0);
vto = kmap_atomic(to, KM_USER1);
- copy_user_page(vto, vfrom, vaddr);
+ copy_user_page(vto, vfrom, vaddr, to);
kunmap_atomic(vfrom, KM_USER0);
kunmap_atomic(vto, KM_USER1);
}
diff -urN linux-davidm/include/linux/list.h linux-2.4.10-lia/include/linux/list.h
--- linux-davidm/include/linux/list.h Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/include/linux/list.h Mon Sep 24 22:26:48 2001
@@ -5,8 +5,6 @@

#include <linux/prefetch.h>

-#include <linux/prefetch.h>
-
/*
* Simple doubly linked list implementation.
*
diff -urN linux-davidm/include/linux/smp.h linux-2.4.10-lia/include/linux/smp.h
--- linux-davidm/include/linux/smp.h Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/include/linux/smp.h Mon Sep 24 22:26:48 2001
@@ -35,11 +35,6 @@
extern void smp_boot_cpus(void);

/*
- * Processor call in. Must hold processors until ..
- */
-extern void smp_callin(void);
-
-/*
* Multiprocessors may now schedule
*/
extern void smp_commence(void);
@@ -56,10 +51,6 @@
extern volatile int smp_threads_ready;

extern int smp_num_cpus;
-
-extern volatile unsigned long smp_msg_data;
-extern volatile int smp_src_cpu;
-extern volatile int smp_msg_id;

#define MSG_ALL_BUT_SELF 0x8000 /* Assume <32768 CPU's */
#define MSG_ALL 0x8001
diff -urN linux-davidm/kernel/module.c linux-2.4.10-lia/kernel/module.c
--- linux-davidm/kernel/module.c Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/kernel/module.c Mon Sep 24 21:29:34 2001
@@ -245,7 +245,6 @@
void __init init_modules(void)
{
kernel_module.nsyms = __stop___ksymtab - __start___ksymtab;
-
arch_init_modules(&kernel_module);
}

diff -urN linux-davidm/kernel/printk.c linux-2.4.10-lia/kernel/printk.c
--- linux-davidm/kernel/printk.c Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/kernel/printk.c Mon Sep 24 21:29:44 2001
@@ -16,8 +16,6 @@
* 01Mar01 Andrew Morton <andrewm@uow.edu.au>
*/

-#include <linux/config.h>
-
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
@@ -312,6 +310,12 @@
__call_console_drivers(start, end);
}
}
+#ifdef CONFIG_IA64_EARLY_PRINTK
+ if (!console_drivers) {
+ static void early_printk (const char *str, size_t len);
+ early_printk(&LOG_BUF(start), end - start);
+ }
+#endif
}

/*
@@ -662,12 +666,13 @@
static int current_ypos = VGALINES, current_xpos = 0;

void
-early_printk (const char *str)
+early_printk (const char *str, size_t len)
{
char c;
int i, k, j;

- while ((c = *str++) != '\0') {
+ while (len-- > 0) {
+ c = *str++;
if (current_ypos >= VGALINES) {
/* scroll 1 line up */
for (k = 1, j = 0; k < VGALINES; k++, j++) {
diff -urN linux-davidm/kernel/sched.c linux-2.4.10-lia/kernel/sched.c
--- linux-davidm/kernel/sched.c Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/kernel/sched.c Mon Sep 24 21:29:47 2001
@@ -540,9 +540,6 @@

spin_lock_prefetch(&runqueue_lock);

-
- prefetch_spin_lock(&runqueue_lock);
-
if (!current->active_mm) BUG();
need_resched_back:
prev = current;
diff -urN linux-davidm/kernel/signal.c linux-2.4.10-lia/kernel/signal.c
--- linux-davidm/kernel/signal.c Mon Sep 24 15:08:37 2001
+++ linux-2.4.10-lia/kernel/signal.c Mon Sep 24 22:13:29 2001
@@ -1104,8 +1104,19 @@
ss_sp = NULL;
} else {
error = -ENOMEM;
+#ifdef __ia64__
+ /*
+ * XXX fix me: due to an oversight, MINSIGSTKSZ used to be defined
+ * as 2KB, which is far too small. This was after Linux kernel
+ * 2.4.9 but since there are a fair number of ia64 apps out there,
+ * we continue to allow "too" small sigaltstacks for a while.
+ */
+ if (ss_size < 2048)
+ goto out;
+#else
if (ss_size < MINSIGSTKSZ)
goto out;
+#endif
}

current->sas_ss_sp = (unsigned long) ss_sp;
diff -urN linux-davidm/lib/Makefile linux-2.4.10-lia/lib/Makefile
--- linux-davidm/lib/Makefile Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/lib/Makefile Mon Sep 24 21:29:52 2001
@@ -10,7 +10,7 @@

export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o

-obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o bust_spinlocks.o rbtree.o
+obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o bust_spinlocks.o rbtree.o crc32.o

obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
obj-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
diff -urN linux-davidm/lib/dec_and_lock.c linux-2.4.10-lia/lib/dec_and_lock.c
--- linux-davidm/lib/dec_and_lock.c Mon Sep 24 15:08:39 2001
+++ linux-2.4.10-lia/lib/dec_and_lock.c Mon Sep 24 22:13:39 2001
@@ -26,7 +26,6 @@
* store-conditional approach, for example.
*/

-#ifndef atomic_dec_and_lock
int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
{
spin_lock(lock);
@@ -37,4 +36,3 @@
}

EXPORT_SYMBOL(atomic_dec_and_lock);
-#endif
diff -urN linux-davidm/mm/memory.c linux-2.4.10-lia/mm/memory.c
--- linux-davidm/mm/memory.c Mon Sep 24 22:31:45 2001
+++ linux-2.4.10-lia/mm/memory.c Mon Sep 24 21:30:00 2001
@@ -127,7 +127,7 @@
pmd = pmd_offset(dir, 0);
pgd_clear(dir);
for (j = 0; j < PTRS_PER_PMD ; j++) {
- prefetchw(pmd+j+(PREFETCH_STRIDE/16));
+ prefetchw(pmd + j + PREFETCH_STRIDE/sizeof(*pmd));
free_one_pmd(pmd+j);
}
pmd_free(pmd);