From mboxrd@z Thu Jan 1 00:00:00 1970 From: David Mosberger Date: Thu, 05 Oct 2000 19:01:10 +0000 Subject: [Linux-ia64] kernel update (relative to v2.4.0-test9) Message-Id: List-Id: References: In-Reply-To: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: linux-ia64@vger.kernel.org The latest IA-64 Linux kernel diff is now available at: ftp://ftp.kernel.org/pub/linux/kernel/ports/ia64/ in file linux-2.4.0-test9-ia64-001004.diff. Actually, it has been available since last night, but I ran into some problems booting the new kernel remotely so I couldn't actually test it until this morning. Here is a summary of what changed since the last kernel: - Stephane's perfmon updates (warning: this is works in progress; especially the changes to ptrace will disappear so don't write user apps that depend on this way of accessing the PMU...) - SGI SN1 updates (Kanoj); also stash away coherence domain info in global variable "ia64_ptc_domain_info" - Asit's patch to support running with VHPT disabled; this is for kernel hacking only and should not be used for normal operation. This patch uncovered some bad kernel references which were also fixed. - With SMP, do sync.i in context switch to ensure "fc"s are visible on all CPUs (Asit) - TLB handler fixes by Patrick and yours truly. - qlogic SCSI driver update (BJ). - Remove IA-64 version of ioperm syscall and fix vt.c to not support the ioctl that used this call - Added 32-bit division routines required by latest CVS compiler. 32-bit division can get away with one fewer iteration and also uses few enough fp registers that we don't need to save/restore anything. - Fix SMP BogoMIPS calculation and printing; the BogoMIPS values are now really per-CPU - Various minor and not so minor updates to the kernel unwinder. - Fixed SCSI disk driver so it works when compiled into the kernel (yes, this is a generic test9 bug; Linus must have been in a hurry to catch that plane to Germany... ;-). - __atomic_fool_gcc() disappeared. It shouldn't be necessary with the compilers available for IA-64 Linux. - Replace "extern inline" with "static inline". - Change HZ for simulator to 32 Hz; the kernel time-of-day code is more accurate if HZ is an integer power of two. - Add parport.h needed by some kernel modules. - Various updates to get things in sync with 2.4.0-test9 That should be it. This kernel is known to boot fine on 4-way Lion, 2-way and 1-way Big Sur, as well as the HP Ski simulator. Enjoy, --david diff -urN linux-davidm/arch/ia64/Makefile linux-2.4.0-test9-lia/arch/ia64/Makefile --- linux-davidm/arch/ia64/Makefile Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/Makefile Wed Oct 4 21:32:24 2000 @@ -46,11 +46,18 @@ $(CORE_FILES) endif -ifdef CONFIG_IA64_SGI_SN1_SIM +ifdef CONFIG_IA64_SGI_SN1 +CFLAGS := $(CFLAGS) -DSN -I. -DBRINGUP -DDIRECT_L1_CONSOLE \ + -DNUMA_BASE -DSIMULATED_KLGRAPH -DNUMA_MIGR_CONTROL \ + -DLITTLE_ENDIAN -DREAL_HARDWARE -DLANGUAGE_C=1 \ + -D_LANGUAGE_C=1 SUBDIRS := arch/$(ARCH)/sn/sn1 \ arch/$(ARCH)/sn \ + arch/$(ARCH)/sn/io \ + arch/$(ARCH)/sn/fprom \ $(SUBDIRS) CORE_FILES := arch/$(ARCH)/sn/sn.a \ + arch/$(ARCH)/sn/io/sgiio.o\ $(CORE_FILES) endif diff -urN linux-davidm/arch/ia64/config.in linux-2.4.0-test9-lia/arch/ia64/config.in --- linux-davidm/arch/ia64/config.in Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/config.in Wed Oct 4 21:32:56 2000 @@ -27,7 +27,7 @@ "generic CONFIG_IA64_GENERIC \ DIG-compliant CONFIG_IA64_DIG \ HP-simulator CONFIG_IA64_HP_SIM \ - SN1-simulator CONFIG_IA64_SGI_SN1_SIM" generic + SGI-SN1 CONFIG_IA64_SGI_SN1" generic choice 'Kernel page size' \ "4KB CONFIG_IA64_PAGE_SIZE_4KB \ @@ -61,9 +61,20 @@ fi fi -if [ "$CONFIG_IA64_SGI_SN1_SIM" = "y" ]; then - define_bool CONFIG_NUMA y - define_bool CONFIG_IA64_SOFTSDV_HACKS y +if [ "$CONFIG_IA64_SGI_SN1" = "y" ]; then + bool ' Enable use of global TLB purge instruction (ptc.g)' CONFIG_ITANIUM_PTCG + bool ' Enable Itanium B-step specific code' CONFIG_ITANIUM_BSTEP_SPECIFIC + if [ "$CONFIG_ITANIUM_BSTEP_SPECIFIC" = "y" ]; then + bool ' Enable Itanium B0-step specific code' CONFIG_ITANIUM_B0_SPECIFIC + fi + bool ' Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN1_SIM n + bool ' Enable SGI hack for version 1.0 syngery bugs' CONFIG_IA64_SGI_SYNERGY_1_0_HACKS n + define_bool CONFIG_DEVFS_DEBUG y + define_bool CONFIG_DEVFS_FS y + define_bool CONFIG_IA64_BRL_EMU y + define_bool CONFIG_IA64_MCA y + define_bool CONFIG_IA64_SGI_IO y + define_bool CONFIG_ITANIUM y fi define_bool CONFIG_KCORE_ELF y # On IA-64, we always want an ELF /proc/kcore. @@ -237,5 +248,6 @@ bool 'Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ bool 'Print possible IA64 hazards to console' CONFIG_IA64_PRINT_HAZARDS bool 'Enable new unwind support' CONFIG_IA64_NEW_UNWIND +bool 'Disable VHPT' CONFIG_DISABLE_VHPT endmenu diff -urN linux-davidm/arch/ia64/dig/iosapic.c linux-2.4.0-test9-lia/arch/ia64/dig/iosapic.c --- linux-davidm/arch/ia64/dig/iosapic.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/dig/iosapic.c Wed Oct 4 21:33:55 2000 @@ -386,7 +386,7 @@ unsigned int ver, v; int l, max_pin; - ver = iosapic_version(iosapic->address); + ver = iosapic_version((unsigned long) ioremap(iosapic->address, 0)); max_pin = (ver >> 16) & 0xff; printk("IOSAPIC Version %x.%x: address 0x%lx IRQs 0x%x - 0x%x\n", diff -urN linux-davidm/arch/ia64/kernel/Makefile linux-2.4.0-test9-lia/arch/ia64/kernel/Makefile --- linux-davidm/arch/ia64/kernel/Makefile Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/Makefile Wed Oct 4 21:34:23 2000 @@ -16,7 +16,7 @@ obj-$(CONFIG_IA64_GENERIC) += machvec.o obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_PCI) += pci.o -obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o diff -urN linux-davidm/arch/ia64/kernel/acpi.c linux-2.4.0-test9-lia/arch/ia64/kernel/acpi.c --- linux-davidm/arch/ia64/kernel/acpi.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/acpi.c Wed Oct 4 21:34:32 2000 @@ -136,13 +136,12 @@ break; } -#if 1/*def ACPI_DEBUG*/ +# ifdef ACPI_DEBUG printk("Legacy ISA IRQ %x -> IA64 Vector %x IOSAPIC Pin %x Active %s %s Trigger\n", legacy->isa_irq, vector, iosapic_pin(vector), ((iosapic_polarity(vector) = IO_SAPIC_POL_LOW) ? "Low" : "High"), ((iosapic_trigger(vector) = IO_SAPIC_LEVEL) ? "Level" : "Edge")); -#endif /* ACPI_DEBUG */ - +# endif /* ACPI_DEBUG */ #endif /* CONFIG_IA64_IRQ_ACPI */ } @@ -279,7 +278,7 @@ #else # if defined (CONFIG_IA64_HP_SIM) return "hpsim"; -# elif defined (CONFIG_IA64_SGI_SN1_SIM) +# elif defined (CONFIG_IA64_SGI_SN1) return "sn1"; # elif defined (CONFIG_IA64_DIG) return "dig"; diff -urN linux-davidm/arch/ia64/kernel/efi.c linux-2.4.0-test9-lia/arch/ia64/kernel/efi.c --- linux-davidm/arch/ia64/kernel/efi.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/efi.c Wed Oct 4 21:34:44 2000 @@ -376,6 +376,16 @@ #endif efi_map_pal_code(); + +#ifndef CONFIG_IA64_SOFTSDV_HACKS + /* + * (Some) SoftSDVs seem to have a problem with this call. + * Since it's mostly a performance optimization, just don't do + * it for now... --davidm 99/12/6 + */ + efi_enter_virtual_mode(); +#endif + } void diff -urN linux-davidm/arch/ia64/kernel/entry.S linux-2.4.0-test9-lia/arch/ia64/kernel/entry.S --- linux-davidm/arch/ia64/kernel/entry.S Fri Sep 8 14:34:53 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/entry.S Wed Oct 4 23:08:09 2000 @@ -120,6 +120,9 @@ mov r13=in0 // set "current" pointer ;; DO_LOAD_SWITCH_STACK( ) +#ifdef CONFIG_SMP + sync.i // ensure "fc"s done by this CPU are visible on other CPUs +#endif br.ret.sptk.few rp END(ia64_switch_to) @@ -1088,7 +1091,7 @@ data8 sys_setpriority data8 sys_statfs data8 sys_fstatfs - data8 sys_ioperm // 1105 + data8 ia64_ni_syscall data8 sys_semget data8 sys_semop data8 sys_semctl diff -urN linux-davidm/arch/ia64/kernel/ia64_ksyms.c linux-2.4.0-test9-lia/arch/ia64/kernel/ia64_ksyms.c --- linux-davidm/arch/ia64/kernel/ia64_ksyms.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/ia64_ksyms.c Wed Oct 4 21:35:21 2000 @@ -97,13 +97,23 @@ EXPORT_SYMBOL(__ia64_syscall); /* from arch/ia64/lib */ +extern void __divsi3(void); +extern void __udivsi3(void); +extern void __modsi3(void); +extern void __umodsi3(void); extern void __divdi3(void); extern void __udivdi3(void); extern void __moddi3(void); extern void __umoddi3(void); +EXPORT_SYMBOL_NOVERS(__divsi3); +EXPORT_SYMBOL_NOVERS(__udivsi3); +EXPORT_SYMBOL_NOVERS(__modsi3); +EXPORT_SYMBOL_NOVERS(__umodsi3); EXPORT_SYMBOL_NOVERS(__divdi3); EXPORT_SYMBOL_NOVERS(__udivdi3); EXPORT_SYMBOL_NOVERS(__moddi3); EXPORT_SYMBOL_NOVERS(__umoddi3); +extern unsigned long ia64_iobase; +EXPORT_SYMBOL(ia64_iobase); diff -urN linux-davidm/arch/ia64/kernel/irq_ia64.c linux-2.4.0-test9-lia/arch/ia64/kernel/irq_ia64.c --- linux-davidm/arch/ia64/kernel/irq_ia64.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/irq_ia64.c Wed Oct 4 21:35:32 2000 @@ -39,7 +39,8 @@ spinlock_t ivr_read_lock; #endif -unsigned long ipi_base_addr = IPI_DEFAULT_BASE_ADDR; /* default base addr of IPI table */ +/* default base addr of IPI table */ +unsigned long ipi_base_addr = (__IA64_UNCACHED_OFFSET | IPI_DEFAULT_BASE_ADDR); /* * Legacy IRQ to IA-64 vector translation table. Any vector not in diff -urN linux-davidm/arch/ia64/kernel/ivt.S linux-2.4.0-test9-lia/arch/ia64/kernel/ivt.S --- linux-davidm/arch/ia64/kernel/ivt.S Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/ivt.S Wed Oct 4 21:36:12 2000 @@ -196,32 +196,32 @@ * The speculative access will fail if there is no TLB entry * for the L3 page table page we're trying to access. */ - mov r16=cr.iha // get virtual address of L3 PTE - mov r19=cr.ifa // get virtual address + mov r16=cr.ifa // get virtual address + mov r19=cr.iha // get virtual address of L3 PTE ;; - ld8.s r17=[r16] // try to read L3 PTE + ld8.s r17=[r19] // try to read L3 PTE mov r31=pr // save predicates ;; - tnat.nz p6,p0=r16 // did read succeed? + tnat.nz p6,p0=r17 // did read succeed? (p6) br.cond.spnt.many 1f ;; itc.i r17 ;; #ifdef CONFIG_SMP - ld8.s r18=[r16] // try to read L3 PTE again and see if same + ld8.s r18=[r19] // try to read L3 PTE again and see if same mov r20=PAGE_SHIFT<<2 // setup page size for purge ;; cmp.eq p6,p7=r17,r18 ;; -(p7) ptc.l r19,r20 +(p7) ptc.l r16,r20 #endif - mov pr=r31,-1 rfi -1: mov r16=cr.ifa // get address that caused the TLB miss - ;; - rsm psr.dt // use physical addressing for data +#ifdef CONFIG_DISABLE_VHPT +itlb_fault: +#endif +1: rsm psr.dt // use physical addressing for data mov r19=ar.k7 // get page table base address shl r21=r16,3 // shift bit 60 into sign bit shr.u r17=r16,61 // get the region number into r17 @@ -283,31 +283,32 @@ * The speculative access will fail if there is no TLB entry * for the L3 page table page we're trying to access. */ - mov r16=cr.iha // get virtual address of L3 PTE - mov r19=cr.ifa // get virtual address + mov r16=cr.ifa // get virtual address + mov r19=cr.iha // get virtual address of L3 PTE ;; - ld8.s r17=[r16] // try to read L3 PTE + ld8.s r17=[r19] // try to read L3 PTE mov r31=pr // save predicates ;; - tnat.nz p6,p0=r16 // did read succeed? + tnat.nz p6,p0=r17 // did read succeed? (p6) br.cond.spnt.many 1f ;; itc.d r17 ;; #ifdef CONFIG_SMP - ld8.s r18=[r16] // try to read L3 PTE again and see if same + ld8.s r18=[r19] // try to read L3 PTE again and see if same mov r20=PAGE_SHIFT<<2 // setup page size for purge ;; cmp.eq p6,p7=r17,r18 ;; -(p7) ptc.l r19,r20 +(p7) ptc.l r16,r20 #endif mov pr=r31,-1 rfi -1: mov r16=cr.ifa // get address that caused the TLB miss - ;; - rsm psr.dt // use physical addressing for data +#ifdef CONFIG_DISABLE_VHPT +dtlb_fault: +#endif +1: rsm psr.dt // use physical addressing for data mov r19=ar.k7 // get page table base address shl r21=r16,3 // shift bit 60 into sign bit shr.u r17=r16,61 // get the region number into r17 @@ -360,6 +361,16 @@ ///////////////////////////////////////////////////////////////////////////////////////// // 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19) mov r16=cr.ifa // get address that caused the TLB miss +#ifdef CONFIG_DISABLE_VHPT + mov r31=pr + ;; + shr.u r21=r16,61 // get the region number into r21 + ;; + cmp.gt p6,p0=6,r21 // user mode +(p6) br.cond.dptk.many itlb_fault + ;; + mov pr=r31,-1 +#endif movl r17=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RX ;; shr.u r18=r16,57 // move address bit 61 to bit 4 @@ -380,8 +391,14 @@ movl r17=__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RW mov r20=cr.isr mov r21=cr.ipsr - mov r19=pr + mov r31=pr ;; +#ifdef CONFIG_DISABLE_VHPT + shr.u r22=r16,61 // get the region number into r21 + ;; + cmp.gt p8,p0=6,r22 // user mode +(p8) br.cond.dptk.many dtlb_fault +#endif tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on? shr.u r18=r16,57 // move address bit 61 to bit 4 dep r16=0,r16,IA64_MAX_PHYS_BITS,(64-IA64_MAX_PHYS_BITS) // clear ed & reserved bits @@ -394,7 +411,7 @@ (p6) mov cr.ipsr=r21 ;; (p7) itc.d r16 // insert the TLB entry - mov pr=r19,-1 + mov pr=r31,-1 rfi ;; diff -urN linux-davidm/arch/ia64/kernel/mca.c linux-2.4.0-test9-lia/arch/ia64/kernel/mca.c --- linux-davidm/arch/ia64/kernel/mca.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/mca.c Wed Oct 4 21:36:32 2000 @@ -255,8 +255,11 @@ IA64_MCA_DEBUG("ia64_mca_init : correctable mca vector setup done\n"); ia64_mc_info.imi_mca_handler = __pa(ia64_os_mca_dispatch); - ia64_mc_info.imi_mca_handler_size = - __pa(ia64_os_mca_dispatch_end) - __pa(ia64_os_mca_dispatch); + /* + * XXX - disable SAL checksum by setting size to 0; should be + * __pa(ia64_os_mca_dispatch_end) - __pa(ia64_os_mca_dispatch); + */ + ia64_mc_info.imi_mca_handler_size = 0; /* Register the os mca handler with SAL */ if (ia64_sal_set_vectors(SAL_VECTOR_OS_MCA, ia64_mc_info.imi_mca_handler, @@ -268,10 +271,14 @@ IA64_MCA_DEBUG("ia64_mca_init : registered os mca handler with SAL\n"); + /* + * XXX - disable SAL checksum by setting size to 0, should be + * IA64_INIT_HANDLER_SIZE + */ ia64_mc_info.imi_monarch_init_handler = __pa(mon_init_ptr->fp); - ia64_mc_info.imi_monarch_init_handler_size = IA64_INIT_HANDLER_SIZE; + ia64_mc_info.imi_monarch_init_handler_size = 0; ia64_mc_info.imi_slave_init_handler = __pa(slave_init_ptr->fp); - ia64_mc_info.imi_slave_init_handler_size = IA64_INIT_HANDLER_SIZE; + ia64_mc_info.imi_slave_init_handler_size = 0; IA64_MCA_DEBUG("ia64_mca_init : os init handler at %lx\n",ia64_mc_info.imi_monarch_init_handler); diff -urN linux-davidm/arch/ia64/kernel/perfmon.c linux-2.4.0-test9-lia/arch/ia64/kernel/perfmon.c --- linux-davidm/arch/ia64/kernel/perfmon.c Thu Aug 24 08:17:30 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/perfmon.c Wed Oct 4 21:36:39 2000 @@ -10,15 +10,19 @@ #include #include +#include #include #include #include +#include +#include #include #include #include #include #include +#include /* Long blurb on how this works: * We set dcr.pp, psr.pp, and the appropriate pmc control values with @@ -52,68 +56,107 @@ #ifdef CONFIG_PERFMON #define MAX_PERF_COUNTER 4 /* true for Itanium, at least */ +#define PMU_FIRST_COUNTER 4 /* first generic counter */ + #define WRITE_PMCS_AND_START 0xa0 #define WRITE_PMCS 0xa1 #define READ_PMDS 0xa2 #define STOP_PMCS 0xa3 -#define IA64_COUNTER_MASK 0xffffffffffffff6fL -#define PERF_OVFL_VAL 0xffffffffL -volatile int used_by_system; -struct perfmon_counter { - unsigned long data; - unsigned long counter_num; -}; +/* + * this structure needs to be enhanced + */ +typedef struct { + unsigned long pmu_reg_data; /* generic PMD register */ + unsigned long pmu_reg_num; /* which register number */ +} perfmon_reg_t; + +/* + * This structure is initialize at boot time and contains + * a description of the PMU main characteristic as indicated + * by PAL + */ +typedef struct { + unsigned long perf_ovfl_val; /* overflow value for generic counters */ + unsigned long max_pmc; /* highest PMC */ + unsigned long max_pmd; /* highest PMD */ + unsigned long max_counters; /* number of generic counter pairs (PMC/PMD) */ +} pmu_config_t; +/* XXX will go static when ptrace() is cleaned */ +unsigned long perf_ovfl_val; /* overflow value for generic counters */ + +static pmu_config_t pmu_conf; + +/* + * could optimize to avoid cache conflicts in SMP + */ unsigned long pmds[NR_CPUS][MAX_PERF_COUNTER]; asmlinkage unsigned long -sys_perfmonctl (int cmd1, int cmd2, void *ptr) +sys_perfmonctl (int cmd, int count, void *ptr, long arg4, long arg5, long arg6, long arg7, long arg8, long stack) { - struct perfmon_counter tmp, *cptr = ptr; - unsigned long cnum, dcr, flags; - struct perf_counter; + struct pt_regs *regs = (struct pt_regs *) &stack; + perfmon_reg_t tmp, *cptr = ptr; + unsigned long cnum; int i; - switch (cmd1) { + switch (cmd) { case WRITE_PMCS: /* Writes to PMC's and clears PMDs */ case WRITE_PMCS_AND_START: /* Also starts counting */ - if (cmd2 <= 0 || cmd2 > MAX_PERF_COUNTER - used_by_system) - return -EINVAL; - - if (!access_ok(VERIFY_READ, cptr, sizeof(struct perf_counter)*cmd2)) + if (!access_ok(VERIFY_READ, cptr, sizeof(struct perfmon_reg_t)*count)) return -EFAULT; - current->thread.flags |= IA64_THREAD_PM_VALID; + for (i = 0; i < count; i++, cptr++) { - for (i = 0; i < cmd2; i++, cptr++) { copy_from_user(&tmp, cptr, sizeof(tmp)); - /* XXX need to check validity of counter_num and perhaps data!! */ - if (tmp.counter_num < 4 - || tmp.counter_num >= 4 + MAX_PERF_COUNTER - used_by_system) - return -EFAULT; - - ia64_set_pmc(tmp.counter_num, tmp.data); - ia64_set_pmd(tmp.counter_num, 0); - pmds[smp_processor_id()][tmp.counter_num - 4] = 0; + + /* XXX need to check validity of pmu_reg_num and perhaps data!! */ + + if (tmp.pmu_reg_num > pmu_conf.max_pmc || tmp.pmu_reg_num = 0) return -EFAULT; + + ia64_set_pmc(tmp.pmu_reg_num, tmp.pmu_reg_data); + + /* to go away */ + if (tmp.pmu_reg_num >= PMU_FIRST_COUNTER && tmp.pmu_reg_num < PMU_FIRST_COUNTER+pmu_conf.max_counters) { + ia64_set_pmd(tmp.pmu_reg_num, 0); + pmds[smp_processor_id()][tmp.pmu_reg_num - PMU_FIRST_COUNTER] = 0; + + printk(__FUNCTION__" setting PMC/PMD[%ld] es=0x%lx pmd[%ld]=%lx\n", tmp.pmu_reg_num, (tmp.pmu_reg_data>>8) & 0x7f, tmp.pmu_reg_num, ia64_get_pmd(tmp.pmu_reg_num)); + } else + printk(__FUNCTION__" setting PMC[%ld]=0x%lx\n", tmp.pmu_reg_num, tmp.pmu_reg_data); } - if (cmd1 = WRITE_PMCS_AND_START) { + if (cmd = WRITE_PMCS_AND_START) { +#if 0 +/* irrelevant with user monitors */ local_irq_save(flags); + dcr = ia64_get_dcr(); dcr |= IA64_DCR_PP; ia64_set_dcr(dcr); + local_irq_restore(flags); +#endif + ia64_set_pmc(0, 0); + + /* will start monitoring right after rfi */ + ia64_psr(regs)->up = 1; } + /* + * mark the state as valid. + * this will trigger save/restore at context switch + */ + current->thread.flags |= IA64_THREAD_PM_VALID; break; case READ_PMDS: - if (cmd2 <= 0 || cmd2 > MAX_PERF_COUNTER - used_by_system) + if (count <= 0 || count > MAX_PERF_COUNTER) return -EINVAL; - if (!access_ok(VERIFY_WRITE, cptr, sizeof(struct perf_counter)*cmd2)) + if (!access_ok(VERIFY_WRITE, cptr, sizeof(struct perfmon_reg_t)*count)) return -EFAULT; /* This looks shady, but IMHO this will work fine. This is @@ -121,14 +164,15 @@ * with the interrupt handler. See explanation in the * following comment. */ - +#if 0 +/* irrelevant with user monitors */ local_irq_save(flags); __asm__ __volatile__("rsm psr.pp\n"); dcr = ia64_get_dcr(); dcr &= ~IA64_DCR_PP; ia64_set_dcr(dcr); local_irq_restore(flags); - +#endif /* * We cannot write to pmc[0] to stop counting here, as * that particular instruction might cause an overflow @@ -142,36 +186,47 @@ * when we re-enabled interrupts. When I muck with dcr, * is the irq_save/restore needed? */ - for (i = 0, cnum = 4;i < cmd2; i++, cnum++, cptr++) { - tmp.data = (pmds[smp_processor_id()][i] - + (ia64_get_pmd(cnum) & PERF_OVFL_VAL)); - tmp.counter_num = cnum; - if (copy_to_user(cptr, &tmp, sizeof(tmp))) - return -EFAULT; - //put_user(pmd, &cptr->data); + + + /* XXX: This needs to change to read more than just the counters */ + for (i = 0, cnum = PMU_FIRST_COUNTER;i < count; i++, cnum++, cptr++) { + + tmp.pmu_reg_data = (pmds[smp_processor_id()][i] + + (ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val)); + + tmp.pmu_reg_num = cnum; + + if (copy_to_user(cptr, &tmp, sizeof(tmp))) return -EFAULT; } +#if 0 +/* irrelevant with user monitors */ local_irq_save(flags); __asm__ __volatile__("ssm psr.pp"); dcr = ia64_get_dcr(); dcr |= IA64_DCR_PP; ia64_set_dcr(dcr); local_irq_restore(flags); +#endif break; case STOP_PMCS: ia64_set_pmc(0, 1); ia64_srlz_d(); - for (i = 0; i < MAX_PERF_COUNTER - used_by_system; ++i) + for (i = 0; i < MAX_PERF_COUNTER; ++i) ia64_set_pmc(4+i, 0); - if (!used_by_system) { - local_irq_save(flags); - dcr = ia64_get_dcr(); - dcr &= ~IA64_DCR_PP; - ia64_set_dcr(dcr); - local_irq_restore(flags); - } +#if 0 +/* irrelevant with user monitors */ + local_irq_save(flags); + dcr = ia64_get_dcr(); + dcr &= ~IA64_DCR_PP; + ia64_set_dcr(dcr); + local_irq_restore(flags); + ia64_psr(regs)->up = 0; +#endif + current->thread.flags &= ~(IA64_THREAD_PM_VALID); + break; default: @@ -187,13 +242,21 @@ unsigned long mask, i, cnum, val; mask = ia64_get_pmc(0) >> 4; - for (i = 0, cnum = 4; i < MAX_PERF_COUNTER - used_by_system; cnum++, i++, mask >>= 1) { - val = 0; + for (i = 0, cnum = PMU_FIRST_COUNTER ; i < pmu_conf.max_counters; cnum++, i++, mask >>= 1) { + + + val = mask & 0x1 ? pmu_conf.perf_ovfl_val + 1 : 0; + if (mask & 0x1) - val += PERF_OVFL_VAL + 1; + printk(__FUNCTION__ " PMD%ld overflowed pmd=%lx pmod=%lx\n", cnum, ia64_get_pmd(cnum), pmds[smp_processor_id()][i]); + /* since we got an interrupt, might as well clear every pmd. */ - val += ia64_get_pmd(cnum) & PERF_OVFL_VAL; + val += ia64_get_pmd(cnum) & pmu_conf.perf_ovfl_val; + + printk(__FUNCTION__ " adding val=%lx to pmod[%ld]=%lx \n", val, i, pmds[smp_processor_id()][i]); + pmds[smp_processor_id()][i] += val; + ia64_set_pmd(cnum, 0); } } @@ -212,16 +275,69 @@ name: "perfmon" }; -void +static int +perfmon_proc_info(char *page) +{ + char *p = page; + u64 pmc0 = ia64_get_pmc(0); + + p += sprintf(p, "PMC[0]=%lx\n", pmc0); + + return p - page; +} + +static int +perfmon_read_entry(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + int len = perfmon_proc_info(page); + + if (len <= off+count) *eof = 1; + + *start = page + off; + len -= off; + + if (len>count) len = count; + if (len<0) len = 0; + + return len; +} + +static struct proc_dir_entry *perfmon_dir; + +void __init perfmon_init (void) { + pal_perf_mon_info_u_t pm_info; + u64 pm_buffer[16]; + s64 status; + irq_desc[PERFMON_IRQ].status |= IRQ_PER_CPU; irq_desc[PERFMON_IRQ].handler = &irq_type_ia64_sapic; setup_irq(PERFMON_IRQ, &perfmon_irqaction); ia64_set_pmv(PERFMON_IRQ); ia64_srlz_d(); - printk("Initialized perfmon vector to %u\n",PERFMON_IRQ); + + printk("perfmon: Initialized vector to %u\n",PERFMON_IRQ); + + if ((status=ia64_pal_perf_mon_info(pm_buffer, &pm_info)) != 0) { + printk(__FUNCTION__ " pal call failed (%ld)\n", status); + return; + } + pmu_conf.perf_ovfl_val = perf_ovfl_val = (1L << pm_info.pal_perf_mon_info_s.width) - 1; + + /* XXX need to use PAL instead */ + pmu_conf.max_pmc = 13; + pmu_conf.max_pmd = 17; + pmu_conf.max_counters = pm_info.pal_perf_mon_info_s.generic; + + printk("perfmon: Counters are %d bits\n", pm_info.pal_perf_mon_info_s.width); + printk("perfmon: Maximum counter value 0x%lx\n", pmu_conf.perf_ovfl_val); + + /* + * for now here for debug purposes + */ + perfmon_dir = create_proc_read_entry ("perfmon", 0, 0, perfmon_read_entry, NULL); } void @@ -238,10 +354,13 @@ ia64_set_pmc(0, 1); ia64_srlz_d(); - for (i=0; i< IA64_NUM_PM_REGS - used_by_system ; i++) { - t->pmd[i] = ia64_get_pmd(4+i); + /* + * XXX: this will need to be extended beyong just counters + */ + for (i=0; i< IA64_NUM_PM_REGS; i++) { + t->pmd[i] = ia64_get_pmd(4+i); t->pmod[i] = pmds[smp_processor_id()][i]; - t->pmc[i] = ia64_get_pmc(4+i); + t->pmc[i] = ia64_get_pmc(4+i); } } @@ -250,7 +369,10 @@ { int i; - for (i=0; i< IA64_NUM_PM_REGS - used_by_system ; i++) { + /* + * XXX: this will need to be extended beyong just counters + */ + for (i=0; i< IA64_NUM_PM_REGS ; i++) { ia64_set_pmd(4+i, t->pmd[i]); pmds[smp_processor_id()][i] = t->pmod[i]; ia64_set_pmc(4+i, t->pmc[i]); @@ -262,7 +384,7 @@ #else /* !CONFIG_PERFMON */ asmlinkage unsigned long -sys_perfmonctl (int cmd1, int cmd2, void *ptr) +sys_perfmonctl (int cmd, int count, void *ptr) { return -ENOSYS; } diff -urN linux-davidm/arch/ia64/kernel/process.c linux-2.4.0-test9-lia/arch/ia64/kernel/process.c --- linux-davidm/arch/ia64/kernel/process.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/process.c Wed Oct 4 21:37:10 2000 @@ -294,7 +294,8 @@ * call behavior where scratch registers are preserved across * system calls (unless used by the system call itself). */ -# define THREAD_FLAGS_TO_CLEAR (IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID) +# define THREAD_FLAGS_TO_CLEAR (IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID \ + | IA64_THREAD_PM_VALID) # define THREAD_FLAGS_TO_SET 0 p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) | THREAD_FLAGS_TO_SET); @@ -333,6 +334,17 @@ if (ia64_peek(pt, current, addr, &val) = 0) access_process_vm(current, addr, &val, sizeof(val), 1); + /* + * coredump format: + * r0-r31 + * NaT bits (for r0-r31; bit N = 1 iff rN is a NaT) + * predicate registers (p0-p63) + * b0-b7 + * ip cfm user-mask + * ar.rsc ar.bsp ar.bspstore ar.rnat + * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec + */ + /* r0 is zero */ for (i = 1, mask = (1UL << i); i < 32; ++i) { unw_get_gr(info, i, &dst[i], &nat); @@ -530,6 +542,24 @@ #ifndef CONFIG_SMP if (ia64_get_fpu_owner() = current) ia64_set_fpu_owner(0); +#endif +#ifdef CONFIG_PERFMON + /* stop monitoring */ + if ((current->thread.flags & IA64_THREAD_PM_VALID) != 0) { + /* + * we cannot rely on switch_to() to save the PMU + * context for the last time. There is a possible race + * condition in SMP mode between the child and the + * parent. by explicitly saving the PMU context here + * we garantee no race. this call we also stop + * monitoring + */ + ia64_save_pm_regs(¤t->thread); + /* + * make sure that switch_to() will not save context again + */ + current->thread.flags &= ~IA64_THREAD_PM_VALID; + } #endif } diff -urN linux-davidm/arch/ia64/kernel/ptrace.c linux-2.4.0-test9-lia/arch/ia64/kernel/ptrace.c --- linux-davidm/arch/ia64/kernel/ptrace.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/ptrace.c Wed Oct 4 21:37:31 2000 @@ -617,6 +617,7 @@ struct switch_stack *sw; struct unw_frame_info info; struct pt_regs *pt; + unsigned long pmd_tmp; pt = ia64_task_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); @@ -793,7 +794,11 @@ addr); return -1; } - } else { + } else +#ifdef CONFIG_PERFMON + if (addr < PT_PMD) +#endif + { /* access debug registers */ if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) { @@ -816,6 +821,32 @@ ptr += regnum; } +#ifdef CONFIG_PERFMON + else { + /* + * XXX: will eventually move back to perfmonctl() + */ + unsigned long pmd = (addr - PT_PMD) >> 3; + extern unsigned long perf_ovfl_val; + + /* we just use ptrace to read */ + if (write_access) return -1; + + if (pmd > 3) { + printk("ptrace: rejecting access to PMD[%ld] address 0x%lx\n", pmd, addr); + return -1; + } + + /* + * We always need to mask upper 32bits of pmd because value is random + */ + pmd_tmp = child->thread.pmod[pmd]+(child->thread.pmd[pmd]& perf_ovfl_val); + + /*printk(__FUNCTION__" child=%d reading pmd[%ld]=%lx\n", child->pid, pmd, pmd_tmp);*/ + + ptr = &pmd_tmp; + } +#endif if (write_access) *ptr = *data; else @@ -945,7 +976,12 @@ /* disallow accessing anything else... */ return -1; } - } else { + } else +#ifdef CONFIG_PERFMON + if (addr < PT_PMD) +#endif + { + /* access debug registers */ if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) { @@ -966,6 +1002,33 @@ ptr += regnum; } +#ifdef CONFIG_PERFMON + else { + /* + * XXX: will eventually move back to perfmonctl() + */ + unsigned long pmd = (addr - PT_PMD) >> 3; + extern unsigned long perf_ovfl_val; + + /* we just use ptrace to read */ + if (write_access) return -1; + + if (pmd > 3) { + printk("ptrace: rejecting access to PMD[%ld] address 0x%lx\n", pmd, addr); + return -1; + } + + /* + * We always need to mask upper 32bits of pmd because value is random + */ + pmd_tmp = child->thread.pmod[pmd]+(child->thread.pmd[pmd]& perf_ovfl_val); + + /*printk(__FUNCTION__" child=%d reading pmd[%ld]=%lx\n", child->pid, pmd, pmd_tmp);*/ + + ptr = &pmd_tmp; + } +#endif + if (write_access) *ptr = *data; else @@ -1041,10 +1104,12 @@ ret = -ESRCH; if (!(child->ptrace & PT_PTRACED)) goto out_tsk; + if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) + if (request != PTRACE_KILL && request != PTRACE_PEEKUSR) goto out_tsk; } + if (child->p_pptr != current) goto out_tsk; diff -urN linux-davidm/arch/ia64/kernel/sal.c linux-2.4.0-test9-lia/arch/ia64/kernel/sal.c --- linux-davidm/arch/ia64/kernel/sal.c Thu Aug 24 08:17:30 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/sal.c Wed Oct 4 21:37:41 2000 @@ -34,6 +34,7 @@ } ia64_sal_handler ia64_sal = (ia64_sal_handler) default_handler; +ia64_sal_desc_ptc_t *ia64_ptc_domain_info; const char * ia64_sal_strerror (long status) @@ -125,6 +126,10 @@ #endif ia64_pal_handler_init(__va(ep->pal_proc)); ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp)); + break; + + case SAL_DESC_PTC: + ia64_ptc_domain_info = (ia64_sal_desc_ptc_t *)p; break; case SAL_DESC_AP_WAKEUP: diff -urN linux-davidm/arch/ia64/kernel/setup.c linux-2.4.0-test9-lia/arch/ia64/kernel/setup.c --- linux-davidm/arch/ia64/kernel/setup.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/setup.c Wed Oct 4 21:37:50 2000 @@ -270,6 +270,11 @@ int get_cpuinfo (char *buffer) { +#ifdef CONFIG_SMP +# define lps c->loops_per_sec +#else +# define lps loops_per_sec +#endif char family[32], model[32], features[128], *cp, *p = buffer; struct cpuinfo_ia64 *c; unsigned long mask; @@ -320,7 +325,7 @@ features, c->ppn, c->number, c->proc_freq / 1000000, c->proc_freq % 1000000, c->itc_freq / 1000000, c->itc_freq % 1000000, - ia64_loops_per_sec() / 500000, (ia64_loops_per_sec() / 5000) % 100); + lps / 500000, (lps / 5000) % 100); } return p - buffer; } @@ -416,8 +421,9 @@ * do NOT defer TLB misses, page-not-present, access bit, or * debug faults but kernel code should not rely on any * particular setting of these bits. - */ ia64_set_dcr(IA64_DCR_DR | IA64_DCR_DK | IA64_DCR_DX | IA64_DCR_PP); + */ + ia64_set_dcr(IA64_DCR_DR | IA64_DCR_DK | IA64_DCR_DX ); #ifndef CONFIG_SMP ia64_set_fpu_owner(0); /* initialize ar.k5 */ #endif diff -urN linux-davidm/arch/ia64/kernel/smp.c linux-2.4.0-test9-lia/arch/ia64/kernel/smp.c --- linux-davidm/arch/ia64/kernel/smp.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/smp.c Wed Oct 4 21:38:41 2000 @@ -44,8 +44,8 @@ extern void __init calibrate_delay(void); extern int cpu_idle(void * unused); -extern void _start(void); extern void machine_halt(void); +extern void start_ap(void); extern int cpu_now_booting; /* Used by head.S to find idle task */ extern volatile unsigned long cpu_online_map; /* Bitmap of available cpu's */ @@ -463,46 +463,6 @@ } } -/* - * SAL shoves the AP's here when we start them. Physical mode, no kernel TR, - * no RRs set, better than even chance that psr is bogus. Fix all that and - * call _start. In effect, pretend to be lilo. - * - * Stolen from lilo_start.c. Thanks David! - */ -void -start_ap(void) -{ - unsigned long flags; - - /* - * Install a translation register that identity maps the - * kernel's 256MB page(s). - */ - ia64_clear_ic(flags); - ia64_set_rr( 0, (0x1000 << 8) | (_PAGE_SIZE_1M << 2)); - ia64_set_rr(PAGE_OFFSET, (ia64_rid(0, PAGE_OFFSET) << 8) | (_PAGE_SIZE_256M << 2)); - ia64_srlz_d(); - ia64_itr(0x3, 1, PAGE_OFFSET, - pte_val(mk_pte_phys(0, __pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX))), - _PAGE_SIZE_256M); - ia64_srlz_i(); - - flags = (IA64_PSR_IT | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_DFH | - IA64_PSR_BN); - - asm volatile ("movl r8 = 1f\n" - ";;\n" - "mov cr.ipsr=%0\n" - "mov cr.iip=r8\n" - "mov cr.ifs=r0\n" - ";;\n" - "rfi;;" - "1:\n" - "movl r1 = __gp" :: "r"(flags) : "r8"); - _start(); -} - /* * AP's start using C here. @@ -642,7 +602,7 @@ /* Setup BP mappings */ __cpu_physical_id[0] = hard_smp_processor_id(); - calibrate_delay(); + /* on the BP, the kernel already called calibrate_delay_loop() in init/main.c */ my_cpu_data.loops_per_sec = loops_per_sec; #if 0 smp_tune_scheduling(); diff -urN linux-davidm/arch/ia64/kernel/smpboot.c linux-2.4.0-test9-lia/arch/ia64/kernel/smpboot.c --- linux-davidm/arch/ia64/kernel/smpboot.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/smpboot.c Wed Oct 4 21:38:56 2000 @@ -0,0 +1,76 @@ +/* + * SMP Support + * + * Application processor startup code, moved from smp.c to better support kernel profile + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * SAL shoves the AP's here when we start them. Physical mode, no kernel TR, + * no RRs set, better than even chance that psr is bogus. Fix all that and + * call _start. In effect, pretend to be lilo. + * + * Stolen from lilo_start.c. Thanks David! + */ +void +start_ap(void) +{ + extern void _start (void); + unsigned long flags; + + /* + * Install a translation register that identity maps the + * kernel's 256MB page(s). + */ + ia64_clear_ic(flags); + ia64_set_rr( 0, (0x1000 << 8) | (_PAGE_SIZE_1M << 2)); + ia64_set_rr(PAGE_OFFSET, (ia64_rid(0, PAGE_OFFSET) << 8) | (_PAGE_SIZE_256M << 2)); + ia64_srlz_d(); + ia64_itr(0x3, 1, PAGE_OFFSET, + pte_val(mk_pte_phys(0, __pgprot(__DIRTY_BITS|_PAGE_PL_0|_PAGE_AR_RWX))), + _PAGE_SIZE_256M); + ia64_srlz_i(); + + flags = (IA64_PSR_IT | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_RT | IA64_PSR_DFH | + IA64_PSR_BN); + + asm volatile ("movl r8 = 1f\n" + ";;\n" + "mov cr.ipsr=%0\n" + "mov cr.iip=r8\n" + "mov cr.ifs=r0\n" + ";;\n" + "rfi;;" + "1:\n" + "movl r1 = __gp" :: "r"(flags) : "r8"); + _start(); +} + + diff -urN linux-davidm/arch/ia64/kernel/traps.c linux-2.4.0-test9-lia/arch/ia64/kernel/traps.c --- linux-davidm/arch/ia64/kernel/traps.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/traps.c Wed Oct 4 21:39:28 2000 @@ -254,10 +254,11 @@ * kernel, so set those bits in the mask and set the low volatile * pointer to point to these registers. */ - fp_state.bitmask_low64 = 0xffc0; /* bit6..bit15 */ #ifndef FPSWA_BUG - fp_state.fp_state_low_volatile = ®s->f6; + fp_state.bitmask_low64 = 0x3c0; /* bit 6..9 */ + fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) ®s->f6; #else + fp_state.bitmask_low64 = 0xffc0; /* bit6..bit15 */ f6_15[0] = regs->f6; f6_15[1] = regs->f7; f6_15[2] = regs->f8; diff -urN linux-davidm/arch/ia64/kernel/unwind.c linux-2.4.0-test9-lia/arch/ia64/kernel/unwind.c --- linux-davidm/arch/ia64/kernel/unwind.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/unwind.c Wed Oct 4 21:39:58 2000 @@ -66,7 +66,7 @@ #define UNW_STATS 0 /* WARNING: this disabled interrupts for long time-spans!! */ #if UNW_DEBUG - static long unw_debug_level = 1; + static long unw_debug_level = 255; # define debug(level,format...) if (unw_debug_level > level) printk(format) # define dprintk(format...) printk(format) # define inline @@ -111,7 +111,7 @@ struct unw_table kernel_table; /* hash table that maps instruction pointer to script index: */ - unw_hash_index_t hash[UNW_HASH_SIZE]; + unsigned short hash[UNW_HASH_SIZE]; /* script cache: */ struct unw_script cache[UNW_CACHE_SIZE]; @@ -152,47 +152,47 @@ UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR }, preg_index: { - struct_offset(struct unw_frame_info, pri_unat)/8, /* PRI_UNAT_GR */ - struct_offset(struct unw_frame_info, pri_unat)/8, /* PRI_UNAT_MEM */ - struct_offset(struct unw_frame_info, pbsp)/8, - struct_offset(struct unw_frame_info, bspstore)/8, - struct_offset(struct unw_frame_info, pfs)/8, - struct_offset(struct unw_frame_info, rnat)/8, + struct_offset(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_GR */ + struct_offset(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_MEM */ + struct_offset(struct unw_frame_info, bsp_loc)/8, + struct_offset(struct unw_frame_info, bspstore_loc)/8, + struct_offset(struct unw_frame_info, pfs_loc)/8, + struct_offset(struct unw_frame_info, rnat_loc)/8, struct_offset(struct unw_frame_info, psp)/8, - struct_offset(struct unw_frame_info, rp)/8, + struct_offset(struct unw_frame_info, rp_loc)/8, struct_offset(struct unw_frame_info, r4)/8, struct_offset(struct unw_frame_info, r5)/8, struct_offset(struct unw_frame_info, r6)/8, struct_offset(struct unw_frame_info, r7)/8, - struct_offset(struct unw_frame_info, unat)/8, - struct_offset(struct unw_frame_info, pr)/8, - struct_offset(struct unw_frame_info, lc)/8, - struct_offset(struct unw_frame_info, fpsr)/8, - struct_offset(struct unw_frame_info, b1)/8, - struct_offset(struct unw_frame_info, b2)/8, - struct_offset(struct unw_frame_info, b3)/8, - struct_offset(struct unw_frame_info, b4)/8, - struct_offset(struct unw_frame_info, b5)/8, - struct_offset(struct unw_frame_info, f2)/8, - struct_offset(struct unw_frame_info, f3)/8, - struct_offset(struct unw_frame_info, f4)/8, - struct_offset(struct unw_frame_info, f5)/8, - struct_offset(struct unw_frame_info, fr[16 - 16])/8, - struct_offset(struct unw_frame_info, fr[17 - 16])/8, - struct_offset(struct unw_frame_info, fr[18 - 16])/8, - struct_offset(struct unw_frame_info, fr[19 - 16])/8, - struct_offset(struct unw_frame_info, fr[20 - 16])/8, - struct_offset(struct unw_frame_info, fr[21 - 16])/8, - struct_offset(struct unw_frame_info, fr[22 - 16])/8, - struct_offset(struct unw_frame_info, fr[23 - 16])/8, - struct_offset(struct unw_frame_info, fr[24 - 16])/8, - struct_offset(struct unw_frame_info, fr[25 - 16])/8, - struct_offset(struct unw_frame_info, fr[26 - 16])/8, - struct_offset(struct unw_frame_info, fr[27 - 16])/8, - struct_offset(struct unw_frame_info, fr[28 - 16])/8, - struct_offset(struct unw_frame_info, fr[29 - 16])/8, - struct_offset(struct unw_frame_info, fr[30 - 16])/8, - struct_offset(struct unw_frame_info, fr[31 - 16])/8, + struct_offset(struct unw_frame_info, unat_loc)/8, + struct_offset(struct unw_frame_info, pr_loc)/8, + struct_offset(struct unw_frame_info, lc_loc)/8, + struct_offset(struct unw_frame_info, fpsr_loc)/8, + struct_offset(struct unw_frame_info, b1_loc)/8, + struct_offset(struct unw_frame_info, b2_loc)/8, + struct_offset(struct unw_frame_info, b3_loc)/8, + struct_offset(struct unw_frame_info, b4_loc)/8, + struct_offset(struct unw_frame_info, b5_loc)/8, + struct_offset(struct unw_frame_info, f2_loc)/8, + struct_offset(struct unw_frame_info, f3_loc)/8, + struct_offset(struct unw_frame_info, f4_loc)/8, + struct_offset(struct unw_frame_info, f5_loc)/8, + struct_offset(struct unw_frame_info, fr_loc[16 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[17 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[18 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[19 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[20 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[21 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[22 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[23 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[24 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[25 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[26 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[27 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[28 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[29 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[30 - 16])/8, + struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8, }, hash : { [0 ... UNW_HASH_SIZE - 1] = -1 }, #if UNW_DEBUG @@ -211,6 +211,27 @@ /* Unwind accessors. */ +/* + * Returns offset of rREG in struct pt_regs. + */ +static inline unsigned long +pt_regs_off (unsigned long reg) +{ + unsigned long off =0; + + if (reg >= 1 && reg <= 3) + off = struct_offset(struct pt_regs, r1) + 8*(reg - 1); + else if (reg <= 11) + off = struct_offset(struct pt_regs, r8) + 8*(reg - 8); + else if (reg <= 15) + off = struct_offset(struct pt_regs, r12) + 8*(reg - 12); + else if (reg <= 31) + off = struct_offset(struct pt_regs, r16) + 8*(reg - 16); + else + dprintk("unwind: bad scratch reg r%lu\n", reg); + return off; +} + int unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write) { @@ -251,26 +272,22 @@ } /* fall through */ case UNW_NAT_NONE: + dummy_nat = 0; nat_addr = &dummy_nat; break; - case UNW_NAT_SCRATCH: - if (info->pri_unat) - nat_addr = info->pri_unat; - else - nat_addr = &info->sw->caller_unat; - case UNW_NAT_PRI_UNAT: + case UNW_NAT_MEMSTK: nat_mask = (1UL << ((long) addr & 0x1f8)/8); break; - case UNW_NAT_STACKED: + case UNW_NAT_REGSTK: nat_addr = ia64_rse_rnat_addr(addr); if ((unsigned long) addr < info->regstk.limit || (unsigned long) addr >= info->regstk.top) { dprintk("unwind: %p outside of regstk " - "[0x%lx-0x%lx)\n", addr, - (void *) info->regstk.limit, + "[0x%lx-0x%lx)\n", (void *) addr, + info->regstk.limit, info->regstk.top); return -1; } @@ -290,18 +307,11 @@ pt = (struct pt_regs *) info->psp - 1; else pt = (struct pt_regs *) info->sp - 1; - if (regnum <= 3) - addr = &pt->r1 + (regnum - 1); - else if (regnum <= 11) - addr = &pt->r8 + (regnum - 8); - else if (regnum <= 15) - addr = &pt->r12 + (regnum - 12); - else - addr = &pt->r16 + (regnum - 16); - if (info->pri_unat) - nat_addr = info->pri_unat; + addr = (unsigned long *) ((long) pt + pt_regs_off(regnum)); + if (info->pri_unat_loc) + nat_addr = info->pri_unat_loc; else - nat_addr = &info->sw->caller_unat; + nat_addr = &info->sw->ar_unat; nat_mask = (1UL << ((long) addr & 0x1f8)/8); } } else { @@ -321,7 +331,10 @@ if (write) { *addr = *val; - *nat_addr = (*nat_addr & ~nat_mask) | nat_mask; + if (*nat) + *nat_addr |= nat_mask; + else + *nat_addr &= ~nat_mask; } else { *val = *addr; *nat = (*nat_addr & nat_mask) != 0; @@ -347,7 +360,7 @@ /* preserved: */ case 1: case 2: case 3: case 4: case 5: - addr = *(&info->b1 + (regnum - 1)); + addr = *(&info->b1_loc + (regnum - 1)); if (!addr) addr = &info->sw->b1 + (regnum - 1); break; @@ -380,7 +393,7 @@ pt = (struct pt_regs *) info->sp - 1; if (regnum <= 5) { - addr = *(&info->f2 + (regnum - 2)); + addr = *(&info->f2_loc + (regnum - 2)); if (!addr) addr = &info->sw->f2 + (regnum - 2); } else if (regnum <= 15) { @@ -389,7 +402,7 @@ else addr = &info->sw->f10 + (regnum - 10); } else if (regnum <= 31) { - addr = info->fr[regnum - 16]; + addr = info->fr_loc[regnum - 16]; if (!addr) addr = &info->sw->f16 + (regnum - 16); } else { @@ -422,52 +435,53 @@ switch (regnum) { case UNW_AR_BSP: - addr = info->pbsp; + addr = info->bsp_loc; if (!addr) addr = &info->sw->ar_bspstore; break; case UNW_AR_BSPSTORE: - addr = info->bspstore; + addr = info->bspstore_loc; if (!addr) addr = &info->sw->ar_bspstore; break; case UNW_AR_PFS: - addr = info->pfs; + addr = info->pfs_loc; if (!addr) addr = &info->sw->ar_pfs; break; case UNW_AR_RNAT: - addr = info->rnat; + addr = info->rnat_loc; if (!addr) addr = &info->sw->ar_rnat; break; case UNW_AR_UNAT: - addr = info->unat; + addr = info->unat_loc; if (!addr) addr = &info->sw->ar_unat; break; case UNW_AR_LC: - addr = info->lc; + addr = info->lc_loc; if (!addr) addr = &info->sw->ar_lc; break; case UNW_AR_EC: - if (!info->cfm) + if (!info->cfm_loc) return -1; if (write) - *info->cfm = (*info->cfm & ~(0x3fUL << 52)) | ((*val & 0x3f) << 52); + *info->cfm_loc + (*info->cfm_loc & ~(0x3fUL << 52)) | ((*val & 0x3f) << 52); else - *val = (*info->cfm >> 52) & 0x3f; + *val = (*info->cfm_loc >> 52) & 0x3f; return 0; case UNW_AR_FPSR: - addr = info->fpsr; + addr = info->fpsr_loc; if (!addr) addr = &info->sw->ar_fpsr; break; @@ -497,7 +511,7 @@ { unsigned long *addr; - addr = info->pr; + addr = info->pr_loc; if (!addr) addr = &info->sw->pr; @@ -609,9 +623,8 @@ int i; /* - * First, resolve implicit register save locations - * (see Section "11.4.2.3 Rules for Using Unwind - * Descriptors", rule 3): + * First, resolve implicit register save locations (see Section "11.4.2.3 Rules + * for Using Unwind Descriptors", rule 3): */ for (i = 0; i < (int) sizeof(unw.save_order)/sizeof(unw.save_order[0]); ++i) { reg = sr->curr.reg + unw.save_order[i]; @@ -1049,16 +1062,16 @@ static inline unw_hash_index_t hash (unsigned long ip) { -# define magic 0x9e3779b97f4a7c16 /* (sqrt(5)/2-1)*2^64 */ +# define magic 0x9e3779b97f4a7c16 /* based on (sqrt(5)/2-1)*2^64 */ return (ip >> 4)*magic >> (64 - UNW_LOG_HASH_SIZE); } static inline long -cache_match (struct unw_script *script, unsigned long ip, unsigned long pr_val) +cache_match (struct unw_script *script, unsigned long ip, unsigned long pr) { read_lock(&script->lock); - if ((ip) = (script)->ip && (((pr_val) ^ (script)->pr_val) & (script)->pr_mask) = 0) + if (ip = script->ip && ((pr ^ script->pr_val) & script->pr_mask) = 0) /* keep the read lock... */ return 1; read_unlock(&script->lock); @@ -1069,21 +1082,26 @@ script_lookup (struct unw_frame_info *info) { struct unw_script *script = unw.cache + info->hint; - unsigned long ip, pr_val; + unsigned short index; + unsigned long ip, pr; STAT(++unw.stat.cache.lookups); ip = info->ip; - pr_val = info->pr_val; + pr = info->pr; - if (cache_match(script, ip, pr_val)) { + if (cache_match(script, ip, pr)) { STAT(++unw.stat.cache.hinted_hits); return script; } - script = unw.cache + unw.hash[hash(ip)]; + index = unw.hash[hash(ip)]; + if (index >= UNW_CACHE_SIZE) + return 0; + + script = unw.cache + index; while (1) { - if (cache_match(script, ip, pr_val)) { + if (cache_match(script, ip, pr)) { /* update hint; no locking required as single-word writes are atomic */ STAT(++unw.stat.cache.normal_hits); unw.cache[info->prev_script].hint = script - unw.cache; @@ -1103,8 +1121,8 @@ script_new (unsigned long ip) { struct unw_script *script, *prev, *tmp; + unw_hash_index_t index; unsigned long flags; - unsigned char index; unsigned short head; STAT(++unw.stat.script.news); @@ -1137,22 +1155,24 @@ unw.lru_tail = head; /* remove the old script from the hash table (if it's there): */ - index = hash(script->ip); - tmp = unw.cache + unw.hash[index]; - prev = 0; - while (1) { - if (tmp = script) { - if (prev) - prev->coll_chain = tmp->coll_chain; - else - unw.hash[index] = tmp->coll_chain; - break; - } else - prev = tmp; - if (tmp->coll_chain >= UNW_CACHE_SIZE) + if (script->ip) { + index = hash(script->ip); + tmp = unw.cache + unw.hash[index]; + prev = 0; + while (1) { + if (tmp = script) { + if (prev) + prev->coll_chain = tmp->coll_chain; + else + unw.hash[index] = tmp->coll_chain; + break; + } else + prev = tmp; + if (tmp->coll_chain >= UNW_CACHE_SIZE) /* old script wasn't in the hash-table */ - break; - tmp = unw.cache + tmp->coll_chain; + break; + tmp = unw.cache + tmp->coll_chain; + } } /* enter new script in the hash table */ @@ -1202,19 +1222,17 @@ struct unw_reg_info *r = sr->curr.reg + i; enum unw_insn_opcode opc; struct unw_insn insn; - unsigned long val; + unsigned long val = 0; switch (r->where) { case UNW_WHERE_GR: if (r->val >= 32) { /* register got spilled to a stacked register */ opc = UNW_INSN_SETNAT_TYPE; - val = UNW_NAT_STACKED; - } else { + val = UNW_NAT_REGSTK; + } else /* register got spilled to a scratch register */ - opc = UNW_INSN_SETNAT_TYPE; - val = UNW_NAT_SCRATCH; - } + opc = UNW_INSN_SETNAT_MEMSTK; break; case UNW_WHERE_FR: @@ -1229,8 +1247,7 @@ case UNW_WHERE_PSPREL: case UNW_WHERE_SPREL: - opc = UNW_INSN_SETNAT_PRI_UNAT; - val = 0; + opc = UNW_INSN_SETNAT_MEMSTK; break; default: @@ -1271,18 +1288,8 @@ } val = unw.preg_index[UNW_REG_R4 + (rval - 4)]; } else { - opc = UNW_INSN_LOAD_SPREL; - val = -sizeof(struct pt_regs); - if (rval >= 1 && rval <= 3) - val += struct_offset(struct pt_regs, r1) + 8*(rval - 1); - else if (rval <= 11) - val += struct_offset(struct pt_regs, r8) + 8*(rval - 8); - else if (rval <= 15) - val += struct_offset(struct pt_regs, r12) + 8*(rval - 12); - else if (rval <= 31) - val += struct_offset(struct pt_regs, r16) + 8*(rval - 16); - else - dprintk("unwind: bad scratch reg r%lu\n", rval); + opc = UNW_INSN_ADD_SP; + val = -sizeof(struct pt_regs) + pt_regs_off(rval); } break; @@ -1292,7 +1299,7 @@ else if (rval >= 16 && rval <= 31) val = unw.preg_index[UNW_REG_F16 + (rval - 16)]; else { - opc = UNW_INSN_LOAD_SPREL; + opc = UNW_INSN_ADD_SP; val = -sizeof(struct pt_regs); if (rval <= 9) val += struct_offset(struct pt_regs, f6) + 16*(rval - 6); @@ -1305,7 +1312,7 @@ if (rval >= 1 && rval <= 5) val = unw.preg_index[UNW_REG_B1 + (rval - 1)]; else { - opc = UNW_INSN_LOAD_SPREL; + opc = UNW_INSN_ADD_SP; val = -sizeof(struct pt_regs); if (rval = 0) val += struct_offset(struct pt_regs, b0); @@ -1317,11 +1324,11 @@ break; case UNW_WHERE_SPREL: - opc = UNW_INSN_LOAD_SPREL; + opc = UNW_INSN_ADD_SP; break; case UNW_WHERE_PSPREL: - opc = UNW_INSN_LOAD_PSPREL; + opc = UNW_INSN_ADD_PSP; break; default: @@ -1334,6 +1341,18 @@ script_emit(script, insn); if (need_nat_info) emit_nat_info(sr, i, script); + + if (i = UNW_REG_PSP) { + /* + * info->psp must contain the _value_ of the previous + * sp, not it's save location. We get this by + * dereferencing the value we just stored in + * info->psp: + */ + insn.opc = UNW_INSN_LOAD; + insn.dst = insn.val = unw.preg_index[UNW_REG_PSP]; + script_emit(script, insn); + } } static inline struct unw_table_entry * @@ -1382,7 +1401,7 @@ memset(&sr, 0, sizeof(sr)); for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) r->when = UNW_WHEN_NEVER; - sr.pr_val = info->pr_val; + sr.pr_val = info->pr; script = script_new(ip); if (!script) { @@ -1451,8 +1470,8 @@ } #if UNW_DEBUG - printk ("unwind: state record for func 0x%lx, t=%u:\n", - table->segment_base + e->start_offset, sr.when_target); + printk("unwind: state record for func 0x%lx, t=%u:\n", + table->segment_base + e->start_offset, sr.when_target); for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) { if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) { printk(" %s <- ", unw.preg_name[r - sr.curr.reg]); @@ -1467,7 +1486,7 @@ break; default: printk("BADWHERE(%d)", r->where); break; } - printk ("\t\t%d\n", r->when); + printk("\t\t%d\n", r->when); } } #endif @@ -1476,13 +1495,17 @@ /* translate state record into unwinder instructions: */ - if (sr.curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE - && sr.when_target > sr.curr.reg[UNW_REG_PSP].when && sr.curr.reg[UNW_REG_PSP].val != 0) - { + /* + * First, set psp if we're dealing with a fixed-size frame; + * subsequent instructions may depend on this value. + */ + if (sr.when_target > sr.curr.reg[UNW_REG_PSP].when + && (sr.curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE) + && sr.curr.reg[UNW_REG_PSP].val != 0) { /* new psp is sp plus frame size */ insn.opc = UNW_INSN_ADD; - insn.dst = unw.preg_index[UNW_REG_PSP]; - insn.val = sr.curr.reg[UNW_REG_PSP].val; + insn.dst = struct_offset(struct unw_frame_info, psp)/8; + insn.val = sr.curr.reg[UNW_REG_PSP].val; /* frame size */ script_emit(script, insn); } @@ -1566,23 +1589,34 @@ val); break; - case UNW_INSN_LOAD_PSPREL: + case UNW_INSN_ADD_PSP: s[dst] = state->psp + val; break; - case UNW_INSN_LOAD_SPREL: + case UNW_INSN_ADD_SP: s[dst] = state->sp + val; break; - case UNW_INSN_SETNAT_PRI_UNAT: - if (!state->pri_unat) - state->pri_unat = &state->sw->caller_unat; - s[dst+1] = ((*state->pri_unat - s[dst]) << 32) | UNW_NAT_PRI_UNAT; + case UNW_INSN_SETNAT_MEMSTK: + if (!state->pri_unat_loc) + state->pri_unat_loc = &state->sw->ar_unat; + /* register off. is a multiple of 8, so the least 3 bits (type) are 0 */ + s[dst+1] = (*state->pri_unat_loc - s[dst]) | UNW_NAT_MEMSTK; break; case UNW_INSN_SETNAT_TYPE: s[dst+1] = val; break; + + case UNW_INSN_LOAD: +#if UNW_DEBUG + if ((s[val] & (my_cpu_data.unimpl_va_mask | 0x7)) || s[val] < TASK_SIZE) { + debug(1, "unwind: rejecting bad psp=0x%lx\n", s[val]); + break; + } +#endif + s[dst] = *(unsigned long *) s[val]; + break; } } STAT(unw.stat.script.run_time += ia64_get_itc() - start); @@ -1591,13 +1625,14 @@ lazy_init: off = unw.sw_off[val]; s[val] = (unsigned long) state->sw + off; - if (off >= struct_offset (struct unw_frame_info, r4) - && off <= struct_offset (struct unw_frame_info, r7)) + if (off >= struct_offset(struct switch_stack, r4) + && off <= struct_offset(struct switch_stack, r7)) /* - * We're initializing a general register: init NaT info, too. Note that we - * rely on the fact that call_unat is the first field in struct switch_stack: + * We're initializing a general register: init NaT info, too. Note that + * the offset is a multiple of 8 which gives us the 3 bits needed for + * the type field. */ - s[val+1] = (-off << 32) | UNW_NAT_PRI_UNAT; + s[val+1] = (struct_offset(struct switch_stack, ar_unat) - off) | UNW_NAT_MEMSTK; goto redo; } @@ -1610,7 +1645,7 @@ if ((info->ip & (my_cpu_data.unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) { /* don't let obviously bad addresses pollute the cache */ debug(1, "unwind: rejecting bad ip=0x%lx\n", info->ip); - info->rp = 0; + info->rp_loc = 0; return -1; } @@ -1651,12 +1686,12 @@ prev_bsp = info->bsp; /* restore the ip */ - if (!info->rp) { + if (!info->rp_loc) { debug(1, "unwind: failed to locate return link (ip=0x%lx)!\n", info->ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } - ip = info->ip = *info->rp; + ip = info->ip = *info->rp_loc; if (ip < GATE_ADDR + PAGE_SIZE) { /* * We don't have unwind info for the gate page, so we consider that part @@ -1668,23 +1703,23 @@ } /* restore the cfm: */ - if (!info->pfs) { + if (!info->pfs_loc) { dprintk("unwind: failed to locate ar.pfs!\n"); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } - info->cfm = info->pfs; + info->cfm_loc = info->pfs_loc; /* restore the bsp: */ - pr = info->pr_val; + pr = info->pr; num_regs = 0; if ((info->flags & UNW_FLAG_INTERRUPT_FRAME)) { if ((pr & (1UL << pNonSys)) != 0) - num_regs = *info->cfm & 0x7f; /* size of frame */ - info->pfs + num_regs = *info->cfm_loc & 0x7f; /* size of frame */ + info->pfs_loc (unsigned long *) (info->sp + 16 + struct_offset(struct pt_regs, ar_pfs)); } else - num_regs = (*info->cfm >> 7) & 0x7f; /* size of locals */ + num_regs = (*info->cfm_loc >> 7) & 0x7f; /* size of locals */ info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs); if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) { dprintk("unwind: bsp (0x%lx) out of range [0x%lx-0x%lx]\n", @@ -1697,7 +1732,7 @@ info->sp = info->psp; if (info->sp < info->memstk.top || info->sp > info->memstk.limit) { dprintk("unwind: sp (0x%lx) out of range [0x%lx-0x%lx]\n", - info->sp, info->regstk.top, info->regstk.limit); + info->sp, info->memstk.top, info->memstk.limit); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1708,8 +1743,11 @@ return -1; } + /* as we unwind, the saved ar.unat becomes the primary unat: */ + info->pri_unat_loc = info->unat_loc; + /* finally, restore the predicates: */ - unw_get_pr(info, &info->pr_val); + unw_get_pr(info, &info->pr); retval = find_save_locs(info); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); @@ -1776,11 +1814,11 @@ info->task = t; info->sw = sw; info->sp = info->psp = (unsigned long) (sw + 1) - 16; - info->cfm = &sw->ar_pfs; - sol = (*info->cfm >> 7) & 0x7f; + info->cfm_loc = &sw->ar_pfs; + sol = (*info->cfm_loc >> 7) & 0x7f; info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol); info->ip = sw->b0; - info->pr_val = sw->pr; + info->pr = sw->pr; find_save_locs(info); STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags)); @@ -1811,7 +1849,7 @@ info->regstk.top = top; info->sw = sw; info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol); - info->cfm = &sw->ar_pfs; + info->cfm_loc = &sw->ar_pfs; info->ip = sw->b0; #endif } @@ -1848,7 +1886,7 @@ info->regstk.top = top; info->sw = sw; info->bsp = (unsigned long) ia64_rse_skip_regs(bsp, -sof); - info->cfm = ®s->cr_ifs; + info->cfm_loc = ®s->cr_ifs; info->ip = regs->cr_iip; #endif } @@ -1884,7 +1922,7 @@ int unw_unwind (struct unw_frame_info *info) { - unsigned long sol, cfm = *info->cfm; + unsigned long sol, cfm = *info->cfm_loc; int is_nat; sol = (cfm >> 7) & 0x7f; /* size of locals */ @@ -1906,7 +1944,7 @@ /* reject let obviously bad addresses */ return -1; - info->cfm = ia64_rse_skip_regs((unsigned long *) info->bsp, sol - 1); + info->cfm_loc = ia64_rse_skip_regs((unsigned long *) info->bsp, sol - 1); cfm = read_reg(info, sol - 1, &is_nat); if (is_nat) return -1; @@ -2073,9 +2111,9 @@ for (i = UNW_REG_F16, off = SW(F16); i <= UNW_REG_F31; ++i, off += 16) unw.sw_off[unw.preg_index[i]] = off; - unw.cache[0].coll_chain = -1; - for (i = 1; i < UNW_CACHE_SIZE; ++i) { - unw.cache[i].lru_chain = (i - 1); + for (i = 0; i < UNW_CACHE_SIZE; ++i) { + if (i > 0) + unw.cache[i].lru_chain = (i - 1); unw.cache[i].coll_chain = -1; unw.cache[i].lock = RW_LOCK_UNLOCKED; } diff -urN linux-davidm/arch/ia64/kernel/unwind_i.h linux-2.4.0-test9-lia/arch/ia64/kernel/unwind_i.h --- linux-davidm/arch/ia64/kernel/unwind_i.h Thu Jun 22 07:09:44 2000 +++ linux-2.4.0-test9-lia/arch/ia64/kernel/unwind_i.h Wed Oct 4 21:40:28 2000 @@ -115,21 +115,21 @@ enum unw_nat_type { UNW_NAT_NONE, /* NaT not represented */ UNW_NAT_VAL, /* NaT represented by NaT value (fp reg) */ - UNW_NAT_PRI_UNAT, /* NaT value is in unat word at offset OFF */ - UNW_NAT_SCRATCH, /* NaT value is in scratch.pri_unat */ - UNW_NAT_STACKED /* NaT is in rnat */ + UNW_NAT_MEMSTK, /* NaT value is in unat word at offset OFF */ + UNW_NAT_REGSTK /* NaT is in rnat */ }; enum unw_insn_opcode { UNW_INSN_ADD, /* s[dst] += val */ + UNW_INSN_ADD_PSP, /* s[dst] = (s.psp + val) */ + UNW_INSN_ADD_SP, /* s[dst] = (s.sp + val) */ UNW_INSN_MOVE, /* s[dst] = s[val] */ UNW_INSN_MOVE2, /* s[dst] = s[val]; s[dst+1] = s[val+1] */ UNW_INSN_MOVE_STACKED, /* s[dst] = ia64_rse_skip(*s.bsp, val) */ - UNW_INSN_LOAD_PSPREL, /* s[dst] = *(*s.psp + 8*val) */ - UNW_INSN_LOAD_SPREL, /* s[dst] = *(*s.sp + 8*val) */ - UNW_INSN_SETNAT_PRI_UNAT, /* s[dst+1].nat.type = PRI_UNAT; + UNW_INSN_SETNAT_MEMSTK, /* s[dst+1].nat.type = MEMSTK; s[dst+1].nat.off = *s.pri_unat - s[dst] */ - UNW_INSN_SETNAT_TYPE /* s[dst+1].nat.type = val */ + UNW_INSN_SETNAT_TYPE, /* s[dst+1].nat.type = val */ + UNW_INSN_LOAD /* s[dst] = *s[val] */ }; struct unw_insn { diff -urN linux-davidm/arch/ia64/lib/Makefile linux-2.4.0-test9-lia/arch/ia64/lib/Makefile --- linux-davidm/arch/ia64/lib/Makefile Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/arch/ia64/lib/Makefile Wed Oct 4 21:40:41 2000 @@ -7,7 +7,8 @@ L_TARGET = lib.a -L_OBJS = __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \ +L_OBJS = __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ + __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \ checksum.o clear_page.o csum_partial_copy.o copy_page.o \ copy_user.o clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o \ flush.o do_csum.o @@ -18,20 +19,33 @@ LX_OBJS = io.o -IGNORE_FLAGS_OBJS = __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o +IGNORE_FLAGS_OBJS = __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ + __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o $(L_TARGET): -__divdi3.o: idiv.S +__divdi3.o: idiv64.S $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -o $@ $< -__udivdi3.o: idiv.S +__udivdi3.o: idiv64.S $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -DUNSIGNED -c -o $@ $< -__moddi3.o: idiv.S +__moddi3.o: idiv64.S $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -DMODULO -c -o $@ $< -__umoddi3.o: idiv.S +__umoddi3.o: idiv64.S + $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -DMODULO -DUNSIGNED -c -o $@ $< + +__divsi3.o: idiv32.S + $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -o $@ $< + +__udivsi3.o: idiv32.S + $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -DUNSIGNED -c -o $@ $< + +__modsi3.o: idiv32.S + $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -DMODULO -c -o $@ $< + +__umodsi3.o: idiv32.S $(CC) $(AFLAGS) $(AFLAGS_KERNEL) -c -DMODULO -DUNSIGNED -c -o $@ $< include $(TOPDIR)/Rules.make diff -urN linux-davidm/arch/ia64/lib/idiv.S linux-2.4.0-test9-lia/arch/ia64/lib/idiv.S --- linux-davidm/arch/ia64/lib/idiv.S Wed Aug 2 18:54:02 2000 +++ linux-2.4.0-test9-lia/arch/ia64/lib/idiv.S Wed Dec 31 16:00:00 1969 @@ -1,98 +0,0 @@ -/* - * Integer division routine. - * - * Copyright (C) 1999-2000 Hewlett-Packard Co - * Copyright (C) 1999-2000 David Mosberger-Tang - */ - -#include - -/* - * Compute a 64-bit unsigned integer quotient. - * - * Use reciprocal approximation and Newton-Raphson iteration to compute the - * quotient. frcpa gives 8.6 significant bits, so we need 3 iterations - * to get more than the 64 bits of precision that we need for DImode. - * - * Must use max precision for the reciprocal computations to get 64 bits of - * precision. - * - * r32 holds the dividend. r33 holds the divisor. - */ - -#ifdef MODULO -# define OP mod -#else -# define OP div -#endif - -#ifdef UNSIGNED -# define SGN u -# define INT_TO_FP(a,b) fcvt.xuf.s1 a=b -# define FP_TO_INT(a,b) fcvt.fxu.trunc.s1 a=b -#else -# define SGN -# define INT_TO_FP(a,b) fcvt.xf a=b -# define FP_TO_INT(a,b) fcvt.fx.trunc.s1 a=b -#endif - -#define PASTE1(a,b) a##b -#define PASTE(a,b) PASTE1(a,b) -#define NAME PASTE(PASTE(__,SGN),PASTE(OP,di3)) - -GLOBAL_ENTRY(NAME) - UNW(.prologue) - .regstk 2,0,0,0 - // Transfer inputs to FP registers. - setf.sig f8 = in0 - setf.sig f9 = in1 - UNW(.fframe 16) - UNW(.save.f 0x20) - stf.spill [sp] = f17,-16 - - // Convert the inputs to FP, to avoid FP software-assist faults. - INT_TO_FP(f8, f8) - ;; - - UNW(.save.f 0x10) - stf.spill [sp] = f16 - UNW(.body) - INT_TO_FP(f9, f9) - ;; - frcpa.s1 f17, p6 = f8, f9 // y = frcpa(b) - ;; - /* - * This is the magic algorithm described in Section 8.6.2 of "IA-64 - * and Elementary Functions" by Peter Markstein; HP Professional Books - * (http://www.hp.com/go/retailbooks/) - */ -(p6) fmpy.s1 f7 = f8, f17 // q = a*y -(p6) fnma.s1 f6 = f9, f17, f1 // e = -b*y + 1 - ;; -(p6) fma.s1 f16 = f7, f6, f7 // q1 = q*e + q -(p6) fmpy.s1 f7 = f6, f6 // e1 = e*e - ;; -(p6) fma.s1 f16 = f16, f7, f16 // q2 = q1*e1 + q1 -(p6) fma.s1 f6 = f17, f6, f17 // y1 = y*e + y - ;; -(p6) fma.s1 f6 = f6, f7, f6 // y2 = y1*e1 + y1 -(p6) fnma.s1 f7 = f9, f16, f8 // r = -b*q2 + a - ;; -(p6) fma.s1 f17 = f7, f6, f16 // q3 = r*y2 + q2 - ;; -#ifdef MODULO - FP_TO_INT(f17, f17) // round quotient to an unsigned integer - ;; - INT_TO_FP(f17, f17) // renormalize - ;; - fnma.s1 f17 = f17, f9, f8 // compute remainder - ;; -#endif - UNW(.restore sp) - ldf.fill f16 = [sp], 16 - FP_TO_INT(f8, f17) // round result to an (unsigned) integer - ;; - ldf.fill f17 = [sp] - getf.sig r8 = f8 // transfer result to result register - br.ret.sptk rp -END(NAME) diff -urN linux-davidm/arch/ia64/lib/idiv32.S linux-2.4.0-test9-lia/arch/ia64/lib/idiv32.S --- linux-davidm/arch/ia64/lib/idiv32.S Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test9-lia/arch/ia64/lib/idiv32.S Wed Oct 4 21:41:02 2000 @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2000 Hewlett-Packard Co + * Copyright (C) 2000 David Mosberger-Tang + * + * 32-bit integer division. + * + * This code is based on the application note entitled "Divide, Square Root + * and Remainder Algorithms for the IA-64 Architecture". This document + * is available as Intel document number 248725-002 or via the web at + * http://developer.intel.com/software/opensource/numerics/ + * + * For more details on the theory behind these algorithms, see "IA-64 + * and Elementary Functions" by Peter Markstein; HP Professional Books + * (http://www.hp.com/go/retailbooks/) + */ + +#include + +#ifdef MODULO +# define OP mod +#else +# define OP div +#endif + +#ifdef UNSIGNED +# define SGN u +# define EXTEND zxt4 +# define INT_TO_FP(a,b) fcvt.xuf.s1 a=b +# define FP_TO_INT(a,b) fcvt.fxu.trunc.s1 a=b +#else +# define SGN +# define EXTEND sxt4 +# define INT_TO_FP(a,b) fcvt.xf a=b +# define FP_TO_INT(a,b) fcvt.fx.trunc.s1 a=b +#endif + +#define PASTE1(a,b) a##b +#define PASTE(a,b) PASTE1(a,b) +#define NAME PASTE(PASTE(__,SGN),PASTE(OP,si3)) + +GLOBAL_ENTRY(NAME) + .regstk 2,0,0,0 + // Transfer inputs to FP registers. + mov r2 = 0xffdd // r2 = -34 + 65535 (fp reg format bias) + EXTEND in0 = in0 // in0 = a + EXTEND in1 = in1 // in1 = b + ;; + setf.sig f8 = in0 + setf.sig f9 = in1 +#ifdef MODULO + sub in1 = r0, in1 // in1 = -b +#endif + ;; + // Convert the inputs to FP, to avoid FP software-assist faults. + INT_TO_FP(f8, f8) + INT_TO_FP(f9, f9) + ;; + setf.exp f7 = r2 // f7 = 2^-34 + frcpa.s1 f6, p6 = f8, f9 // y0 = frcpa(b) + ;; +(p6) fmpy.s1 f8 = f8, f6 // q0 = a*y0 +(p6) fnma.s1 f6 = f9, f6, f1 // e0 = -b*y0 + 1 + ;; +#ifdef MODULO + setf.sig f9 = in1 // f9 = -b +#endif +(p6) fma.s1 f8 = f6, f8, f8 // q1 = e0*q0 + q0 +(p6) fma.s1 f6 = f6, f6, f7 // e1 = e0*e0 + 2^-34 + ;; +#ifdef MODULO + setf.sig f7 = in0 +#endif +(p6) fma.s1 f6 = f6, f8, f8 // q2 = e1*q1 + q1 + ;; + FP_TO_INT(f6, f6) // q = trunc(q2) + ;; +#ifdef MODULO + xma.l f6 = f6, f9, f7 // r = q*(-b) + a + ;; +#endif + getf.sig r8 = f6 // transfer result to result register + br.ret.sptk rp +END(NAME) diff -urN linux-davidm/arch/ia64/lib/idiv64.S linux-2.4.0-test9-lia/arch/ia64/lib/idiv64.S --- linux-davidm/arch/ia64/lib/idiv64.S Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test9-lia/arch/ia64/lib/idiv64.S Wed Oct 4 21:41:04 2000 @@ -0,0 +1,92 @@ +/* + * Copyright (C) 1999-2000 Hewlett-Packard Co + * Copyright (C) 1999-2000 David Mosberger-Tang + * + * 64-bit integer division. + * + * This code is based on the application note entitled "Divide, Square Root + * and Remainder Algorithms for the IA-64 Architecture". This document + * is available as Intel document number 248725-002 or via the web at + * http://developer.intel.com/software/opensource/numerics/ + * + * For more details on the theory behind these algorithms, see "IA-64 + * and Elementary Functions" by Peter Markstein; HP Professional Books + * (http://www.hp.com/go/retailbooks/) + */ + +#include + +#ifdef MODULO +# define OP mod +#else +# define OP div +#endif + +#ifdef UNSIGNED +# define SGN u +# define INT_TO_FP(a,b) fcvt.xuf.s1 a=b +# define FP_TO_INT(a,b) fcvt.fxu.trunc.s1 a=b +#else +# define SGN +# define INT_TO_FP(a,b) fcvt.xf a=b +# define FP_TO_INT(a,b) fcvt.fx.trunc.s1 a=b +#endif + +#define PASTE1(a,b) a##b +#define PASTE(a,b) PASTE1(a,b) +#define NAME PASTE(PASTE(__,SGN),PASTE(OP,di3)) + +GLOBAL_ENTRY(NAME) + UNW(.prologue) + .regstk 2,0,0,0 + // Transfer inputs to FP registers. + setf.sig f8 = in0 + setf.sig f9 = in1 + UNW(.fframe 16) + UNW(.save.f 0x20) + stf.spill [sp] = f17,-16 + + // Convert the inputs to FP, to avoid FP software-assist faults. + INT_TO_FP(f8, f8) + ;; + + UNW(.save.f 0x10) + stf.spill [sp] = f16 + UNW(.body) + INT_TO_FP(f9, f9) + ;; + frcpa.s1 f17, p6 = f8, f9 // y0 = frcpa(b) + ;; +(p6) fmpy.s1 f7 = f8, f17 // q0 = a*y0 +(p6) fnma.s1 f6 = f9, f17, f1 // e0 = -b*y0 + 1 + ;; +(p6) fma.s1 f16 = f7, f6, f7 // q1 = q0*e0 + q0 +(p6) fmpy.s1 f7 = f6, f6 // e1 = e0*e0 + ;; +#ifdef MODULO + sub in1 = r0, in1 // in1 = -b +#endif +(p6) fma.s1 f16 = f16, f7, f16 // q2 = q1*e1 + q1 +(p6) fma.s1 f6 = f17, f6, f17 // y1 = y0*e0 + y0 + ;; +(p6) fma.s1 f6 = f6, f7, f6 // y2 = y1*e1 + y1 +(p6) fnma.s1 f7 = f9, f16, f8 // r = -b*q2 + a + ;; +#ifdef MODULO + setf.sig f8 = in0 // f8 = a + setf.sig f9 = in1 // f9 = -b +#endif +(p6) fma.s1 f17 = f7, f6, f16 // q3 = r*y2 + q2 + ;; + UNW(.restore sp) + ldf.fill f16 = [sp], 16 + FP_TO_INT(f17, f17) // q = trunc(q3) + ;; +#ifdef MODULO + xma.l f17 = f17, f9, f8 // r = q*(-b) + a + ;; +#endif + getf.sig r8 = f17 // transfer result to result register + ldf.fill f17 = [sp] + br.ret.sptk rp +END(NAME) diff -urN linux-davidm/arch/ia64/mm/init.c linux-2.4.0-test9-lia/arch/ia64/mm/init.c --- linux-davidm/arch/ia64/mm/init.c Thu Aug 24 08:17:30 2000 +++ linux-2.4.0-test9-lia/arch/ia64/mm/init.c Wed Oct 4 23:03:06 2000 @@ -357,6 +357,7 @@ panic("mm/init: overlap between virtually mapped linear page table and " "mapped kernel space!"); pta = POW2(61) - POW2(impl_va_msb); +#ifndef CONFIG_DISABLE_VHPT /* * Set the (virtually mapped linear) page table address. Bit * 8 selects between the short and long format, bits 2-7 the @@ -364,6 +365,9 @@ * enabled. */ ia64_set_pta(pta | (0<<8) | ((3*(PAGE_SHIFT-3)+3)<<2) | 1); +#else + ia64_set_pta(pta | (0<<8) | ((3*(PAGE_SHIFT-3)+3)<<2) | 0); +#endif } /* @@ -444,15 +448,6 @@ /* install the gate page in the global page table: */ put_gate_page(virt_to_page(__start_gate_section), GATE_ADDR); - -#ifndef CONFIG_IA64_SOFTSDV_HACKS - /* - * (Some) SoftSDVs seem to have a problem with this call. - * Since it's mostly a performance optimization, just don't do - * it for now... --davidm 99/12/6 - */ - efi_enter_virtual_mode(); -#endif #ifdef CONFIG_IA32_SUPPORT ia32_gdt_init(); diff -urN linux-davidm/drivers/char/vt.c linux-2.4.0-test9-lia/drivers/char/vt.c --- linux-davidm/drivers/char/vt.c Wed Aug 2 18:54:18 2000 +++ linux-2.4.0-test9-lia/drivers/char/vt.c Wed Oct 4 21:43:13 2000 @@ -62,7 +62,7 @@ */ unsigned char keyboard_type = KB_101; -#if !defined(__alpha__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on); #endif @@ -472,7 +472,7 @@ ucval = keyboard_type; goto setchar; -#if !defined(__alpha__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) /* * These cannot be implemented on any machine that implements * ioperm() in user level (such as Alpha PCs). diff -urN linux-davidm/drivers/scsi/Makefile linux-2.4.0-test9-lia/drivers/scsi/Makefile --- linux-davidm/drivers/scsi/Makefile Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/drivers/scsi/Makefile Wed Oct 4 21:30:21 2000 @@ -123,7 +123,7 @@ scsicam.o scsi_proc.o scsi_error.o \ scsi_obsolete.o scsi_queue.o scsi_lib.o \ scsi_merge.o scsi_dma.o scsi_scan.o \ - + sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o initio-objs := ini9100u.o i91uscsi.o a100u2w-objs := inia100.o i60uscsi.o diff -urN linux-davidm/drivers/scsi/qla1280.c linux-2.4.0-test9-lia/drivers/scsi/qla1280.c --- linux-davidm/drivers/scsi/qla1280.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/drivers/scsi/qla1280.c Wed Oct 4 21:43:30 2000 @@ -19,6 +19,10 @@ /**************************************************************************** Revision History: + Rev 3.17 Beta September 18, 2000 BN Qlogic + - Removed warnings for 32 bit 2.4.x compiles + - Corrected declared size for request and response + DMA addresses that are kept in each ha Rev. 3.16 Beta August 25, 2000 BN Qlogic - Corrected 64 bit addressing issue on IA-64 where the upper 32 bits were not properly @@ -98,7 +102,7 @@ #include #endif -#define QLA1280_VERSION "3.16 Beta" +#define QLA1280_VERSION "3.17 Beta" #include #include @@ -175,8 +179,13 @@ #define QLA1280_DELAY(sec) mdelay(sec * 1000) /* 3.16 */ +#if BITS_PER_LONG > 32 #define pci_dma_lo32(a) (a & 0xffffffff) #define pci_dma_hi32(a) ((a >> 32) & 0xffffffff) +#else +#define pci_dma_lo32(a) (a & 0xffffffff) +#define pci_dma_hi32(a) 0 +#endif #define VIRT_TO_BUS(a) virt_to_bus(((void *)a)) @@ -2789,7 +2798,7 @@ uint8_t *sp; uint8_t *tbuf; #if BITS_PER_LONG > 32 - u_long p_tbuf; + dma_addr_t p_tbuf; #else uint32_t p_tbuf; #endif @@ -4170,12 +4179,12 @@ #endif } } -#ifdef QL_DEBUG_LEVEL_5 - else /* No data transfer */ + else /* No data transfer */ { *dword_ptr++ = (uint32_t) 0; *dword_ptr++ = (uint32_t) 0; *dword_ptr = (uint32_t) 0; +#ifdef QL_DEBUG_LEVEL_5 qla1280_print( "qla1280_64bit_start_scsi: No data, command packet data - c"); qla1280_print(" b "); @@ -4186,8 +4195,8 @@ qla1280_output_number((uint32_t)SCSI_LUN_32(cmd), 10); qla1280_print("\n\r"); qla1280_dump_buffer((caddr_t)pkt, REQUEST_ENTRY_SIZE); - } #endif + } /* Adjust ring index. */ ha->req_ring_index++; if (ha->req_ring_index = REQUEST_ENTRY_CNT) diff -urN linux-davidm/drivers/scsi/qla1280.h linux-2.4.0-test9-lia/drivers/scsi/qla1280.h --- linux-davidm/drivers/scsi/qla1280.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/drivers/scsi/qla1280.h Wed Oct 4 21:43:38 2000 @@ -1439,22 +1439,35 @@ request_t req[REQUEST_ENTRY_CNT+1]; response_t res[RESPONSE_ENTRY_CNT+1]; +#if BITS_PER_LONG > 32 + dma_addr_t request_dma; /* Physical Address */ +#else uint32_t request_dma; /* Physical address. */ +#endif request_t *request_ring; /* Base virtual address */ request_t *request_ring_ptr; /* Current address. */ uint16_t req_ring_index; /* Current index. */ uint16_t req_q_cnt; /* Number of available entries. */ +#if BITS_PER_LONG > 32 + dma_addr_t response_dma; /* Physical address. */ +#else uint32_t response_dma; /* Physical address. */ +#endif response_t *response_ring; /* Base virtual address */ response_t *response_ring_ptr; /* Current address. */ uint16_t rsp_ring_index; /* Current index. */ #if QL1280_TARGET_MODE_SUPPORT /* Target buffer and sense data. */ +#if BITS_PER_LONG > 32 + dma_addr_t tbuf_dma; /* Physical address. */ + dma_addr_t tsense_dma; /* Physical address. */ +#else uint32_t tbuf_dma; /* Physical address. */ - tgt_t *tbuf; uint32_t tsense_dma; /* Physical address. */ +#endif + tgt_t *tbuf; uint8_t *tsense; #endif diff -urN linux-davidm/drivers/scsi/simscsi.c linux-2.4.0-test9-lia/drivers/scsi/simscsi.c --- linux-davidm/drivers/scsi/simscsi.c Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/drivers/scsi/simscsi.c Wed Oct 4 21:43:52 2000 @@ -357,3 +357,8 @@ } return 0; } + + +static Scsi_Host_Template driver_template = SIMSCSI; + +#include "scsi_module.c" diff -urN linux-davidm/include/asm-ia64/acpikcfg.h linux-2.4.0-test9-lia/include/asm-ia64/acpikcfg.h --- linux-davidm/include/asm-ia64/acpikcfg.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/acpikcfg.h Wed Oct 4 21:46:27 2000 @@ -7,12 +7,10 @@ */ -typedef u32 ACPI_STATUS; /* from actypes.h */ +u32 __init acpi_cf_init (void * rsdp); +u32 __init acpi_cf_terminate (void ); -ACPI_STATUS __init acpi_cf_init (void * rsdp); -ACPI_STATUS __init acpi_cf_terminate (void ); - -ACPI_STATUS __init +u32 __init acpi_cf_get_pci_vectors ( struct pci_vector_struct **vectors, int *num_pci_vectors diff -urN linux-davidm/include/asm-ia64/atomic.h linux-2.4.0-test9-lia/include/asm-ia64/atomic.h --- linux-davidm/include/asm-ia64/atomic.h Fri Apr 21 15:21:24 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/atomic.h Wed Oct 4 21:46:40 2000 @@ -17,13 +17,6 @@ #include /* - * Make sure gcc doesn't try to be clever and move things around - * on us. We need to use _exactly_ the address the user gave us, - * not some alias that contains the same information. - */ -#define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x) - -/* * On IA-64, counter must always be volatile to ensure that that the * memory accesses are ordered. */ diff -urN linux-davidm/include/asm-ia64/bitops.h linux-2.4.0-test9-lia/include/asm-ia64/bitops.h --- linux-davidm/include/asm-ia64/bitops.h Wed Jul 5 22:15:26 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/bitops.h Wed Oct 4 21:46:53 2000 @@ -20,7 +20,7 @@ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). */ -extern __inline__ void +static __inline__ void set_bit (int nr, volatile void *addr) { __u32 bit, old, new; @@ -36,7 +36,12 @@ } while (cmpxchg_acq(m, old, new) != old); } -extern __inline__ void +/* + * clear_bit() doesn't provide any barrier for the compiler. + */ +#define smp_mb__before_clear_bit() smp_mb() +#define smp_mb__after_clear_bit() smp_mb() +static __inline__ void clear_bit (int nr, volatile void *addr) { __u32 mask, old, new; @@ -52,7 +57,7 @@ } while (cmpxchg_acq(m, old, new) != old); } -extern __inline__ void +static __inline__ void change_bit (int nr, volatile void *addr) { __u32 bit, old, new; @@ -68,7 +73,7 @@ } while (cmpxchg_acq(m, old, new) != old); } -extern __inline__ int +static __inline__ int test_and_set_bit (int nr, volatile void *addr) { __u32 bit, old, new; @@ -85,7 +90,7 @@ return (old & bit) != 0; } -extern __inline__ int +static __inline__ int test_and_clear_bit (int nr, volatile void *addr) { __u32 mask, old, new; @@ -102,7 +107,7 @@ return (old & ~mask) != 0; } -extern __inline__ int +static __inline__ int test_and_change_bit (int nr, volatile void *addr) { __u32 bit, old, new; @@ -119,7 +124,7 @@ return (old & bit) != 0; } -extern __inline__ int +static __inline__ int test_bit (int nr, volatile void *addr) { return 1 & (((const volatile __u32 *) addr)[nr >> 5] >> (nr & 31)); @@ -129,7 +134,7 @@ * ffz = Find First Zero in word. Undefined if no zero exists, * so code should check against ~0UL first.. */ -extern inline unsigned long +static inline unsigned long ffz (unsigned long x) { unsigned long result; @@ -164,7 +169,7 @@ * hweightN: returns the hamming weight (i.e. the number * of bits set) of a N-bit word */ -extern __inline__ unsigned long +static __inline__ unsigned long hweight64 (unsigned long x) { unsigned long result; @@ -181,7 +186,7 @@ /* * Find next zero bit in a bitmap reasonably efficiently.. */ -extern inline int +static inline int find_next_zero_bit (void *addr, unsigned long size, unsigned long offset) { unsigned long *p = ((unsigned long *) addr) + (offset >> 6); diff -urN linux-davidm/include/asm-ia64/delay.h linux-2.4.0-test9-lia/include/asm-ia64/delay.h --- linux-davidm/include/asm-ia64/delay.h Sun Feb 6 18:42:40 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/delay.h Wed Oct 4 21:46:59 2000 @@ -18,13 +18,13 @@ #include -extern __inline__ void +static __inline__ void ia64_set_itm (unsigned long val) { __asm__ __volatile__("mov cr.itm=%0;; srlz.d;;" :: "r"(val) : "memory"); } -extern __inline__ unsigned long +static __inline__ unsigned long ia64_get_itm (void) { unsigned long result; @@ -33,7 +33,7 @@ return result; } -extern __inline__ void +static __inline__ void ia64_set_itv (unsigned char vector, unsigned char masked) { if (masked > 1) @@ -43,13 +43,13 @@ :: "r"((masked << 16) | vector) : "memory"); } -extern __inline__ void +static __inline__ void ia64_set_itc (unsigned long val) { __asm__ __volatile__("mov ar.itc=%0;; srlz.d;;" :: "r"(val) : "memory"); } -extern __inline__ unsigned long +static __inline__ unsigned long ia64_get_itc (void) { unsigned long result; @@ -58,7 +58,7 @@ return result; } -extern __inline__ void +static __inline__ void __delay (unsigned long loops) { unsigned long saved_ar_lc; @@ -72,7 +72,7 @@ __asm__ __volatile__("mov ar.lc=%0" :: "r"(saved_ar_lc)); } -extern __inline__ void +static __inline__ void udelay (unsigned long usecs) { #ifdef CONFIG_IA64_SOFTSDV_HACKS diff -urN linux-davidm/include/asm-ia64/efi.h linux-2.4.0-test9-lia/include/asm-ia64/efi.h --- linux-davidm/include/asm-ia64/efi.h Thu Aug 24 08:17:47 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/efi.h Wed Oct 4 21:47:05 2000 @@ -219,7 +219,7 @@ efi_reset_system_t *reset_system; } efi; -extern inline int +static inline int efi_guidcmp (efi_guid_t left, efi_guid_t right) { return memcmp(&left, &right, sizeof (efi_guid_t)); diff -urN linux-davidm/include/asm-ia64/io.h linux-2.4.0-test9-lia/include/asm-ia64/io.h --- linux-davidm/include/asm-ia64/io.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/io.h Wed Oct 4 21:47:47 2000 @@ -63,7 +63,7 @@ */ #define __ia64_mf_a() __asm__ __volatile__ ("mf.a" ::: "memory") -extern inline const unsigned long +static inline const unsigned long __ia64_get_io_port_base (void) { extern unsigned long ia64_iobase; @@ -71,7 +71,7 @@ return ia64_iobase; } -extern inline void* +static inline void* __ia64_mk_io_addr (unsigned long port) { const unsigned long io_base = __ia64_get_io_port_base(); @@ -99,7 +99,7 @@ * order. --davidm 99/12/07 */ -extern inline unsigned int +static inline unsigned int __inb (unsigned long port) { volatile unsigned char *addr = __ia64_mk_io_addr(port); @@ -110,7 +110,7 @@ return ret; } -extern inline unsigned int +static inline unsigned int __inw (unsigned long port) { volatile unsigned short *addr = __ia64_mk_io_addr(port); @@ -121,7 +121,7 @@ return ret; } -extern inline unsigned int +static inline unsigned int __inl (unsigned long port) { volatile unsigned int *addr = __ia64_mk_io_addr(port); @@ -132,7 +132,7 @@ return ret; } -extern inline void +static inline void __insb (unsigned long port, void *dst, unsigned long count) { volatile unsigned char *addr = __ia64_mk_io_addr(port); @@ -146,7 +146,7 @@ return; } -extern inline void +static inline void __insw (unsigned long port, void *dst, unsigned long count) { volatile unsigned short *addr = __ia64_mk_io_addr(port); @@ -160,7 +160,7 @@ return; } -extern inline void +static inline void __insl (unsigned long port, void *dst, unsigned long count) { volatile unsigned int *addr = __ia64_mk_io_addr(port); @@ -174,7 +174,7 @@ return; } -extern inline void +static inline void __outb (unsigned char val, unsigned long port) { volatile unsigned char *addr = __ia64_mk_io_addr(port); @@ -183,7 +183,7 @@ __ia64_mf_a(); } -extern inline void +static inline void __outw (unsigned short val, unsigned long port) { volatile unsigned short *addr = __ia64_mk_io_addr(port); @@ -192,7 +192,7 @@ __ia64_mf_a(); } -extern inline void +static inline void __outl (unsigned int val, unsigned long port) { volatile unsigned int *addr = __ia64_mk_io_addr(port); @@ -201,7 +201,7 @@ __ia64_mf_a(); } -extern inline void +static inline void __outsb (unsigned long port, const void *src, unsigned long count) { volatile unsigned char *addr = __ia64_mk_io_addr(port); @@ -214,7 +214,7 @@ return; } -extern inline void +static inline void __outsw (unsigned long port, const void *src, unsigned long count) { volatile unsigned short *addr = __ia64_mk_io_addr(port); @@ -227,7 +227,7 @@ return; } -extern inline void +static inline void __outsl (unsigned long port, void *src, unsigned long count) { volatile unsigned int *addr = __ia64_mk_io_addr(port); @@ -256,49 +256,49 @@ /* * The address passed to these functions are ioremap()ped already. */ -extern inline unsigned char +static inline unsigned char __readb (void *addr) { return *(volatile unsigned char *)addr; } -extern inline unsigned short +static inline unsigned short __readw (void *addr) { return *(volatile unsigned short *)addr; } -extern inline unsigned int +static inline unsigned int __readl (void *addr) { return *(volatile unsigned int *) addr; } -extern inline unsigned long +static inline unsigned long __readq (void *addr) { return *(volatile unsigned long *) addr; } -extern inline void +static inline void __writeb (unsigned char val, void *addr) { *(volatile unsigned char *) addr = val; } -extern inline void +static inline void __writew (unsigned short val, void *addr) { *(volatile unsigned short *) addr = val; } -extern inline void +static inline void __writel (unsigned int val, void *addr) { *(volatile unsigned int *) addr = val; } -extern inline void +static inline void __writeq (unsigned long val, void *addr) { *(volatile unsigned long *) addr = val; diff -urN linux-davidm/include/asm-ia64/mmu_context.h linux-2.4.0-test9-lia/include/asm-ia64/mmu_context.h --- linux-davidm/include/asm-ia64/mmu_context.h Thu Aug 24 08:17:47 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/mmu_context.h Wed Oct 4 21:48:03 2000 @@ -57,7 +57,7 @@ { } -extern inline unsigned long +static inline unsigned long ia64_rid (unsigned long context, unsigned long region_addr) { # ifdef CONFIG_IA64_TLB_CHECKS_REGION_NUMBER @@ -67,7 +67,7 @@ # endif } -extern inline void +static inline void get_new_mmu_context (struct mm_struct *mm) { spin_lock(&ia64_ctx.lock); @@ -80,7 +80,7 @@ } -extern inline void +static inline void get_mmu_context (struct mm_struct *mm) { /* check if our ASN is of an older generation and thus invalid: */ @@ -88,20 +88,20 @@ get_new_mmu_context(mm); } -extern inline int +static inline int init_new_context (struct task_struct *p, struct mm_struct *mm) { mm->context = 0; return 0; } -extern inline void +static inline void destroy_context (struct mm_struct *mm) { /* Nothing to do. */ } -extern inline void +static inline void reload_context (struct mm_struct *mm) { unsigned long rid; diff -urN linux-davidm/include/asm-ia64/module.h linux-2.4.0-test9-lia/include/asm-ia64/module.h --- linux-davidm/include/asm-ia64/module.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/module.h Wed Oct 4 21:48:16 2000 @@ -76,7 +76,9 @@ * Pointers are reasonable, add the module unwind table */ archdata->unw_table = unw_add_unwind_table(mod->name, archdata->segment_base, - archdata->gp, archdata->unw_start, archdata->unw_end); + (unsigned long) archdata->gp, + (unsigned long) archdata->unw_start, + (unsigned long) archdata->unw_end); #endif /* CONFIG_IA64_NEW_UNWIND */ return 0; } diff -urN linux-davidm/include/asm-ia64/offsets.h linux-2.4.0-test9-lia/include/asm-ia64/offsets.h --- linux-davidm/include/asm-ia64/offsets.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/offsets.h Wed Oct 4 21:48:29 2000 @@ -11,7 +11,7 @@ #define PT_PTRACED_BIT 0 #define PT_TRACESYS_BIT 1 -#define IA64_TASK_SIZE 2928 /* 0xb70 */ +#define IA64_TASK_SIZE 3328 /* 0xd00 */ #define IA64_PT_REGS_SIZE 400 /* 0x190 */ #define IA64_SWITCH_STACK_SIZE 560 /* 0x230 */ #define IA64_SIGINFO_SIZE 128 /* 0x80 */ @@ -21,9 +21,9 @@ #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 928 /* 0x3a0 */ -#define IA64_TASK_THREAD_KSP_OFFSET 928 /* 0x3a0 */ -#define IA64_TASK_THREAD_SIGMASK_OFFSET 2784 /* 0xae0 */ +#define IA64_TASK_THREAD_OFFSET 1424 /* 0x590 */ +#define IA64_TASK_THREAD_KSP_OFFSET 1424 /* 0x590 */ +#define IA64_TASK_THREAD_SIGMASK_OFFSET 3184 /* 0xc70 */ #define IA64_TASK_PID_OFFSET 188 /* 0xbc */ #define IA64_TASK_MM_OFFSET 88 /* 0x58 */ #define IA64_PT_REGS_CR_IPSR_OFFSET 0 /* 0x0 */ diff -urN linux-davidm/include/asm-ia64/page.h linux-2.4.0-test9-lia/include/asm-ia64/page.h --- linux-davidm/include/asm-ia64/page.h Thu Aug 24 08:17:47 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/page.h Wed Oct 4 21:48:41 2000 @@ -102,15 +102,13 @@ #ifdef CONFIG_IA64_GENERIC # include # define virt_to_page(kaddr) (mem_map + platform_map_nr(kaddr)) -#elif defined (CONFIG_IA64_SN_SN1_SIM) +#elif defined (CONFIG_IA64_SN_SN1) # define virt_to_page(kaddr) (mem_map + MAP_NR_SN1(kaddr)) #else # define virt_to_page(kaddr) (mem_map + MAP_NR_DENSE(kaddr)) #endif #define VALID_PAGE(page) ((page - mem_map) < max_mapnr) -# endif /* __KERNEL__ */ - typedef union ia64_va { struct { unsigned long off : 61; /* intra-region offset */ @@ -138,7 +136,7 @@ #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0) #define PAGE_BUG(page) do { BUG(); } while (0) -extern __inline__ int +static __inline__ int get_order (unsigned long size) { double d = size - 1; @@ -151,6 +149,7 @@ return order; } +# endif /* __KERNEL__ */ #endif /* !ASSEMBLY */ #define PAGE_OFFSET 0xe000000000000000 diff -urN linux-davidm/include/asm-ia64/pal.h linux-2.4.0-test9-lia/include/asm-ia64/pal.h --- linux-davidm/include/asm-ia64/pal.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/pal.h Wed Oct 4 21:48:58 2000 @@ -708,7 +708,7 @@ extern void pal_bus_features_print (u64); /* Provide information about configurable processor bus features */ -extern 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) @@ -725,7 +725,7 @@ } /* Enables/disables specific processor bus features */ -extern inline s64 +static inline s64 ia64_pal_bus_set_features (pal_bus_features_u_t feature_select) { struct ia64_pal_retval iprv; @@ -734,7 +734,7 @@ } /* Get detailed cache information */ -extern inline s64 +static inline s64 ia64_pal_cache_config_info (u64 cache_level, u64 cache_type, pal_cache_config_info_t *conf) { struct ia64_pal_retval iprv; @@ -752,7 +752,7 @@ } /* Get detailed cche protection information */ -extern inline s64 +static inline s64 ia64_pal_cache_prot_info (u64 cache_level, u64 cache_type, pal_cache_protection_info_t *prot) { struct ia64_pal_retval iprv; @@ -775,7 +775,7 @@ * Flush the processor instruction or data caches. *PROGRESS must be * initialized to zero before calling this for the first time.. */ -extern inline s64 +static inline s64 ia64_pal_cache_flush (u64 cache_type, u64 invalidate, u64 *progress) { struct ia64_pal_retval iprv; @@ -786,7 +786,7 @@ /* Initialize the processor controlled caches */ -extern inline s64 +static inline s64 ia64_pal_cache_init (u64 level, u64 cache_type, u64 restrict) { struct ia64_pal_retval iprv; @@ -798,7 +798,7 @@ * processor controlled cache to known values without the availability * of backing memory. */ -extern inline s64 +static inline s64 ia64_pal_cache_line_init (u64 physical_addr, u64 data_value) { struct ia64_pal_retval iprv; @@ -808,7 +808,7 @@ /* Read the data and tag of a processor controlled cache line for diags */ -extern inline s64 +static inline s64 ia64_pal_cache_read (pal_cache_line_id_u_t line_id, u64 physical_addr) { struct ia64_pal_retval iprv; @@ -817,7 +817,7 @@ } /* Return summary information about the heirarchy of caches controlled by the processor */ -extern inline s64 +static inline s64 ia64_pal_cache_summary (u64 *cache_levels, u64 *unique_caches) { struct ia64_pal_retval iprv; @@ -830,7 +830,7 @@ } /* Write the data and tag of a processor-controlled cache line for diags */ -extern inline s64 +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; @@ -840,7 +840,7 @@ /* Return the parameters needed to copy relocatable PAL procedures from ROM to memory */ -extern inline s64 +static inline s64 ia64_pal_copy_info (u64 copy_type, u64 num_procs, u64 num_iopics, u64 *buffer_size, u64 *buffer_align) { @@ -854,7 +854,7 @@ } /* Copy relocatable PAL procedures from ROM to memory */ -extern inline s64 +static inline s64 ia64_pal_copy_pal (u64 target_addr, u64 alloc_size, u64 processor, u64 *pal_proc_offset) { struct ia64_pal_retval iprv; @@ -865,7 +865,7 @@ } /* Return the number of instruction and data debug register pairs */ -extern inline s64 +static inline s64 ia64_pal_debug_info (u64 *inst_regs, u64 *data_regs) { struct ia64_pal_retval iprv; @@ -880,7 +880,7 @@ #ifdef TBD /* Switch from IA64-system environment to IA-32 system environment */ -extern inline s64 +static inline s64 ia64_pal_enter_ia32_env (ia32_env1, ia32_env2, ia32_env3) { struct ia64_pal_retval iprv; @@ -890,7 +890,7 @@ #endif /* Get unique geographical address of this processor on its bus */ -extern inline s64 +static inline s64 ia64_pal_fixed_addr (u64 *global_unique_addr) { struct ia64_pal_retval iprv; @@ -901,7 +901,7 @@ } /* Get base frequency of the platform if generated by the processor */ -extern inline s64 +static inline s64 ia64_pal_freq_base (u64 *platform_base_freq) { struct ia64_pal_retval iprv; @@ -915,7 +915,7 @@ * Get the ratios for processor frequency, bus frequency and interval timer to * to base frequency of the platform */ -extern 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) { @@ -934,7 +934,7 @@ * power states where prefetching and execution are suspended and cache and * TLB coherency is not maintained. */ -extern inline s64 +static inline s64 ia64_pal_halt (u64 halt_state) { struct ia64_pal_retval iprv; @@ -954,7 +954,7 @@ } pal_power_mgmt_info_u_t; /* Return information about processor's optional power management capabilities. */ -extern inline s64 +static inline s64 ia64_pal_halt_info (pal_power_mgmt_info_u_t *power_buf) { struct ia64_pal_retval iprv; @@ -965,7 +965,7 @@ /* Cause the processor to enter LIGHT HALT state, where prefetching and execution are * suspended, but cache and TLB coherency is maintained. */ -extern inline s64 +static inline s64 ia64_pal_halt_light (void) { struct ia64_pal_retval iprv; @@ -977,7 +977,7 @@ * the error logging registers to be written. This procedure also checks the pending * machine check bit and pending INIT bit and reports their states. */ -extern inline s64 +static inline s64 ia64_pal_mc_clear_log (u64 *pending_vector) { struct ia64_pal_retval iprv; @@ -990,7 +990,7 @@ /* Ensure that all outstanding transactions in a processor are completed or that any * MCA due to thes outstanding transaction is taken. */ -extern inline s64 +static inline s64 ia64_pal_mc_drain (void) { struct ia64_pal_retval iprv; @@ -999,7 +999,7 @@ } /* Return the machine check dynamic processor state */ -extern inline s64 +static inline s64 ia64_pal_mc_dynamic_state (u64 offset, u64 *size, u64 *pds) { struct ia64_pal_retval iprv; @@ -1012,7 +1012,7 @@ } /* Return processor machine check information */ -extern inline s64 +static inline s64 ia64_pal_mc_error_info (u64 info_index, u64 type_index, u64 *size, u64 *error_info) { struct ia64_pal_retval iprv; @@ -1027,7 +1027,7 @@ /* Inform PALE_CHECK whether a machine check is expected so that PALE_CHECK willnot * attempt to correct any expected machine checks. */ -extern inline s64 +static inline s64 ia64_pal_mc_expected (u64 expected, u64 *previous) { struct ia64_pal_retval iprv; @@ -1041,7 +1041,7 @@ * minimal processor state in the event of a machine check or initialization * event. */ -extern inline s64 +static inline s64 ia64_pal_mc_register_mem (u64 physical_addr) { struct ia64_pal_retval iprv; @@ -1052,7 +1052,7 @@ /* Restore minimal architectural processor state, set CMC interrupt if necessary * and resume execution */ -extern inline s64 +static inline s64 ia64_pal_mc_resume (u64 set_cmci, u64 save_ptr) { struct ia64_pal_retval iprv; @@ -1061,7 +1061,7 @@ } /* Return the memory attributes implemented by the processor */ -extern inline s64 +static inline s64 ia64_pal_mem_attrib (u64 *mem_attrib) { struct ia64_pal_retval iprv; @@ -1074,7 +1074,7 @@ /* Return the amount of memory needed for second phase of processor * self-test and the required alignment of memory. */ -extern inline s64 +static inline s64 ia64_pal_mem_for_test (u64 *bytes_needed, u64 *alignment) { struct ia64_pal_retval iprv; @@ -1100,7 +1100,7 @@ /* Return the performance monitor information about what can be counted * and how to configure the monitors to count the desired events. */ -extern inline s64 +static inline s64 ia64_pal_perf_mon_info (u64 *pm_buffer, pal_perf_mon_info_u_t *pm_info) { struct ia64_pal_retval iprv; @@ -1113,7 +1113,7 @@ /* Specifies the physical address of the processor interrupt block * and I/O port space. */ -extern inline s64 +static inline s64 ia64_pal_platform_addr (u64 type, u64 physical_addr) { struct ia64_pal_retval iprv; @@ -1122,7 +1122,7 @@ } /* Set the SAL PMI entrypoint in memory */ -extern inline s64 +static inline s64 ia64_pal_pmi_entrypoint (u64 sal_pmi_entry_addr) { struct ia64_pal_retval iprv; @@ -1132,7 +1132,7 @@ struct pal_features_s; /* Provide information about configurable processor features */ -extern inline s64 +static inline s64 ia64_pal_proc_get_features (u64 *features_avail, u64 *features_status, u64 *features_control) @@ -1148,7 +1148,7 @@ } /* Enable/disable processor dependent features */ -extern inline s64 +static inline s64 ia64_pal_proc_set_features (u64 feature_select) { struct ia64_pal_retval iprv; @@ -1169,7 +1169,7 @@ /* Return the information required for the architected loop used to purge * (initialize) the entire TC */ -extern inline s64 +static inline s64 ia64_get_ptce (ia64_ptce_info_t *ptce) { struct ia64_pal_retval iprv; @@ -1189,7 +1189,7 @@ } /* Return info about implemented application and control registers. */ -extern inline s64 +static inline s64 ia64_pal_register_info (u64 info_request, u64 *reg_info_1, u64 *reg_info_2) { struct ia64_pal_retval iprv; @@ -1213,7 +1213,7 @@ /* Return information about the register stack and RSE for this processor * implementation. */ -extern inline s64 +static inline s64 ia64_pal_rse_info (u64 *num_phys_stacked, pal_hints_u_t *hints) { struct ia64_pal_retval iprv; @@ -1229,7 +1229,7 @@ * suspended, but cause cache and TLB coherency to be maintained. * This is usually called in IA-32 mode. */ -extern inline s64 +static inline s64 ia64_pal_shutdown (void) { struct ia64_pal_retval iprv; @@ -1238,7 +1238,7 @@ } /* Perform the second phase of processor self-test. */ -extern 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; @@ -1263,7 +1263,7 @@ /* Return PAL version information */ -extern inline s64 +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; @@ -1301,7 +1301,7 @@ /* Return information about the virtual memory characteristics of the processor * implementation. */ -extern 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; @@ -1316,7 +1316,7 @@ /* Get page size information about the virtual memory characteristics of the processor * implementation. */ -extern inline s64 +static inline s64 ia64_pal_vm_page_size (u64 *tr_pages, u64 *vw_pages) { struct ia64_pal_retval iprv; @@ -1355,7 +1355,7 @@ /* Get summary information about the virtual memory characteristics of the processor * implementation. */ -extern inline s64 +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; @@ -1379,7 +1379,7 @@ } pal_tr_valid_u_t; /* Read a translation register */ -extern 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; @@ -1389,7 +1389,7 @@ return iprv.status; } -extern inline s64 +static inline s64 ia64_pal_prefetch_visibility (void) { struct ia64_pal_retval iprv; diff -urN linux-davidm/include/asm-ia64/param.h linux-2.4.0-test9-lia/include/asm-ia64/param.h --- linux-davidm/include/asm-ia64/param.h Thu Aug 24 08:17:47 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/param.h Wed Oct 4 21:49:06 2000 @@ -15,7 +15,7 @@ * Yeah, simulating stuff is slow, so let us catch some breath between * timer interrupts... */ -# define HZ 20 +# define HZ 32 #else # define HZ 1024 #endif diff -urN linux-davidm/include/asm-ia64/parport.h linux-2.4.0-test9-lia/include/asm-ia64/parport.h --- linux-davidm/include/asm-ia64/parport.h Wed Dec 31 16:00:00 1969 +++ linux-2.4.0-test9-lia/include/asm-ia64/parport.h Wed Oct 4 21:49:17 2000 @@ -0,0 +1,20 @@ +/* + * parport.h: platform-specific PC-style parport initialisation + * + * Copyright (C) 1999, 2000 Tim Waugh + * + * This file should only be included by drivers/parport/parport_pc.c. + */ + +#ifndef _ASM_IA64_PARPORT_H +#define _ASM_IA64_PARPORT_H 1 + +static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma); + +static int __devinit +parport_pc_find_nonpci_ports (int autoirq, int autodma) +{ + return parport_pc_find_isa_ports(autoirq, autodma); +} + +#endif /* _ASM_IA64_PARPORT_H */ diff -urN linux-davidm/include/asm-ia64/pci.h linux-2.4.0-test9-lia/include/asm-ia64/pci.h --- linux-davidm/include/asm-ia64/pci.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/pci.h Wed Oct 4 21:49:25 2000 @@ -22,12 +22,12 @@ struct pci_dev; -extern inline void pcibios_set_master(struct pci_dev *dev) +static inline void pcibios_set_master(struct pci_dev *dev) { /* No special bus mastering setup handling */ } -extern inline void pcibios_penalize_isa_irq(int irq) +static inline void pcibios_penalize_isa_irq(int irq) { /* We don't do dynamic PCI IRQ allocation */ } @@ -128,7 +128,7 @@ * only drive the low 24-bits during PCI bus mastering, then * you would pass 0x00ffffff as the mask to this function. */ -extern inline int +static inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) { return 1; diff -urN linux-davidm/include/asm-ia64/pgalloc.h linux-2.4.0-test9-lia/include/asm-ia64/pgalloc.h --- linux-davidm/include/asm-ia64/pgalloc.h Fri Apr 21 15:21:24 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/pgalloc.h Wed Oct 4 21:49:31 2000 @@ -32,7 +32,7 @@ #define pte_quicklist (my_cpu_data.pte_quick) #define pgtable_cache_size (my_cpu_data.pgtable_cache_sz) -extern __inline__ pgd_t* +static __inline__ pgd_t* get_pgd_slow (void) { pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL); @@ -41,7 +41,7 @@ return ret; } -extern __inline__ pgd_t* +static __inline__ pgd_t* get_pgd_fast (void) { unsigned long *ret = pgd_quicklist; @@ -54,7 +54,7 @@ return (pgd_t *)ret; } -extern __inline__ pgd_t* +static __inline__ pgd_t* pgd_alloc (void) { pgd_t *pgd; @@ -65,7 +65,7 @@ return pgd; } -extern __inline__ void +static __inline__ void free_pgd_fast (pgd_t *pgd) { *(unsigned long *)pgd = (unsigned long) pgd_quicklist; @@ -73,7 +73,7 @@ ++pgtable_cache_size; } -extern __inline__ pmd_t * +static __inline__ pmd_t * get_pmd_slow (void) { pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL); @@ -83,7 +83,7 @@ return pmd; } -extern __inline__ pmd_t * +static __inline__ pmd_t * get_pmd_fast (void) { unsigned long *ret = (unsigned long *)pmd_quicklist; @@ -96,7 +96,7 @@ return (pmd_t *)ret; } -extern __inline__ void +static __inline__ void free_pmd_fast (pmd_t *pmd) { *(unsigned long *)pmd = (unsigned long) pmd_quicklist; @@ -104,7 +104,7 @@ ++pgtable_cache_size; } -extern __inline__ void +static __inline__ void free_pmd_slow (pmd_t *pmd) { free_page((unsigned long)pmd); @@ -112,7 +112,7 @@ extern pte_t *get_pte_slow (pmd_t *pmd, unsigned long address_preadjusted); -extern __inline__ pte_t * +static __inline__ pte_t * get_pte_fast (void) { unsigned long *ret = (unsigned long *)pte_quicklist; @@ -125,7 +125,7 @@ return (pte_t *)ret; } -extern __inline__ void +static __inline__ void free_pte_fast (pte_t *pte) { *(unsigned long *)pte = (unsigned long) pte_quicklist; @@ -142,7 +142,7 @@ extern void __handle_bad_pgd (pgd_t *pgd); extern void __handle_bad_pmd (pmd_t *pmd); -extern __inline__ pte_t* +static __inline__ pte_t* pte_alloc (pmd_t *pmd, unsigned long vmaddr) { unsigned long offset; @@ -163,7 +163,7 @@ return (pte_t *) pmd_page(*pmd) + offset; } -extern __inline__ pmd_t* +static __inline__ pmd_t* pmd_alloc (pgd_t *pgd, unsigned long vmaddr) { unsigned long offset; @@ -228,7 +228,7 @@ /* * Flush a specified user mapping */ -extern __inline__ void +static __inline__ void flush_tlb_mm (struct mm_struct *mm) { if (mm) { diff -urN linux-davidm/include/asm-ia64/pgtable.h linux-2.4.0-test9-lia/include/asm-ia64/pgtable.h --- linux-davidm/include/asm-ia64/pgtable.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/pgtable.h Wed Oct 4 21:49:41 2000 @@ -318,7 +318,7 @@ /* * Return the region index for virtual address ADDRESS. */ -extern __inline__ unsigned long +static __inline__ unsigned long rgn_index (unsigned long address) { ia64_va a; @@ -330,7 +330,7 @@ /* * Return the region offset for virtual address ADDRESS. */ -extern __inline__ unsigned long +static __inline__ unsigned long rgn_offset (unsigned long address) { ia64_va a; @@ -342,7 +342,7 @@ #define RGN_SIZE (1UL << 61) #define RGN_KERNEL 7 -extern __inline__ unsigned long +static __inline__ unsigned long pgd_index (unsigned long address) { unsigned long region = address >> 61; @@ -353,7 +353,7 @@ /* The offset in the 1-level directory is given by the 3 region bits (61..63) and the seven level-1 bits (33-39). */ -extern __inline__ pgd_t* +static __inline__ pgd_t* pgd_offset (struct mm_struct *mm, unsigned long address) { return mm->pgd + pgd_index(address); diff -urN linux-davidm/include/asm-ia64/processor.h linux-2.4.0-test9-lia/include/asm-ia64/processor.h --- linux-davidm/include/asm-ia64/processor.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/processor.h Wed Oct 4 21:49:46 2000 @@ -454,31 +454,31 @@ ia64_fph_disable(); } -extern inline void +static inline void ia64_fc (void *addr) { __asm__ __volatile__ ("fc %0" :: "r"(addr) : "memory"); } -extern inline void +static inline void ia64_sync_i (void) { __asm__ __volatile__ (";; sync.i" ::: "memory"); } -extern inline void +static inline void ia64_srlz_i (void) { __asm__ __volatile__ (";; srlz.i ;;" ::: "memory"); } -extern inline void +static inline void ia64_srlz_d (void) { __asm__ __volatile__ (";; srlz.d" ::: "memory"); } -extern inline __u64 +static inline __u64 ia64_get_rr (__u64 reg_bits) { __u64 r; @@ -486,13 +486,13 @@ return r; } -extern inline void +static inline void ia64_set_rr (__u64 reg_bits, __u64 rr_val) { __asm__ __volatile__ ("mov rr[%0]=%1" :: "r"(reg_bits), "r"(rr_val) : "memory"); } -extern inline __u64 +static inline __u64 ia64_get_dcr (void) { __u64 r; @@ -500,14 +500,14 @@ return r; } -extern inline void +static inline void ia64_set_dcr (__u64 val) { __asm__ __volatile__ ("mov cr.dcr=%0;;" :: "r"(val) : "memory"); ia64_srlz_d(); } -extern inline __u64 +static inline __u64 ia64_get_lid (void) { __u64 r; @@ -515,7 +515,7 @@ return r; } -extern inline void +static inline void ia64_invala (void) { __asm__ __volatile__ ("invala" ::: "memory"); @@ -533,7 +533,7 @@ * Insert a translation into an instruction and/or data translation * register. */ -extern inline void +static inline void ia64_itr (__u64 target_mask, __u64 tr_num, __u64 vmaddr, __u64 pte, __u64 log_page_size) @@ -552,7 +552,7 @@ * Insert a translation into the instruction and/or data translation * cache. */ -extern inline void +static inline void ia64_itc (__u64 target_mask, __u64 vmaddr, __u64 pte, __u64 log_page_size) { @@ -569,7 +569,7 @@ * Purge a range of addresses from instruction and/or data translation * register(s). */ -extern inline void +static inline void ia64_ptr (__u64 target_mask, __u64 vmaddr, __u64 log_size) { if (target_mask & 0x1) @@ -579,21 +579,21 @@ } /* Set the interrupt vector address. The address must be suitably aligned (32KB). */ -extern inline void +static inline void ia64_set_iva (void *ivt_addr) { __asm__ __volatile__ ("mov cr.iva=%0;; srlz.i;;" :: "r"(ivt_addr) : "memory"); } /* Set the page table address and control bits. */ -extern inline void +static inline void ia64_set_pta (__u64 pta) { /* Note: srlz.i implies srlz.d */ __asm__ __volatile__ ("mov cr.pta=%0;; srlz.i;;" :: "r"(pta) : "memory"); } -extern inline __u64 +static inline __u64 ia64_get_cpuid (__u64 regnum) { __u64 r; @@ -602,13 +602,13 @@ return r; } -extern inline void +static inline void ia64_eoi (void) { __asm__ ("mov cr.eoi=r0;; srlz.d;;" ::: "memory"); } -extern __inline__ void +static inline void ia64_set_lrr0 (__u8 vector, __u8 masked) { if (masked > 1) @@ -619,7 +619,7 @@ } -extern __inline__ void +static inline void ia64_set_lrr1 (__u8 vector, __u8 masked) { if (masked > 1) @@ -629,13 +629,13 @@ :: "r"((masked << 16) | vector) : "memory"); } -extern __inline__ void +static inline void ia64_set_pmv (__u64 val) { __asm__ __volatile__ ("mov cr.pmv=%0" :: "r"(val) : "memory"); } -extern __inline__ __u64 +static inline __u64 ia64_get_pmc (__u64 regnum) { __u64 retval; @@ -644,13 +644,13 @@ return retval; } -extern __inline__ void +static inline void ia64_set_pmc (__u64 regnum, __u64 value) { __asm__ __volatile__ ("mov pmc[%0]=%1" :: "r"(regnum), "r"(value)); } -extern __inline__ __u64 +static inline __u64 ia64_get_pmd (__u64 regnum) { __u64 retval; @@ -659,7 +659,7 @@ return retval; } -extern __inline__ void +static inline void ia64_set_pmd (__u64 regnum, __u64 value) { __asm__ __volatile__ ("mov pmd[%0]=%1" :: "r"(regnum), "r"(value)); @@ -669,7 +669,7 @@ * Given the address to which a spill occurred, return the unat bit * number that corresponds to this address. */ -extern inline __u64 +static inline __u64 ia64_unat_pos (void *spill_addr) { return ((__u64) spill_addr >> 3) & 0x3f; @@ -679,7 +679,7 @@ * Set the NaT bit of an integer register which was spilled at address * SPILL_ADDR. UNAT is the mask to be updated. */ -extern inline void +static inline void ia64_set_unat (__u64 *unat, void *spill_addr, unsigned long nat) { __u64 bit = ia64_unat_pos(spill_addr); @@ -692,7 +692,7 @@ * Return saved PC of a blocked thread. * Note that the only way T can block is through a call to schedule() -> switch_to(). */ -extern inline unsigned long +static inline unsigned long thread_saved_pc (struct thread_struct *t) { struct unw_frame_info info; @@ -727,7 +727,7 @@ /* * Set the correctable machine check vector register */ -extern __inline__ void +static inline void ia64_set_cmcv (__u64 val) { __asm__ __volatile__ ("mov cr.cmcv=%0" :: "r"(val) : "memory"); @@ -736,7 +736,7 @@ /* * Read the correctable machine check vector register */ -extern __inline__ __u64 +static inline __u64 ia64_get_cmcv (void) { __u64 val; @@ -745,7 +745,7 @@ return val; } -extern inline __u64 +static inline __u64 ia64_get_ivr (void) { __u64 r; @@ -753,13 +753,13 @@ return r; } -extern inline void +static inline void ia64_set_tpr (__u64 val) { __asm__ __volatile__ ("mov cr.tpr=%0" :: "r"(val)); } -extern inline __u64 +static inline __u64 ia64_get_tpr (void) { __u64 r; @@ -767,71 +767,75 @@ return r; } -extern __inline__ void +static inline void ia64_set_irr0 (__u64 val) { __asm__ __volatile__("mov cr.irr0=%0;;" :: "r"(val) : "memory"); ia64_srlz_d(); } -extern __inline__ __u64 +static inline __u64 ia64_get_irr0 (void) { __u64 val; - __asm__ ("mov %0=cr.irr0" : "=r"(val)); + /* this is volatile because irr may change unbeknownst to gcc... */ + __asm__ __volatile__("mov %0=cr.irr0" : "=r"(val)); return val; } -extern __inline__ void +static inline void ia64_set_irr1 (__u64 val) { __asm__ __volatile__("mov cr.irr1=%0;;" :: "r"(val) : "memory"); ia64_srlz_d(); } -extern __inline__ __u64 +static inline __u64 ia64_get_irr1 (void) { __u64 val; - __asm__ ("mov %0=cr.irr1" : "=r"(val)); + /* this is volatile because irr may change unbeknownst to gcc... */ + __asm__ __volatile__("mov %0=cr.irr1" : "=r"(val)); return val; } -extern __inline__ void +static inline void ia64_set_irr2 (__u64 val) { __asm__ __volatile__("mov cr.irr2=%0;;" :: "r"(val) : "memory"); ia64_srlz_d(); } -extern __inline__ __u64 +static inline __u64 ia64_get_irr2 (void) { __u64 val; - __asm__ ("mov %0=cr.irr2" : "=r"(val)); + /* this is volatile because irr may change unbeknownst to gcc... */ + __asm__ __volatile__("mov %0=cr.irr2" : "=r"(val)); return val; } -extern __inline__ void +static inline void ia64_set_irr3 (__u64 val) { __asm__ __volatile__("mov cr.irr3=%0;;" :: "r"(val) : "memory"); ia64_srlz_d(); } -extern __inline__ __u64 +static inline __u64 ia64_get_irr3 (void) { __u64 val; - __asm__ ("mov %0=cr.irr3" : "=r"(val)); + /* this is volatile because irr may change unbeknownst to gcc... */ + __asm__ __volatile__("mov %0=cr.irr3" : "=r"(val)); return val; } -extern __inline__ __u64 +static inline __u64 ia64_get_gp(void) { __u64 val; @@ -859,7 +863,7 @@ #define ia64_rotl(w,n) ia64_rotr((w),(64)-(n)) -extern __inline__ __u64 +static inline __u64 ia64_thash (__u64 addr) { __u64 result; diff -urN linux-davidm/include/asm-ia64/ptrace_offsets.h linux-2.4.0-test9-lia/include/asm-ia64/ptrace_offsets.h --- linux-davidm/include/asm-ia64/ptrace_offsets.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/ptrace_offsets.h Wed Oct 4 23:05:46 2000 @@ -17,6 +17,8 @@ * unsigned long dbr[8]; * unsigned long rsvd2[504]; * unsigned long ibr[8]; + * unsigned long rsvd3[504]; + * unsigned long pmd[4]; * } */ @@ -210,5 +212,6 @@ #define PT_DBR 0x2000 /* data breakpoint registers */ #define PT_IBR 0x3000 /* instruction breakpoint registers */ +#define PT_PMD 0x4000 /* performance monitoring counters */ #endif /* _ASM_IA64_PTRACE_OFFSETS_H */ diff -urN linux-davidm/include/asm-ia64/sal.h linux-2.4.0-test9-lia/include/asm-ia64/sal.h --- linux-davidm/include/asm-ia64/sal.h Thu Jun 22 07:09:45 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/sal.h Wed Oct 4 21:50:21 2000 @@ -17,6 +17,7 @@ */ #include +#include #include #include @@ -158,12 +159,22 @@ char reserved2[8]; }; -struct ia64_sal_desc_ptc { +typedef struct ia64_sal_desc_ptc { char type; char reserved1[3]; unsigned int num_domains; /* # of coherence domains */ - long domain_info; /* physical address of domain info table */ -}; + s64 domain_info; /* physical address of domain info table */ +} ia64_sal_desc_ptc_t; + +typedef struct ia64_sal_ptc_domain_info { + unsigned long proc_count; /* number of processors in domain */ + long proc_list; /* physical address of LID array */ +} ia64_sal_ptc_domain_info_t; + +typedef struct ia64_sal_ptc_domain_proc_entry { + unsigned char id; /* id of processor */ + unsigned char eid; /* eid of processor */ +} ia64_sal_ptc_domain_proc_entry_t; #define IA64_SAL_AP_EXTERNAL_INT 0 @@ -175,6 +186,7 @@ }; extern ia64_sal_handler ia64_sal; +extern struct ia64_sal_desc_ptc *ia64_ptc_domain_info; extern const char *ia64_sal_strerror (long status); extern void ia64_sal_init (struct ia64_sal_systab *sal_systab); @@ -387,7 +399,7 @@ * Now define a couple of inline functions for improved type checking * and convenience. */ -extern inline long +static inline long ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second, unsigned long *drift_info) { @@ -400,7 +412,7 @@ } /* Flush all the processor and platform level instruction and/or data caches */ -extern inline s64 +static inline s64 ia64_sal_cache_flush (u64 cache_type) { struct ia64_sal_retval isrv; @@ -411,7 +423,7 @@ /* Initialize all the processor and platform level instruction and data caches */ -extern inline s64 +static inline s64 ia64_sal_cache_init (void) { struct ia64_sal_retval isrv; @@ -422,7 +434,7 @@ /* Clear the processor and platform information logged by SAL with respect to the * machine state at the time of MCA's, INITs or CMCs */ -extern inline s64 +static inline s64 ia64_sal_clear_state_info (u64 sal_info_type, u64 sal_info_sub_type) { struct ia64_sal_retval isrv; @@ -434,7 +446,7 @@ /* Get the processor and platform information logged by SAL with respect to the machine * state at the time of the MCAs, INITs or CMCs. */ -extern inline u64 +static inline u64 ia64_sal_get_state_info (u64 sal_info_type, u64 sal_info_sub_type, u64 *sal_info) { struct ia64_sal_retval isrv; @@ -446,7 +458,7 @@ /* Get the maximum size of the information logged by SAL with respect to the machine * state at the time of MCAs, INITs or CMCs */ -extern inline u64 +static inline u64 ia64_sal_get_state_info_size (u64 sal_info_type, u64 sal_info_sub_type) { struct ia64_sal_retval isrv; @@ -459,7 +471,7 @@ /* Causes the processor to go into a spin loop within SAL where SAL awaits a wakeup * from the monarch processor. */ -extern inline s64 +static inline s64 ia64_sal_mc_rendez (void) { struct ia64_sal_retval isrv; @@ -471,7 +483,7 @@ * the machine check rendezvous sequence as well as the mechanism to wake up the * non-monarch processor at the end of machine check processing. */ -extern inline s64 +static inline s64 ia64_sal_mc_set_params (u64 param_type, u64 i_or_m, u64 i_or_m_val, u64 timeout) { struct ia64_sal_retval isrv; @@ -480,7 +492,7 @@ } /* Read from PCI configuration space */ -extern inline s64 +static inline s64 ia64_sal_pci_config_read (u64 pci_config_addr, u64 size, u64 *value) { struct ia64_sal_retval isrv; @@ -503,7 +515,7 @@ } /* Write to PCI configuration space */ -extern inline s64 +static inline s64 ia64_sal_pci_config_write (u64 pci_config_addr, u64 size, u64 value) { struct ia64_sal_retval isrv; @@ -527,7 +539,7 @@ * Register physical addresses of locations needed by SAL when SAL * procedures are invoked in virtual mode. */ -extern inline s64 +static inline s64 ia64_sal_register_physical_addr (u64 phys_entry, u64 phys_addr) { struct ia64_sal_retval isrv; @@ -539,7 +551,7 @@ * or entry points where SAL will pass control for the specified event. These event * handlers are for the bott rendezvous, MCAs and INIT scenarios. */ -extern inline s64 +static inline s64 ia64_sal_set_vectors (u64 vector_type, u64 handler_addr1, u64 gp1, u64 handler_len1, u64 handler_addr2, u64 gp2, u64 handler_len2) @@ -552,7 +564,7 @@ return isrv.status; } /* Update the contents of PAL block in the non-volatile storage device */ -extern inline s64 +static inline s64 ia64_sal_update_pal (u64 param_buf, u64 scratch_buf, u64 scratch_buf_size, u64 *error_code, u64 *scratch_buf_size_needed) { diff -urN linux-davidm/include/asm-ia64/semaphore.h linux-2.4.0-test9-lia/include/asm-ia64/semaphore.h --- linux-davidm/include/asm-ia64/semaphore.h Fri Apr 21 15:21:24 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/semaphore.h Wed Oct 4 21:50:28 2000 @@ -39,7 +39,7 @@ #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1) #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0) -extern inline void +static inline void sema_init (struct semaphore *sem, int val) { *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val); @@ -68,7 +68,7 @@ * Atomically decrement the semaphore's count. If it goes negative, * block the calling thread in the TASK_UNINTERRUPTIBLE state. */ -extern inline void +static inline void down (struct semaphore *sem) { #if WAITQUEUE_DEBUG @@ -82,7 +82,7 @@ * Atomically decrement the semaphore's count. If it goes negative, * block the calling thread in the TASK_INTERRUPTIBLE state. */ -extern inline int +static inline int down_interruptible (struct semaphore * sem) { int ret = 0; @@ -95,7 +95,7 @@ return ret; } -extern inline int +static inline int down_trylock (struct semaphore *sem) { int ret = 0; @@ -108,7 +108,7 @@ return ret; } -extern inline void +static inline void up (struct semaphore * sem) { #if WAITQUEUE_DEBUG @@ -181,7 +181,7 @@ extern void __down_write_failed (struct rw_semaphore *sem, long count); extern void __rwsem_wake (struct rw_semaphore *sem, long count); -extern inline void +static inline void init_rwsem (struct rw_semaphore *sem) { sem->count = RW_LOCK_BIAS; @@ -196,7 +196,7 @@ #endif } -extern inline void +static inline void down_read (struct rw_semaphore *sem) { long count; @@ -218,7 +218,7 @@ #endif } -extern inline void +static inline void down_write (struct rw_semaphore *sem) { long old_count, new_count; @@ -252,7 +252,7 @@ * case is when there was a writer waiting, and we've * bumped the count to 0: we must wake the writer up. */ -extern inline void +static inline void __up_read (struct rw_semaphore *sem) { long count; @@ -271,7 +271,7 @@ * Releasing the writer is easy -- just release it and * wake up any sleepers. */ -extern inline void +static inline void __up_write (struct rw_semaphore *sem) { long old_count, new_count; @@ -290,7 +290,7 @@ __rwsem_wake(sem, new_count); } -extern inline void +static inline void up_read (struct rw_semaphore *sem) { #if WAITQUEUE_DEBUG @@ -303,7 +303,7 @@ __up_read(sem); } -extern inline void +static inline void up_write (struct rw_semaphore *sem) { #if WAITQUEUE_DEBUG diff -urN linux-davidm/include/asm-ia64/siginfo.h linux-2.4.0-test9-lia/include/asm-ia64/siginfo.h --- linux-davidm/include/asm-ia64/siginfo.h Thu Aug 24 08:17:47 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/siginfo.h Wed Oct 4 21:50:51 2000 @@ -235,7 +235,8 @@ #ifdef __KERNEL__ #include -extern inline void copy_siginfo(siginfo_t *to, siginfo_t *from) +static inline void +copy_siginfo (siginfo_t *to, siginfo_t *from) { if (from->si_code < 0) memcpy(to, from, sizeof(siginfo_t)); diff -urN linux-davidm/include/asm-ia64/smp.h linux-2.4.0-test9-lia/include/asm-ia64/smp.h --- linux-davidm/include/asm-ia64/smp.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/smp.h Wed Oct 4 21:51:16 2000 @@ -49,7 +49,7 @@ * Function to map hard smp processor id to logical id. Slow, so * don't use this in performance-critical code. */ -extern __inline__ int +static inline int cpu_logical_id (int cpuid) { int i; @@ -68,28 +68,28 @@ * max_xtp : never deliver interrupts to this CPU. */ -extern __inline__ void +static inline void min_xtp(void) { if (smp_int_redirect & SMP_IRQ_REDIRECTION) writeb(0x00, ipi_base_addr | XTP_OFFSET); /* XTP to min */ } -extern __inline__ void +static inline void normal_xtp(void) { if (smp_int_redirect & SMP_IRQ_REDIRECTION) writeb(0x08, ipi_base_addr | XTP_OFFSET); /* XTP normal */ } -extern __inline__ void +static inline void max_xtp(void) { if (smp_int_redirect & SMP_IRQ_REDIRECTION) writeb(0x0f, ipi_base_addr | XTP_OFFSET); /* Set XTP to max */ } -extern __inline__ unsigned int +static inline unsigned int hard_smp_processor_id(void) { struct { diff -urN linux-davidm/include/asm-ia64/spinlock.h linux-2.4.0-test9-lia/include/asm-ia64/spinlock.h --- linux-davidm/include/asm-ia64/spinlock.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/spinlock.h Wed Oct 4 21:51:32 2000 @@ -63,8 +63,8 @@ }) #define spin_is_locked(x) ((x)->lock != 0) -#define spin_unlock(x) ({((spinlock_t *) x)->lock = 0;}) -#define spin_unlock_wait(x) ({ while ((x)->lock); }) +#define spin_unlock(x) do {((spinlock_t *) x)->lock = 0;} while (0) +#define spin_unlock_wait(x) do {} while ((x)->lock) #else /* !NEW_LOCK */ @@ -97,9 +97,9 @@ :: "r"(&(x)->lock) : "r2", "r29", "memory") #define spin_is_locked(x) ((x)->lock != 0) -#define spin_unlock(x) ({((spinlock_t *) x)->lock = 0; barrier();}) +#define spin_unlock(x) do {((spinlock_t *) x)->lock = 0; barrier(); } while (0) #define spin_trylock(x) (cmpxchg_acq(&(x)->lock, 0, 1) = 0) -#define spin_unlock_wait(x) ({ do { barrier(); } while ((x)->lock); }) +#define spin_unlock_wait(x) do { barrier(); } while ((x)->lock) #endif /* !NEW_LOCK */ @@ -146,16 +146,16 @@ "movl r29 = 0x80000000\n" \ ";;\n" \ "1:\n" \ - "ld4 r2 = %0\n" \ + "ld4 r2 = [%0]\n" \ ";;\n" \ "cmp4.eq p0,p7 = r0,r2\n" \ "(p7) br.cond.spnt.few 1b \n" \ - IA64_SEMFIX"cmpxchg4.acq r2 = %0, r29, ar.ccv\n" \ + IA64_SEMFIX"cmpxchg4.acq r2 = [%0], r29, ar.ccv\n" \ ";;\n" \ "cmp4.eq p0,p7 = r0, r2\n" \ "(p7) br.cond.spnt.few 1b\n" \ ";;\n" \ - :: "m" __atomic_fool_gcc((rw)) : "r2", "r29", "memory"); \ + :: "r"(rw) : "r2", "r29", "memory"); \ } while(0) /* diff -urN linux-davidm/include/asm-ia64/system.h linux-2.4.0-test9-lia/include/asm-ia64/system.h --- linux-davidm/include/asm-ia64/system.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/system.h Thu Oct 5 00:20:25 2000 @@ -38,6 +38,7 @@ #ifndef __ASSEMBLY__ +#include #include struct pci_vector_struct { @@ -67,7 +68,7 @@ __u64 initrd_size; } ia64_boot_param; -extern inline void +static inline void ia64_insn_group_barrier (void) { __asm__ __volatile__ (";;" ::: "memory"); @@ -98,6 +99,16 @@ #define mb() __asm__ __volatile__ ("mf" ::: "memory") #define rmb() mb() #define wmb() mb() + +#ifdef CONFIG_SMP +# define smp_mb() mb() +# define smp_rmb() rmb() +# define smp_wmb() wmb() +#else +# define smp_mb() barrier() +# define smp_rmb() barrier() +# define smp_wmb() barrier() +#endif /* * XXX check on these---I suspect what Linus really wants here is diff -urN linux-davidm/include/asm-ia64/uaccess.h linux-2.4.0-test9-lia/include/asm-ia64/uaccess.h --- linux-davidm/include/asm-ia64/uaccess.h Wed Oct 4 23:20:21 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/uaccess.h Wed Oct 4 21:51:49 2000 @@ -61,7 +61,7 @@ #define __access_ok(addr,size,segment) (((unsigned long) (addr)) <= (segment).seg) #define access_ok(type,addr,size) __access_ok((addr),(size),get_fs()) -extern inline int +static inline int verify_area (int type, const void *addr, unsigned long size) { return access_ok(type,addr,size) ? 0 : -EFAULT; diff -urN linux-davidm/include/asm-ia64/unaligned.h linux-2.4.0-test9-lia/include/asm-ia64/unaligned.h --- linux-davidm/include/asm-ia64/unaligned.h Sun Feb 6 18:42:40 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/unaligned.h Wed Oct 4 21:52:08 2000 @@ -22,42 +22,42 @@ struct __una_u32 { __u32 x __attribute__((packed)); }; struct __una_u16 { __u16 x __attribute__((packed)); }; -extern inline unsigned long +static inline unsigned long __uldq (const unsigned long * r11) { const struct __una_u64 *ptr = (const struct __una_u64 *) r11; return ptr->x; } -extern inline unsigned long +static inline unsigned long __uldl (const unsigned int * r11) { const struct __una_u32 *ptr = (const struct __una_u32 *) r11; return ptr->x; } -extern inline unsigned long +static inline unsigned long __uldw (const unsigned short * r11) { const struct __una_u16 *ptr = (const struct __una_u16 *) r11; return ptr->x; } -extern inline void +static inline void __ustq (unsigned long r5, unsigned long * r11) { struct __una_u64 *ptr = (struct __una_u64 *) r11; ptr->x = r5; } -extern inline void +static inline void __ustl (unsigned long r5, unsigned int * r11) { struct __una_u32 *ptr = (struct __una_u32 *) r11; ptr->x = r5; } -extern inline void +static inline void __ustw (unsigned long r5, unsigned short * r11) { struct __una_u16 *ptr = (struct __una_u16 *) r11; diff -urN linux-davidm/include/asm-ia64/unistd.h linux-2.4.0-test9-lia/include/asm-ia64/unistd.h --- linux-davidm/include/asm-ia64/unistd.h Wed Sep 13 18:25:40 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/unistd.h Wed Oct 4 21:52:16 2000 @@ -93,7 +93,7 @@ #define __NR_setpriority 1102 #define __NR_statfs 1103 #define __NR_fstatfs 1104 -#define __NR_ioperm 1105 +/* unused; used to be __NR_ioperm */ #define __NR_semget 1106 #define __NR_semop 1107 #define __NR_semctl 1108 diff -urN linux-davidm/include/asm-ia64/unwind.h linux-2.4.0-test9-lia/include/asm-ia64/unwind.h --- linux-davidm/include/asm-ia64/unwind.h Thu Jun 22 07:09:45 2000 +++ linux-2.4.0-test9-lia/include/asm-ia64/unwind.h Wed Oct 4 21:52:27 2000 @@ -52,36 +52,38 @@ unsigned int flags; short hint; short prev_script; - unsigned long bsp; - unsigned long sp; /* stack pointer */ - unsigned long psp; /* previous sp */ - unsigned long ip; /* instruction pointer */ - unsigned long pr_val; /* current predicates */ - unsigned long *cfm; + + /* current frame info: */ + unsigned long bsp; /* backing store pointer value */ + unsigned long sp; /* stack pointer value */ + unsigned long psp; /* previous sp value */ + unsigned long ip; /* instruction pointer value */ + unsigned long pr; /* current predicate values */ + unsigned long *cfm_loc; /* cfm save location (or NULL) */ struct task_struct *task; struct switch_stack *sw; /* preserved state: */ - unsigned long *pbsp; /* previous bsp */ - unsigned long *bspstore; - unsigned long *pfs; - unsigned long *rnat; - unsigned long *rp; - unsigned long *pri_unat; - unsigned long *unat; - unsigned long *pr; - unsigned long *lc; - unsigned long *fpsr; + unsigned long *bsp_loc; /* previous bsp save location */ + unsigned long *bspstore_loc; + unsigned long *pfs_loc; + unsigned long *rnat_loc; + unsigned long *rp_loc; + unsigned long *pri_unat_loc; + unsigned long *unat_loc; + unsigned long *pr_loc; + unsigned long *lc_loc; + unsigned long *fpsr_loc; struct unw_ireg { unsigned long *loc; struct unw_ireg_nat { - int type : 3; /* enum unw_nat_type */ - signed int off; /* NaT word is at loc+nat.off */ + long type : 3; /* enum unw_nat_type */ + signed long off : 61; /* NaT word is at loc+nat.off */ } nat; } r4, r5, r6, r7; - unsigned long *b1, *b2, *b3, *b4, *b5; - struct ia64_fpreg *f2, *f3, *f4, *f5, *fr[16]; + unsigned long *b1_loc, *b2_loc, *b3_loc, *b4_loc, *b5_loc; + struct ia64_fpreg *f2_loc, *f3_loc, *f4_loc, *f5_loc, *fr_loc[16]; }; /* @@ -140,19 +142,56 @@ */ extern int unw_unwind_to_user (struct unw_frame_info *info); -#define unw_get_ip(info,vp) ({*(vp) = (info)->ip; 0;}) -#define unw_get_sp(info,vp) ({*(vp) = (unsigned long) (info)->sp; 0;}) -#define unw_get_psp(info,vp) ({*(vp) = (unsigned long) (info)->psp; 0;}) -#define unw_get_bsp(info,vp) ({*(vp) = (unsigned long) (info)->bsp; 0;}) -#define unw_get_cfm(info,vp) ({*(vp) = *(info)->cfm; 0;}) -#define unw_set_cfm(info,val) ({*(info)->cfm = (val); 0;}) +#define unw_is_intr_frame(info) (((info)->flags & UNW_FLAG_INTERRUPT_FRAME) != 0) + +static inline unsigned long +unw_get_ip (struct unw_frame_info *info, unsigned long *valp) +{ + *valp = (info)->ip; + return 0; +} + +static inline unsigned long +unw_get_sp (struct unw_frame_info *info, unsigned long *valp) +{ + *valp = (info)->sp; + return 0; +} + +static inline unsigned long +unw_get_psp (struct unw_frame_info *info, unsigned long *valp) +{ + *valp = (info)->psp; + return 0; +} + +static inline unsigned long +unw_get_bsp (struct unw_frame_info *info, unsigned long *valp) +{ + *valp = (info)->bsp; + return 0; +} + +static inline unsigned long +unw_get_cfm (struct unw_frame_info *info, unsigned long *valp) +{ + *valp = *(info)->cfm_loc; + return 0; +} + +static inline unsigned long +unw_set_cfm (struct unw_frame_info *info, unsigned long val) +{ + *(info)->cfm_loc = val; + return 0; +} static inline int unw_get_rp (struct unw_frame_info *info, unsigned long *val) { - if (!info->rp) + if (!info->rp_loc) return -1; - *val = *info->rp; + *val = *info->rp_loc; return 0; } diff -urN linux-davidm/kernel/Makefile linux-2.4.0-test9-lia/kernel/Makefile --- linux-davidm/kernel/Makefile Thu Aug 10 19:56:32 2000 +++ linux-2.4.0-test9-lia/kernel/Makefile Wed Oct 4 21:53:44 2000 @@ -30,6 +30,13 @@ OX_OBJS += pm.o endif +ifneq ($(CONFIG_IA64),y) +# According to Alan Modra , the -fno-omit-frame-pointer is +# needed for x86 only. Why this used to be enabled for all architectures is beyond +# me. I suspect most platforms don't need this, but until we know that for sure +# I turn this off for IA-64 only. Andreas Schwab says it's also needed on m68k +# to get a correct value for the wait-channel (WCHAN in ps). --davidm CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer +endif include $(TOPDIR)/Rules.make